C程序打印换行符

时间:2018-08-06 21:08:53

标签: c newline

下面是我的K&R练习1-19的C程序。

#include <stdio.h>
#define MAXLINE 999

int main (void) {
    printf("Line Reverser.\n");
    printf("This program reverses the input per line.\n");
    middle ();
}
int middle (void) {
    reverse ();
    printf("\n");
    middle ();
}
int reverse (void) {
    int i, c;
    char s[MAXLINE] = {0};
    for (i = 0; ((c = getchar()) != '\n') && (i <= MAXLINE); ++i) {
        s[i] = c;
    };
    if (c == '\n') {
        s[i] = c;
        ++i;
    };
    for (i = MAXLINE; (s[i] != '0') && i >= 0; --i) {
        printf("%c", s[i]);
    };
    return 0;
}

当我使用Code :: Blocks运行它时,如果输入为asdf,则会得到以下输出。

Line Reverser.
This program reverses the input per line.
asdf










fdsa

我希望输出只是fdsa,没有10个换行符。 我不明白为什么要打印10条换行符。我想念什么?

编辑:我知道可以更有效地完成此操作,但这是我的第一次尝试,我将其作为学习打印换行符原因的学习经验。

2 个答案:

答案 0 :(得分:1)

您的代码大部分是正确的。在读取输入结束时,变量i已保存输入字符串的长度,因此只需将其用作开始反转的点即可。您可能不需要在s的末尾保存回车符,因为您不希望它在输出的开头。还要注意,在从main调用reverse之前,需要先声明。因此,您可以将函数声明放在main之上,而将定义保留在下面,或者将整个函数定义移到main之上。所以,这样的事情是正确的:

#include <stdio.h>
#define MAXLINE 999

int reverse (void);

int main (void) {
    printf("Line Reverser.\n");
    printf("This program reverses the input per line.\n");
    reverse ();
}

int reverse (void) {
    int i, j, c;
    char s[MAXLINE] = {0};
    for (i = 0; ((c = getchar()) != '\n') && (i <= MAXLINE); ++i) {
        s[i] = c;
    }

    for (j = i; (s[j] != '0') && j >= 0; --j) {
        printf("%c", s[j]);
    }
    printf("\n");
    return 0;
}

答案 1 :(得分:1)

运行程序时,我得到一个换行符。

$ ./test
Line Reverser.
This program reverses the input per line.
foo

oof$ 

有很多问题。首先,最后一个prinf("\n")永远不会运行,因为它紧接在return之后。因此,反向行上没有换行符。

for (i = MAXLINE; (s[i] != '0') && i >= 0; --i) {
    printf("%c", s[i]);
};
return 0;
printf("\n"); // never runs

第二,代码显式地将尾随换行符放回到s上。这就是为什么在输入和反转之间要有额外的换行符的原因。

if (c == '\n') {
    s[i] = (char)c;
    ++i;
};

我们可以通过简单的调试printf("s = '%s'\n", s);看到这一点。

$ ./test
Line Reverser.
This program reverses the input per line.
foo
s = 'foo
'

oof$

简单的解决方法是不将最后一个换行符放在第一个换行符中,并在返回之前打印换行符。

int reverse (void) {
    int i, c;
    char s[MAXLINE] = {0};
    for (i = 0; ((c = getchar()) != '\n') && (i <= MAXLINE); ++i) {
        s[i] = (char)c;
    };
    for (i = MAXLINE; (s[i] != '0') && i >= 0; --i) {
        printf("%c", s[i]);
    };
    printf("\n");
    return 0;
}

$ ./test
Line Reverser.
This program reverses the input per line.
foo
oof
$

还有另一个错误,尽管这不是问题的原因。 (s[i] != '0')正在检查s[i]是否是字符0而不是数字0。对于您的测试数据,它实际上没有任何作用。

for (i = MAXLINE; (s[i] != '0') && i >= 0; --i) {
    printf("%d: %c\n", i, s[i]);
}

此循环仅适用,因为s已初始化为全部为空字节。每个字符都已打印,但都为空。我们也可以通过打印i来看到这一点。

for (i = MAXLINE; (s[i] != '0') && i >= 0; --i) {
    printf("%d: %c\n", i, s[i]);
}

$ ./test
Line Reverser.
This program reverses the input per line.
foo
999: 
998: 
...
4: 
3: 
2: o
1: o
0: f

通过从行的末尾而不是缓冲区的末尾读取,可以使此过程更简单,更高效。我们可以记住阅读时字符串的大小。

#include <stdio.h>

void reverse(void) {
    // Use BUFSIZ from stdio
    char buf[BUFSIZ];

    // Read a line, but not the newline.
    // buf_idx remembers where the end of the line is.
    size_t buf_idx;
    int c;
    for(
        buf_idx = 0;
        ((c = getchar()) && (c != EOF) && (c != '\n') );
        buf_idx++
    ) {
        buf[buf_idx] = (char)c;
    }

    // A for loop always executes all its statements, even when the
    // condition fails, so we need to back up one.
    // Stick a null on the end of buf. It's not necessary, but just
    // in case we want to print it for debugging.
    buf[buf_idx--] = '\0';


    // Print the characters from the end to the start.
    for( int i = (int)buf_idx; i >= 0; i-- ) {
        printf("%c", buf[i]);
    }

    // Print a trailing newline.
    printf("\n");
}
对于操作系统决定的读缓冲区,

BUFSIZ是合适的大小。由stdio.h提供。

没有必要花费运行时初始化buf的原因,因为我们只从那里读取我们编写的内容。无论如何,最好在末尾添加一个空值。