【问题标题】:Using pointers to iterate through argv[]使用指针遍历 argv[]
【发布时间】:2019-09-13 12:50:11
【问题描述】:

我想使用以下代码,但不使用“[][]”索引数组并用指针替换它

for (int i = 0; i < argc; i++) {
    for (int j = 0; argv[i][j] != '\0'; j++) {
        //code
    }
}

我知道您可以使用指针来遍历数组,但我不确定如何使用第二个数组中未定义的长度来执行此操作,在本例中是来自输入的字符串。由于 argv[] 的每个元素可以有不同的长度,我想确保我可以正确读取字符并知道 argv[] 的每个元素何时结束,下一个开始。

我希望它是这样的:(如果 main 的以下标题有误,请告诉我。)

int main(int argc, char **argv) {
    for (int i = 0; i < argc; i++) {
        while(argv != '\0') {
            //code
            *argv+1;
        }
        //to skip null character
        argv+1;
    }
}

【问题讨论】:

  • 您似乎假设argv 是一个连续的内存块。我不认为这是一个安全的假设。
  • @CareyGregory - 是对的。您不能简单地假设下一个元素就在空字节之后。但是您可以放心地假设每个元素的大小相同,因此可以安全地假设元素从 argvargv + argc - 1

标签: c arrays argv


【解决方案1】:

鉴于argv 中的最后一个元素是NULL,如果您真的不想这样做,则无需对其进行索引或与argc 进行比较。

int main(int argc, char *argv[]) {
  for (char **arg = argv; *arg; ++arg) { // for each arg
    for (char *p = *arg; *p; ++p) {      // for each character
      process(*p);
    }
  }
}

*arg 将是 NULL 在参数列表的末尾,这是错误的。 *p 将是 '\0' 在每个字符串的末尾,这是错误的。

从 N1256 5.1.2.2.1/2

如果它们被声明,主函数的参数应遵守以下约束:

— argc 的值应为非负数。

——argv[argc] 应该是一个空指针。

【讨论】:

    【解决方案2】:

    由于for 循环允许任何类型的值,不一定是整数作为“循环索引”,您的循环可以这样重写:

    for (char **a = argv ; a != argv+argc ; a++) {
        for(char *p = *a ; *p != '\0' ; p++) {
            // code uses *p instead of argv[i][j]
        }
    }
    

    内部循环使用p作为循环变量,使用常规p++递增,并使用*p != '\0'进行检查。循环条件可以缩短为*p,所以内部循环看起来像这样:

    for(char *p = *a ; *p ; p++)
    

    【讨论】:

    • 如何消除使用 argv[i] 的索引?也许我应该删除上面的 for 循环,让它更清楚。您所写的内容将从 argv[][] 转到每个单独的子数组。由于它都被视为线性一维数组,因此我认为应该可以在没有 argc 的情况下进行迭代。其中一部分是找到行尾,因此外循环将是 "\n"
    • @BlakeLassiter 谁说这都是线性一维数组?
    【解决方案3】:

    是的,您可以使用指针遍历 argv

    内部循环告诉p 指向argv+i 的开头并遍历它直到到达\0

    #include <stdio.h>
    int main(int argc, char **argv) {
        int i;
        char *p;
        for(i=0; i < argc; i++) {
            for(p=*(argv+i); *p; p++)
                printf("%c", *p);
            printf("\n");
        }
    }
    

    如果你只对遍历每个参数感兴趣,而不对解析每个字符感兴趣,那么你可以简单地。

    #include <stdio.h>
    int main(int argc, char **argv) {
        int i;
        char *p;
        for(i=0; i < argc; i++) {
            printf("Argument position %d is %s\n", i, *(argv+i));
        }
    }
    

    【讨论】:

      【解决方案4】:
      #include <stdio.h>
      int main(int argc, char **argv)
      {
          printf("%i\n",argc);
          while (*argv != NULL) {
              printf("%s\n",*argv);
              argv++;
          }
          return 1;
      }
      

      【讨论】:

      • 您应该解释您的代码,而不是发布仅代码的答案
      【解决方案5】:

      您可以使用任何any_t * 来迭代任何any_t[],在这种情况下:

      int main(int argc, char **argv) {
      
        char **i = argv; //iterator of argv
        char **e = argv + argc; //end of argv
      
        for(; i != e; ++i) {
      
          char *j = *i; //iterator of *i
      
          //condition: *j mean *j != 0
          for(; *j; ++j) {
            printf("%c", *j);
          }
      
          printf("\n");
      
        }
      
        return 0;
      
      }
      

      【讨论】:

      • 好答案。但 OP 要求的是 c 而不是 c++
      • @CareyGregory 这只是嵌套循环的一个例子,请注意问题是关于嵌套循环,而不是关于“如何打印序列”。我所做的是使用printf 而不是//code
      【解决方案6】:

      请记住,argv[] 本质上是一个指针数组,这意味着 *(argv+i) 会将 i * 指针大小添加到基地址(在本例中为 argv)并将其威慑为指针到一个字符串。然后,您可以随意操纵每个指向字符串的指针。以下代码是打印出 argv 中所有字符串的示例:

      int main(int argc, char *argv[]){
           int i;
           for(i = 0; i < argc; i++)
               printf("%s\n", *(argv+i));
           return 0;
      }
      

      【讨论】:

      • for 循环在这里的意义何在,它将在第一遍遍历所有argv。接下来的传球会做什么? SEGFAULT?
      • 感谢@alvits 指出。我之前的答案中的 while 循环很容易出错。我已经更新了我的答案。
      猜你喜欢
      • 2021-03-19
      • 2023-02-13
      • 2021-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-29
      • 1970-01-01
      相关资源
      最近更新 更多