(*&&x2B;&x2B;argv)[0]和while之间的差异(c=*&&x2B;&"x2B;argv[0])

(*&&x2B;&x2B;argv)[0]和while之间的差异(c=*&&x2B;&"x2B;argv[0]),c,string,pointers,argv,C,String,Pointers,Argv,我有以下代码片段: int main(int argc, char *argv[]) { char line[MAXLINE]; long lineno = 0; int c, except = 0, number = 0, found = 0; while(--argc > 0 && (*++argv)[0] == '-') //These two lines while(c = *++argv[0])

我有以下代码片段:

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

     char line[MAXLINE];
     long lineno = 0;
     int c, except = 0, number = 0, found = 0;

     while(--argc > 0 && (*++argv)[0] == '-') //These two lines
        while(c = *++argv[0])                 //These two lines
          switch(c) {
             case 'x':
                  except = 1;
                  break;
             case 'n':
                  number = 1;
                  break;
             default:
                  printf("find: illegal option %c\n", c);
                  argc = 0;
                  found = -1;
                  break;
          }

     ...
}

包含以下表达式:

while(--argc > 0 && (*++argv)[0] == '-')
括号
(*++argv)[0]
中的表达式是否与不带括号的(c=*++argv[0])中的表达式不同

如果是,怎么做?
(*++argv)
是否表示指向下一个参数的指针,
*++argv[0]
是否表示指向当前字符数组中指向的下一个字符的指针?

是的,您是正确的

while(--argc > 0 && (*++argv)[0] == '-')
正在逐个扫描命令行参数的数组(长度为argc),查找以
-
选项前缀开头的参数。对于其中每一项:

while(c = *++argv[0])
正在扫描当前参数中第一个
-
后面的一组开关字符(即
-tn
中的
t
n
),直到它到达字符串null终止符
\0
,该终止符终止while循环,因为它的计算结果为false

这种设计既允许

myApp -t -n


要同时工作并被理解为具有选项
t
n

增加argv是一个非常糟糕的主意,因为一旦这样做,就很难恢复原始值。使用整数索引更简单、更清晰、更好——毕竟argv是一个数组


要回答您的问题,++argv递增指针。然后对指针应用间接寻址以获取第一个字符。

是的,这两个表达式有所不同(虽然略有不同)。在我看来,这段代码有点过于聪明了。您最好使用这样的代码:

for (int i=1; i<argc; i++)
    if (argv[i][0] == '-') {
       size_t len = strlen(argv[i]);
       for (int j=0; j<len; ++j)
           switch(argv[i][j]) {
               case 'x':
               // ...
                 +---+         +---+---+---+---+---+
 argv ---------->| 0 |-------->| p | r | o | g | 0 |
                 +---+         +---+---+---+---+---+
                 | 1 |-------->| - | a | b | 0 |
                 +---+         +---+---+---+---+
                 | 2 |-------->| - | c | 0 |
                 +---+         +---+---+---+---+---+---+
                 | 3 |-------->| H | e | l | l | o | 0 |
                 +---+         +---+---+---+---+---+---+
                 | 4 |-------->| W | o | r | l | d | 0 |
                 +---+         +---+---+---+---+---+---+
                 | 5 |-------->NULL
                 +---+

for(int i=1;i括号更改表达式的求值顺序

不带括号
*++argv[0]

  • argv[0]
    获取指向当前由
    argv
    指向的字符数据的指针
  • ++
    递增指向字符数组中下一个字符的指针
  • *
    获取字符
  • 带括号的
    (*++argv)[0]

  • ++argv
    递增argv指针以指向下一个参数
  • *
    将其延迟以获取指向字符数据的指针
  • [0]
    获取字符数组中的第一个字符

  • 首先,K&R有一个关于这个特定片段的勘误表:

    117(§5.10):在find示例中,程序递增
    argv[0]
    。这不是特别禁止的,但也不是特别允许的

    现在来解释一下

    假设您的程序名为
    prog
    ,您使用以下命令执行它:
    prog-ab-c Hello World
    。您希望能够解析参数,说明指定了选项
    a
    b
    c
    ,并且
    Hello
    World
    是非选项参数

    argv
    属于
    char**
    类型-请记住,函数中的数组参数与指针相同。在程序调用时,情况如下所示:

    for (int i=1; i<argc; i++)
        if (argv[i][0] == '-') {
           size_t len = strlen(argv[i]);
           for (int j=0; j<len; ++j)
               switch(argv[i][j]) {
                   case 'x':
                   // ...
    
                     +---+         +---+---+---+---+---+
     argv ---------->| 0 |-------->| p | r | o | g | 0 |
                     +---+         +---+---+---+---+---+
                     | 1 |-------->| - | a | b | 0 |
                     +---+         +---+---+---+---+
                     | 2 |-------->| - | c | 0 |
                     +---+         +---+---+---+---+---+---+
                     | 3 |-------->| H | e | l | l | o | 0 |
                     +---+         +---+---+---+---+---+---+
                     | 4 |-------->| W | o | r | l | d | 0 |
                     +---+         +---+---+---+---+---+---+
                     | 5 |-------->NULL
                     +---+
    
    这里,
    argc
    是5,
    argv[argc]
    NULL
    。开始时,
    argv[0]
    是一个
    char*
    字符,包含字符串
    “prog”

    (*++argv)[0]
    中,由于括号的原因,
    argv
    首先递增,然后取消引用。递增的效果是将
    argv------>
    箭头向下移动一个块,指向
    1
    。取消引用的效果是获取指向第一个命令行参数
    -ab
    的指针。最后,我们获取该字符串的
    (*++argv)[0]
    )中的第一个字符(
    [0]
    ),并测试它是否为
    '-'
    ,因为这表示选项的开始

    对于第二个构造,我们实际上希望遍历当前
    argv[0]
    指针指向的字符串。因此,我们需要将
    argv[0]
    视为指针,忽略其第一个字符(即刚才测试的
    '-'
    ),然后查看其他字符:

    ++(argv[0])
    将递增
    argv[0]
    ,以获取指向第一个非
    -
    字符的指针,取消对它的引用将给出该字符的值。因此我们得到
    *++(argv[0])
    。但是在C中,
    []
    绑定比
    ++
    更紧密,我们实际上可以去掉括号,将表达式设为
    *++argv[0]
    。我们希望继续处理此字符,直到它成为
    0
    (上图中每行的最后一个字符框)

    表情

    c = *++argv[0]
    
    将当前选项的值分配给
    c
    ,并具有值
    c
    while(c)
    while(c!=0)
    的缩写,因此
    while(c=*++argv[0])
    line基本上是将当前选项的值赋给
    c
    ,并对其进行测试,以查看是否已到达当前命令行参数的末尾

    在此循环结束时,argv将指向第一个非选项参数:

                     +---+         +---+---+---+---+---+
                     | 0 |-------->| p | r | o | g | 0 |
                     +---+         +---+---+---+---+---+
                     | 1 |-------->| - | a | b | 0 |
                     +---+         +---+---+---+---+
                     | 2 |-------->| - | c | 0 |
                     +---+         +---+---+---+---+---+---+
     argv ---------->| 3 |-------->| H | e | l | l | o | 0 |
                     +---+         +---+---+---+---+---+---+
                     | 4 |-------->| W | o | r | l | d | 0 |
                     +---+         +---+---+---+---+---+---+
                     | 5 |-------->NULL
                     +---+
    

    这有帮助吗?

    我还对一件事感兴趣:while(c=*++argv[0])这个表达式。这实际上意味着:while(c=*++argv[0]!=0),我的意思是*++argv[0]如果未找到字符,则返回指向c的空指针?如我的回答中所述,请参阅此代码中的K&R勘误表条目:但此代码不会检测选项链-您需要另一个迭代器来遍历选项链-tn@Alex布朗:我相信我已经解决了这个问题——尽管我不确定这是否是真正的改进。允许
    -tn而不是
    -t-n
    将意味着一笔可观的费用,但这已经不值得了。@Jerry这完全值得了。每个命令行用户都希望能够在一个组中提供单字母选项,而对代码的懒惰意味着违反规则