简体   繁体   English

C程序打印换行符

[英]C program printing newlines

below is my C program for K&R exercise 1-19. 以下是我的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;
}

When I run it using Code::Blocks, I get the following output if input is asdf. 当我使用Code :: Blocks运行它时,如果输入为asdf,则会得到以下输出。

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










fdsa

I expected the output to be just fdsa, without the 10 newlines. 我希望输出只是fdsa,没有10个换行符。 I don't understand why there are 10 newlines that are being printed. 我不明白为什么要打印10条换行符。 What am I missing? 我想念什么?

Edit: I know this can be done way more efficiently, but this was my first attempt and I'm taking it as a learning experience as to why the newlines are being printed. 编辑:我知道可以更有效地完成此操作,但这是我的第一次尝试,我将其作为学习为什么换行的打印方法。

Your code is mostly correct. 您的代码大部分是正确的。 At the end of reading the input, the variable i has saved the length of the input string, so just use that as the point to start reversing. 在读取输入结束时,变量i已保存了输入字符串的长度,因此只需将其用作开始反转的点即可。 You likely don't need to save the carriage return at the end of s since you don't want it to be at the beginning of the output. 您可能不需要在s的末尾保存回车符,因为您不希望它在输出的开头。 Note also that you need to declare reverse before you call it from main. 还要注意,在从main调用它之前,需要声明reverse So you can put the function declaration above main and leave the definition below, or move the entire function definition above main. 因此,您可以将函数声明放在main之上,而将定义保留在下面,或者将整个函数定义移到main之上。 So, something like this is correct: 因此,这样的事情是正确的:

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

When I run your program, I get a single newline. 当我运行您的程序时,我得到一个换行符。

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

oof$ 

There's a bunch of issues. 有很多问题。 First, the final prinf("\\n") never runs because it's immediately after a return . 首先,最后的prinf("\\n")永远不会运行,因为它紧接在return Thus the reversed line has no newline on it. 因此,反向行上没有换行符。

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

Second, the code explicitly puts the trailing newline back onto the s . 其次,代码将尾随换行符显式地放回到s This is why there's an extra newline between the input and its reversal. 这就是为什么在输入和它的反转之间有一个额外的换行符的原因。

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

We can see this with a simple debugging printf("s = '%s'\\n", s); 我们可以通过简单的调试printf("s = '%s'\\n", s);看到这一点printf("s = '%s'\\n", s); .

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

oof$

The simple fix is to not put the final newline one, and print the newline before the return. 简单的解决方法是不要将最后一个换行符放在最后,并在返回之前打印换行符。

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
$

There's another bug, though it's not the cause of the problem. 还有另一个错误,尽管这不是问题的原因。 (s[i] != '0') is checking to see if s[i] is the character 0 not the number 0. With your test data, it effectively does nothing. (s[i] != '0')正在检查s[i]是否是字符0而不是数字0。对于您的测试数据,它实际上什么也不做。

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

This loop only works because s is initialized to be all null bytes. 该循环仅起作用,因为s被初始化为全为空字节。 Every character is printed, but they're all null. 每个字符都已打印,但都为空。 We can see this by printing i as well. 我们也可以通过打印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

This can be made simpler and more efficient by reading from the end of the line, not the end of the buffer. 通过从行的末尾而不是缓冲区的末尾进行读取,可以使此操作更简单,更高效。 We can remember how large the string is while we read. 我们可以记住阅读时字符串的大小。

#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 is a good size for a read buffer decided by the operating system. 对于由操作系统决定的读取缓冲区, BUFSIZ大小合适。 It's provided by stdio.h . stdio.h提供。

It's not necessary to spend the runtime initializing buf because we only ever read from it what we write. 不必花时间在运行时初始化buf因为我们只会从中读取我们编写的内容。 Though it's probably a good idea to stick a null on the end anyway. 虽然无论如何最好在末尾添加一个空值。

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

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