有关C

时间:2019-08-11 17:05:20

标签: c

我在练习本中看到了这个小问题,该练习本用于打印向后键入的内容。在这里,我只是无法理解此循环for (; i >= 0; i--),为什么它不首先将i分配给变量,这也是一种正常的语法吗?谢谢!

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

3 个答案:

答案 0 :(得分:5)

  

为什么不将i分配给第一个变量

因为i已经具有我们希望从先前的逻辑开始的值。

  

这也是一种普通语法吗?

是的。 for简介的三个部分中的任何一个都可能为空。

答案 1 :(得分:0)

for()循环中括号之间出现的三个表达式都是可选的,理论上是任意的。

理论上,你可以写

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

这可能毫无意义,也没有用,但是就C语言而言,它没有任何问题,我不希望编译器发出任何错误消息甚至警告。

现在,常规地,第一个表达式初始化某些内容,第二个表达式测试是否应该再次执行循环,第三个表达式递增。但这仅是约定,所有三个表达式都是可选的。

例如,您可以写

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

在这种情况下,i在声明时会获得其初始值。可以肯定的是,这看起来很奇怪,而且可以说是不好的风格,但这不是违法的。

其他表达式也是可选的。例如,我可以这样写:

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

现在iprintf调用中递增,因此无需在for循环头中递增。但是到目前为止,我们基本上有了一个while循环:

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

无论如何,这说明了您看到的循环。从上面的代码开始,变量i已经具有所需的值,因此没有必要在for循环头中进行设置。

答案 2 :(得分:0)

for循环的初始子句可以为空:在您提到的情况下,i已经包含了存储在数组中的字符数,如果用户之前输入的字符数少于25,则为25个或更少换行符。但是该程序存在一个错误,因为应减小i以避免访问超出数组中存储的最后一个字符的msg。如果键入的字符是i,则减少'\n'的不一致,并且从msg[i]开始的输出也是不正确的。

您的实践手册已过时且令人困惑。考虑丢弃它,并使用最新的书籍或在线教程。

for循环的任何子句都可以为空:

  • 可能不需要初始子句
  • test子句可以为空,从而导致无限循环,该循环可以通过breakreturn语句,或者通过直接或间接调用exit()结束。
  • update子句可以包含任何update表达式,如果代码已经更新了循环主体中的必需变量(如果根本需要任何更新),则不能包含任何更新表达式。

第一个for循环是一个非常惯用的示例:for (i = 0; i < 25; i++) { ... }

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

在发布的代码中注意以下问题:

  • main必须使用返回类型int进行定义。该代码使用过时的语法,其中返回类型隐式为int。此语法在C99中无效。
  • 如果用户在换行符之前键入了24个以上的字符,或者在换行符之前发出了文件结尾的信号,则第一个for循环将最多25个字节存储到数组中。
  • 在后一种情况下,程序具有未定义的行为,因为如果用户在换行符之前键入25个字符,则msg[i]会指向msg的结尾。
  • 数组的内容向后打印,如果确实过早结束了输入,则可能会在开头添加一些有趣的字符,例如ÿ
  • 无需添加<string.h>
  • 返回值(0)周围的括号没用。

这是修改后的版本:

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