0

我最近向一位想学习 C 的朋友推荐了 K&R。他在第一章中遇到了一个练习,它给了他各种错误。我在我的 Ubuntu 安装上编译它,在 C90 选项和默认值之间交替。我已经查看了各个角度,但它似乎是完美的代码......但是每次运行它时它总是给我一个分段错误。我不是棚子里最聪明的程序员,但这让我很沮丧。

到底是什么导致了这样的错误?

这是代码:

#include <stdio.h>
#define MAXLINE 1000

void reverse(char s[]);

/* A program that reverses its input a line at a time */
main()
{
    int c, i;
    char line[MAXLINE];

    for (i = 0; (c = getchar()) != EOF; ++i) {
        line[i] = c;

        if (c == '\n') {        /* Upon encountering a newline */
            line[i] = '\0';     /* replace newline with null terminator */
            i = 0;
            reverse(line);
            printf("\n%s\n", line);
        }
    }
    return 0;
}

/* A function that reverses the character string */
void reverse(char s[])
{   
    int a, z;
    char x;

    for (z = 0; s[z]; ++z)      /* Figure out where null terminator is */
        ;
    --z;
    for (a = 0; a != z; ++a) {  /* Reverse array usinng x as placeholder */
        x = s[a];
        s[a] = s[z];
        s[z] = x;
        --z;
    }
}
4

3 回答 3

3

你在这里缺少一个分号:

for (z = 0; s[z]; ++z);     /* Figure out where null terminator is */
                   // ^

该循环应该一直运行到找到空终止符为止。如果你去掉这个分号,那么在每次迭代中它都会执行++zand --z,这意味着它只会永远循环。您希望在此循环完成--z发生,因为它将设置为等于字符串的空终止符之前的最后一个字符。z

对于偶数长度的字符串,a并且z将在第二个循环中相互交叉(它们永远不会相等)。例如,如果z=5a=4,那么在下一次迭代中a=5z=4。如果你检查a<z而不是a!=zthen 你避免了这个问题。由于您正在检查!=而不是<,这将导致循环几乎无限运行。但是,您最终会得到一个 SEGFAULT ,因为它们会a变得太大和z太小,因为它们都将用于索引缓冲区之外的内存。

for (a = 0; a != z; ++a) {  /* Reverse array usinng x as placeholder */
          //  ^ should be <, not !=

最后,还有一个错误main。当你找到一个换行符时,你设置i=0. 当您打印字符串时,这很好用,但是在i循环结束时增加时,您i=1会在开始读取下一个字符串时结束。这意味着您将在字符串的开头有一个额外的字符。您需要做一些事情来正确重置i以确保不会发生这种情况。

K&R 在 3.5 节中有一个字符串反转功能。在我的副本中,它位于第 62 页。看起来您的朋友决定迭代字符串而不是调用strlen(这实际上是函数调用所做的所有事情),并认为这a<z应该等同于a!=z.

于 2013-11-05T04:10:32.753 回答
0

这个循环是否过度运行?

for (z = 0; s[z]; ++z)      /* Figure out where null terminator is */
        --z;
于 2013-11-05T04:11:02.177 回答
0
for (z = 0; s[z]; ++z)      /* Figure out where null terminator is */
        --z;

就在第一次迭代之后,z 变为 -1——因此尝试访问s[z]会导致分段错误。

于 2013-11-05T04:14:09.733 回答