(*&&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当一个典型的终端是电传打字机时,code>而不是-t-n
将意味着一笔可观的费用,但这已经不值得了。@Jerry这完全值得了。每个命令行用户都希望能够在一个组中提供单字母选项,而对代码的懒惰意味着违反规则