prev up next   top/contents search

comp.lang.c FAQ 列表· 第 20.3 题

我如何打开命令行中提到的文件,并解析选项标志?


这是一个实现了传统 Unix 风格的骨架argv解析,处理以-开头的选项标志,以及可选的文件名。(此示例接受的两个标志是-a-b; -b接受一个参数。)

#include <stdio.h>
#include <string.h>
#include <errno.h>

main(int argc, char *argv[])
{
	int argi;
	int aflag = 0;
	char *bval = NULL;

	for(argi = 1; argi < argc && argv[argi][0] == '-'; argi++) {
		char *p;
		for(p = &argv[argi][1]; *p != '\0'; p++) {
			switch(*p) {
			case 'a':
				aflag = 1;
				printf("-a seen\n");
				break;

			case 'b':
				bval = argv[++argi];
				printf("-b seen (\"%s\")\n", bval);
				break;

			default:
				fprintf(stderr,
					"unknown option -%c\n", *p);
			}
		}
	}

	if(argi >= argc) {
		/* no filename arguments; process stdin */
		printf("processing standard input\n");
	} else {
		/* process filename arguments */

		for(; argi < argc; argi++) {
			FILE *ifp = fopen(argv[argi], "r");
			if(ifp == NULL) {
				fprintf(stderr, "can't open %s: %s\n",
					argv[argi], strerror(errno));
				continue;
			}

			printf("processing %s\n", argv[argi]);

			fclose(ifp);
		}
	}

	return 0;
}
(此代码假定fopen在失败时会设置errno,这并非绝对保证,但通常有效,并且能使错误消息更有用。另请参阅问题 20.4。)

有几种现成的函数可用于以标准方式进行命令行解析;最流行的函数是getopt(另请参阅问题 18.16)。以上示例已重写为使用getopt:

extern char *optarg;
extern int optind;

main(int argc, char *argv[])
{
	int aflag = 0;
	char *bval = NULL;
	int c;

	while((c = getopt(argc, argv, "ab:")) != -1)
		switch(c) {
		case 'a':
			aflag = 1;
			printf("-a seen\n");
			break;

		case 'b':
			bval = optarg;
			printf("-b seen (\"%s\")\n", bval);
			break;
	}

	if(optind >= argc) {
		/* no filename arguments; process stdin */
		printf("processing standard input\n");
	} else {
		/* process filename arguments */

		for(; optind < argc; optind++) {
			FILE *ifp = fopen(argv[optind], "r");
			if(ifp == NULL) {
				fprintf(stderr, "can't open %s: %s\n",
					argv[optind], strerror(errno));
				continue;
			}

			printf("processing %s\n", argv[optind]);

			fclose(ifp);
		}
	}

	return 0;
}

上述示例忽略了一些细微之处:单个“-”通常被解释为“读取标准输入”;标记“--”通常表示选项的结束(正确实现的getopt会处理这种情况);当命令因参数不正确或缺失而调用时,打印用法消息是传统做法。

如果您想知道argv在内存中的布局,它实际上是一个“不规则数组”;请参阅问题 20.2 中的图片。另请参阅问题 8.213.719.20

参考资料:K&R1 第 5.11 节 pp. 110-114
K&R2 第 5.10 节 pp. 114-118
ISO 第 5.1.2.2.1 节
H&S 第 20.1 节 p. 416
PCS 第 5.6 节 pp. 81-2,第 11 节 p. 159,pp. 339-40 附录 F
Schumacher 编,《C 语言软件解决方案》第 4 节 pp. 75-85


prev up next   contents search
关于此 FAQ 列表   关于 Eskimo   搜索   反馈   版权

Eskimo North 托管