C程序打印换行符
C program printing newlines
下面是我的 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 个换行符。我错过了什么?
编辑:我知道这可以更有效地完成,但这是我的第一次尝试,我将其作为一种学习经验,了解为什么要打印换行符。
您的代码大部分是正确的。在读取输入结束时,变量 i
已经保存了输入字符串的长度,因此只需以此为起点开始反转即可。您可能不需要在 s
末尾保存回车符 return,因为您不希望它出现在输出的开头。另请注意,在从 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;
}
当我 运行 你的程序时,我得到一个换行符。
$ ./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$
简单的解决方法是不放置最后一个换行符,并在 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
$
还有一个错误,虽然它不是问题的原因。 (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--] = '[=17=]';
// 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
,因为我们只会从中读取我们所写的内容。尽管无论如何在末尾添加一个 null 可能是个好主意。
下面是我的 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 个换行符。我错过了什么?
编辑:我知道这可以更有效地完成,但这是我的第一次尝试,我将其作为一种学习经验,了解为什么要打印换行符。
您的代码大部分是正确的。在读取输入结束时,变量 i
已经保存了输入字符串的长度,因此只需以此为起点开始反转即可。您可能不需要在 s
末尾保存回车符 return,因为您不希望它出现在输出的开头。另请注意,在从 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;
}
当我 运行 你的程序时,我得到一个换行符。
$ ./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$
简单的解决方法是不放置最后一个换行符,并在 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
$
还有一个错误,虽然它不是问题的原因。 (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--] = '[=17=]';
// 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
,因为我们只会从中读取我们所写的内容。尽管无论如何在末尾添加一个 null 可能是个好主意。