首页 > 解决方案 > 如何从命令行获取文件名

问题描述

我知道以前曾在 Stack Overflow 上提出过这种性质的问题,但即使在阅读了一些线程 ( 1 )( 2 )之后,我也无法取得成功。

我正在编写一个 C 函数,它将读取指定为命令行参数的文件名。但我也有空间放置文件名之前的一个可选参数。

示例执行(这三个调用相互独立):

./my_program -a foo.txt  // Standalone example #1
./my_program -b foo.txt  // Standalone example #2
./my_program foo.txt  // Standalone example #3

我的代码:

int main(int argc, char* argv[]) {

  int aflag = 0;
  int bflag = 0;
  int cflag = 0;
  int option;
  char *filename;

  while ((option = getopt(argc, argv, "abc:")) != -1) {
    switch (option) {
    case 'a':
      aflag = 1;
      break;
    case 'b':
      bflag = 1;
      break;
    case 'c':
      cflag = 1;
      break;
    default:
      aflag = 1;  // If no flags are set, use "a"
      break;
    }
  }

  if (argc == 2) {
    filename = argv[1];
  } else if (argc == 3) {
    filename = argv[2];
  }

  printf("Flags: aflag = %d, bflag = %d, cflag = %d\n", aflag, bflag, cflag);
  printf("Got filename = %s\n", filename);

确实适用于具有一个可选参数的情况。

但是,我正在阅读[optind]( 3 ) 并且想知道它的正确用法是什么,以便我可以获得文件名。我似乎无法让它工作,我不知道使用if这样的语句是否是好的风格。

例如,现在此代码仅限于一个可选参数。但是,如果我后来决定添加第二个参数怎么办?那么我上面的代码将不起作用,因为argv文件名所在的索引会发生变化。

有没有办法——大概使用getindgetopt——总是把最后一个参数作为文件名,不管我在它之前指定了多少(可选)参数?

标签: cgetopt

解决方案


从您链接的页面:

如果没有更多选项字符,getopt() 返回 -1。然后 optind 是第一个 argv 元素的 argv 中不是选项的索引。

所以代替

if (argc == 2) {
    filename = argv[1];
  } else if (argc == 3) {
    filename = argv[2];
  }

你只是想要

filename = argv[optind];

请注意,如果在选项之后没有指定任何参数(例如,如果您的程序被简单地调用./my_program -a,那么这将设置filenameNULL,您应该准备相应地处理这个问题。如果您愿意,也可以显式检测这种情况:

if (optind < argc) {
    filename = argv[optind];
} else {
    fprintf(stderr, "Usage: %s -a|-b|-c filename\n", argv[0]);
    exit(2);
}

推荐阅读