对于文件中文件系统的简单C项目,我必须创建一个用于编写分区表的命令。它只包含分区数和大小,非常简单。
它应该像mk_part -s size [-s size ...] [name]
一样工作。
[name]
是磁盘的文件名,它是可选的,因为提供了默认的文件。
我不太了解getopt_long(和getopt),但我读到的只是我在一段时间内获得选项,所以我的两种处理方式是:
对于第一个选择,困难在于我不知道分区的数量。但我仍然可以通过argc或更好的(argc-1)/ 2对这个数字进行处理,这样就可以了。
对于第二种选择,我不知道要写哪个文件。
那么获取所有这些参数的最佳替代方法是什么?如何获得此选项名称?
答案 0 :(得分:2)
getopt
可以很好地处理重复和可选的args。对于重复的args,每次getopt
的调用都会给你下一个arg。 getopt
并不关心它是否重复。对于最后的arg,只需要在解析所有选项后检查它的存在。下面是从getopt
手册页中的示例修改的代码,用于处理您的场景:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int
main(int argc, char *argv[])
{
int opt;
while ((opt = getopt(argc, argv, "s:")) != -1) {
switch (opt) {
case 's':
printf("size=%d\n", atoi(optarg));
break;
default: /* '?' */
exit(EXIT_FAILURE);
}
}
if (optind < argc) {
printf("name=%s\n", argv[optind]);
} else {
printf("optional name arg not present\n");
}
exit(EXIT_SUCCESS);
}
以下是程序的一些示例运行,显示它处理重复的选项和最后的arg。
$ ./a.out -s 10 -s 20 -s 30
size=10
size=20
size=30
optional name arg not present
$ ./a.out -s 1 my_name
size=1
name=my_name
答案 1 :(得分:0)
我认为你是在思考这个问题。我知道尝试避免使用malloc总是很诱人,但选项解析的效率永远不会(*)很重要。您只需解析一次选项,并以初始化新进程,查找可执行文件,链接和加载它以及启动命令的所有其余过程为代价,解析选项所需的时间可能不是噪音
所以尽可能以最简单的方式做到这一点。这是一个可能的大纲:
int main(int argc, char* argv) {
/* These variables describe the options */
int nparts = 0; // Number of partitions
unsigned long* parts = NULL; // Array of partitions (of size nparts)
const char* diskname="/the/default/name"; // Disk's filename
for (;;) {
switch (getopt(argc, argv, "s:")) {
case '?':
/* Print usage message */
exit(1);
case 's':
/* Some error checking missing */
parts = realloc(parts, ++nparts * sizeof *parts);
parts[nparts - 1] = strtoul(optarg, NULL, 0);
continue;
case -1:
break;
}
break;
}
if (optind < argc) diskname = argv[optind++];
if (optind != argc) {
/* print error message */
exit(1);
}
return do_partitions(diskname, parts, nparts);
}
上面的代码缺少很多错误检查和其他细节,但它很简短。它只是在每次找到新大小时重新分配分区数组。 (这可能不像你想象的那么糟糕,因为realloc本身可能足够聪明,能够以指数方式增加分配大小。但即使它很糟糕,它也不会经常发生,甚至不会注意到。)
使用continue
和break
的技巧是将开关嵌套在for中的常用方法。在切换中,continue
将继续for循环,而break
将突破切换;因为所有不终止for循环continue
的开关动作,所以切换块后面的任何内容仅针对明确break
s的切换动作执行。因此,break
块之后的switch
会在切换操作执行break
的情况下中断for循环。
在调用执行重新分区的函数之前,您可能需要检查是否至少定义了一个分区大小。