简体   繁体   English

有关C语言中循环语法的问题

[英]A question regarding the syntax of loop in C

I saw this little problem in the practice book, which is used to print whatever is typed in backward. 我在练习本中看到了这个小问题,该练习本用于打印向后键入的内容。 And here, I just can't understand this loop for (; i >= 0; i--) , why doesn't it assign the i to a variable in the first, is this a normal syntax as well? 在这里,我只是无法理解for (; i >= 0; i--)循环,为什么它不首先将i分配给变量,这也是一种正常的语法吗? Thanks! 谢谢!

#include <stdio.h>
#include <string.h>

main() {
    int i;
    char msg[25];
    printf("Type up to 25 characters and then press Enter...\n");
    for (i = 0; i < 25; i++) {
        msg[i] = getchar(); //Outputs a single character
        if (msg[i] == '\n') {
            i--;
            break;
        }
    }
    putchar('\n'); // One line break after the loop is done.
    for (; i >= 0; i--) {   // <--- this is the line
        putchar(msg[i]);
    }
    putchar('\n');
    return (0);
}

why doesn't it assign the i to a variable in the first 为什么不将i分配给第一个变量

Because i already has the value we want to start at, from prior logic. 因为i已经拥有我们想从先前的逻辑开始的价值。

is this a normal syntax as well? 这也是一种正常的语法吗?

Yes. 是。 Any of the three parts of the for intro may be empty. 任何的三个部分for介绍可能是空的。

The three expressions which appear between the parentheses in a for() loop are all optional, and theoretically arbitrary. for()循环中括号之间出现的三个表达式都是可选的,并且在理论上是任意的。

Theoretically, you could write 从理论上讲,你可以写

for(a = b; c < d; e++)
    printf("%d\n", f);

This is probably meaningless and useless, but as far as the C language is concerned, there's nothing wrong with it, and I wouldn't expect a compiler to emit any error messages or even warnings about it. 这可能毫无意义,也没有用,但是就C语言而言,它没有任何问题,而且我不希望编译器发出任何错误消息甚至警告。

Now, conventionally , the first expression initializes something, the second expression tests whether we should make another trip through the loop, and the third expression increments. 现在, 按照惯例 ,第一个表达式将初始化某些内容,第二个表达式测试是否应再次执行循环,第三个表达式递增。 But that's all by convention, and again, all three expressions are optional. 但这仅是约定,所有三个表达式都是可选的。

For example, you could write 例如,你可以写

int i = 5;
for(; i < 10; i++)
    printf("%d\n", i);

In this case, i gets its initial value when it's declared. 在这种情况下, i将在声明时获取其初始值。 This looks weird, to be sure, and it's arguably bad style, but it's not illegal. 可以肯定的是,这看起来很奇怪,而且可以说是不好的风格,但这不是违法的。

The other expressions are optional, too. 其他表达式也是可选的。 For example, I could write it like this: 例如,我可以这样写:

int i = 5;
for(; i < 10; )
    printf("%d\n", i++);

Now i gets incremented within the printf call, so there's no need to increment it in the for loop header. 现在, iprintf调用中得到了递增,因此无需在for循环头中对其for递增。 But by now, we've basically got a while loop: 但是到现在,我们基本上有了一个while循环:

int i = 5;
while(i < 10)
    printf("%d\n", i++);

Anyway, this explains the loop you saw. 无论如何,这解释了您看到的循环。 The variable i already had the value it needed, from code up above, so there was no reason to set it in the for loop header. 从上面的代码开始,变量i已经具有所需的值,因此没有理由在for循环头中设置它。

The initial clause of the for loop can be empty: in the case you mention, i already contains the number of characters stored into the array, 25 or less if the user typed fewer characters before the newline. for循环的初始子句可以为空:在您提到的情况下, i已经包含了存储在数组中的字符数,如果用户在换行符之前键入的字符数较少,则为25个或更少。 Yet the program has a bug because i should be decremented to avoid accessing msg beyond the last character stored in the array. 但是该程序存在一个错误,因为i应该减少操作权限,以避免超出存储在数组中的最后一个字符访问msg Decrementing i if the character typed was '\\n' is inconsistent and starting the output at msg[i] is incorrect too. 递减i如果字符被键入'\\n'不一致和从输出开始msg[i]是不正确了。

Your practice book is obsolete and confusing. 您的练习本过时且令人困惑。 Consider discarding it and using a more up to date book or online tutorial. 考虑丢弃它,并使用最新的书籍或在线教程。

Any of the clauses of the for loop can be empty: for循环的任何子句都可以为空:

  • the initial clause may not be needed 可能不需要初始子句
  • the test clause can be empty, causing an infinite loop that ends either via a break or a return statement, or via a direct or indirect call to exit() . test子句可以为空,从而导致无限循环,该循环可以通过breakreturn语句,或者通过直接或间接调用exit()
  • the update clause can contain any update expression, or nothing if the code already updates the required variables in the body of the loop, if any update is needed at all. update子句可以包含任何更新表达式,或者如果代码已经更新了循环主体中的必需变量(如果根本需要任何更新),则该更新子句可以不包含任何更新表达式。

The first for loop is a very idiomatic example: for (i = 0; i < 25; i++) { ... } 第一个for循环是一个非常惯用的示例: for (i = 0; i < 25; i++) { ... }

Here is another classic for loop: for (;;) { /* repeat some action for ever */ } 这是另一个经典的for循环: for (;;) { /* repeat some action for ever */ }

Note the following problems in the posted code: 在发布的代码中注意以下问题:

  • main must be defined with a return type int . main必须使用返回类型int定义。 The code uses an obsolete syntax where the return type was implicitly int . 代码使用过时的语法,其中返回类型隐式为int This syntax is invalid in C99. 此语法在C99中无效。
  • the first for loop stores up to 25 bytes to the array, if the user typed more than 24 characters before the newline or signalled an end of file before the newline. 如果用户在换行符之前键入超过24个字符或在换行符之前发出文件结尾的信号,则第一个for循环最多可将25个字节存储到数组中。
  • the program has undefined behavior in this latter case because msg[i] points beyond the end of msg if the user typed 25 characters before the newline. 该程序在后一种情况下具有未定义的行为,因为如果用户在换行符之前键入25个字符,则msg[i]指向msg末尾。
  • the contents of the array is printed backwards, with potentially some funny characters such as ÿ at the beginning if indeed the input was ended prematurely. 如果确实过早结束了输入,则数组的内容将向后打印,并可能在开头添加一些有趣的字符,例如ÿ
  • there is no need to include <string.h> 无需包含<string.h>
  • the parentheses around the return value (0) are useless. 返回值(0)周围的括号是没有用的。

Here is a modified version: 这是修改后的版本:

#include <stdio.h>

int main() {
    int i, c;
    char msg[25];
    printf("Type up to 25 characters and then press Enter...\n");
    for (i = 0; i < 25; i++) {
        c = getchar();
        if (c == EOF || c == '\n')
            break;
        msg[i] = c;
    }
    putchar('\n'); // One line break after the loop is done.
    while (--i >= 0) {   // equivalent to for (; --i >= 0;)
        putchar(msg[i]);
    }
    putchar('\n');
    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM