为什么这个C代码(for-loop)永远循环?

时间:2016-03-07 05:56:13

标签: c for-loop

现在学习C,我做了这个简单的 $.post( "charge.php", { stripeToken: token.id, amount:$("#custom-donation-amount").val(),stripeEmail:token.email}) 。该程序只是检查给定的参数是否包含'a'字母。

for-loop

这样做的结果是一个永远循环的程序,但是如果我改变了行:

int main(int argc, char *argv[]) { if(argc != 2) { printf("ERROR: Need one argument\n"); return 1; } int i = 0; char letter; for(i = 0, letter = argv[1][i]; letter != '\0'; i++) { switch(letter) { case 'a': printf("%d: 'a'\n", i); break; default: printf("%d: '%c' is not an 'a'\n", i, letter); } } return 0; }

for(i = 0, letter = argv[1][i]; letter != '\0'; i++)

代码运行得很好。为什么是这样?

5 个答案:

答案 0 :(得分:2)

letter永远不会在您的循环中更新。它始终具有argv[1]中字符串的第一个字符。发表此声明

letter = argv[1][i];  

在循环体中的switch语句之后。

答案 1 :(得分:2)

letter仅被赋值一次;在循环的开始。该赋值应该在for循环中:

// Assign initial value to letter
char letter = argv[1][0];
for(i = 0; letter != '\0'; i++){
    switch(letter) {
        // ...
    }

    // Update new value to letter
    letter = argv[1][i];
}

答案 2 :(得分:2)

for循环的第一部分仅在开头初始化。您可以通过交换,;来“修复”您的代码:

for (i = 0; letter = argv[1][i], letter != '\0'; i++) {

现在条件使用逗号运算符首先分配字母(并丢弃此值),然后检查字符是否为'\ 0'。实际上第二部分是多余的,因为letter = argv[1][i]的值是字符,只有当它不是'\ 0'时它才是真的,所以我们可以把循环写为

for (i = 0; letter = argv[1][i]; i++) {

如果您不需要循环索引,经验丰富的C程序员不会使用上面的任何构造 - 包括索引,而只使用指向char的指针:

char *pos;
for (pos = argv[1]; *pos; pos++) {
    switch(*pos) {
        case 'a':
            printf("'a'\n");
            break;

        default:
            printf("'%c' is not an 'a'\n", *pos);
    }
}

或甚至索引

char letter, *pos = argv[1];
int i;
for (i = 0; letter = pos[i]; i++) {
    switch(letter) {
        case 'a':
            printf("%d: 'a'\n", i);
            break;

        default:
            printf("%d: '%c' is not an 'a'\n", i, letter);
    }
}

答案 3 :(得分:2)

如果您在调试for循环时遇到问题,通常会认为for (INITIALISE; TEST; INCREMENT)等同于:

INITIALISE;
while (TEST)
{
    // code
    INCREMENT;
}

此外,您永远不应该使用逗号运算符。如果你真的知道你在做什么就可以使用它,但如果你真的知道你在做什么,那么你就不会在这里发布这个问题。

所以在你的for循环for(i = 0, letter = argv[1][i]; letter != '\0'; i++)中用逗号替换逗号我们可以把它看作:

i = 0;
letter = argv[1][i];
while (letter != '\0')
{
    // other code (which doesn't modify letter)
    i++;
}

并且应该清楚为什么循环不会终止。

答案 4 :(得分:1)

每当你得到一个偶然的for-for循环时,首先要检查的是你是否实际增加了循环迭代器。你没有,所以你去。

修复是微不足道的,只需使用指针,这可能是你想要的吗?

const char* cptr = argv[1]; 

for(i = 0; cptr[i] != '\0'; i++)
{
  switch(cptr[i])
  { 
    ... 
  }
}

你现在拥有一个纯粹,简单的循环。尽可能避免使用多个迭代器。作为奖励,它比原始版本运行得更快,因为在循环的每一圈都没有无意义的复制。