使用指针迭代遍历argv[]

7

我想使用以下代码,但不想使用“[][]”来索引数组,而是用指针来替代它。

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

我知道你可以使用指针遍历数组,但是我不确定如何处理第二个数组的未定义长度,在这种情况下,即从输入中获取的字符串。由于argv[]的每个元素可能具有不同的长度,因此我希望确保我可以正确读取字符并知道每个argv[]元素何时结束以及下一个元素何时开始。

我期望它应该像这样:(如果下面的主标题是错误的,请告诉我。)

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;
    }
}

2
你似乎假定argv是一段连续的内存块,但我认为这并不安全。 - Carey Gregory
1
@CareyGregory - 是正确的。你不能简单地假设下一个元素紧跟着空字节。但你可以安全地假设每个元素的尺寸相同,因此可以安全地假设元素是从 argvargv + argc - 1 - alvits
6个回答

6

考虑到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

如果它们被声明,main函数的参数应遵守以下限制:

— argc的值应为非负数。

— argv[argc]应为空指针。


5
自从 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 [] []中的每个单独的子数组。由于所有内容都被视为线性1D数组,因此应该可以在没有argc的情况下进行迭代。其中一部分是找到行的末尾,因此外部循环将是“\n”。 - Blake Lassiter
2
@BlakeLassiter 谁说它都是线性的1D数组了? - Carey Gregory

3
#include <stdio.h>
int main(int argc, char **argv)
{
    printf("%i\n",argc);
    while (*argv != NULL) {
        printf("%s\n",*argv);
        argv++;
    }
    return 1;
}

2
你应该解释你的代码,而不是只发布代码答案。 - M.M

2

您可以使用指针遍历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));
    }
}

1
你可以使用任何 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++ - alvits
@CareyGregory 这只是一个嵌套循环的示例,请注意问题是关于嵌套循环,而不是关于“如何打印序列”。我所做的是使用printf代替//code行。 - DMaster

-1
请注意,argv[]本质上是一个指针数组,这意味着*(argv+i)将会在基地址(在这种情况下为argv)上加上i *指针大小,并将其转换为指向字符串的指针。然后,您可以随意操作每个指向字符串的指针。以下代码是打印出argv中所有字符串的示例:
int main(int argc, char *argv[]){
     int i;
     for(i = 0; i < argc; i++)
         printf("%s\n", *(argv+i));
     return 0;
}

1
这里使用for循环有什么意义,当它在第一次遍历时就会遍历所有的argv。那么接下来的遍历会做什么呢?会导致段错误吗? - alvits
感谢 @alvits 的指出。我先前回答中的 while 循环存在易错问题。我已经进行了更新。 - lordofire

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接