为什么 return 0 在这种情况下不起作用?
Why is return 0 not working in this case?
我最近开始从 Brian Kernighan 和 Dennis Ritchie 的 The C Programming Language 那里学习 C。在那本书中,有一个完整的小节(1.5.1,第 2 版),作者在其中创建了一个文件复制程序(但我将其用作文本(由用户输入)复制程序)。他们的代码基本上是这样的
#include <stdio.h>
int main()
{
int c;
c = getchar();
while (c != EOF) {
putchar(c);
c = getchar();
}
}
此代码在 运行 时运行良好,但程序永远不会停止。该程序一直在等待输入并继续复制它们,无休止地,永不终止。现在我想创建一个程序,让这种无休止的复制终止。为此,我稍微调整了代码。这是我的代码
#include <stdio.h>
int main()
{
int c;
c = getchar();
while (c != EOF) {
putchar(c);
c = getchar();
}
return 0;
}
我认为在末尾显式写入 return 0;
可能会完成这项工作,但输出似乎根本没有改变。我还尝试使用 if-else 条件并将它们循环如下
#include <stdio.h>
int main()
{
int c;
c = getchar();
while (1) {
if (c != EOF){
putchar(c);
c = getchar();
}
else
return 0;
}
}
但在这种情况下,程序也完全没有改变。
我的问题是如何更改代码,以便我的程序在复制一次后立即结束(或者,更好的是,将其概括为复制 n 次)?
在这里,我必须澄清“一次”(或“n 次”)的意思。当我使用命令提示符(我使用 Windows)来 运行 编译文件时,程序需要一个输入。我通过键盘输入,然后按 Enter 以查看复制的输入。在此之后,程序再次要求我输入一些内容。我不希望这发生。我希望程序在复制我的输入一次后自行结束。这就是我所说的“一次”的意思(上面的定义也可以很容易地扩展为“n 次”)。
@anatolyg 和 @Jabberwocky 建议使用 \n(新行转义字符)使程序运行。但是当输入包含换行符时,此解决方案失败,例如
我的代码可以
这么不行
我在问
在这里寻求帮助
将其作为输入复制到命令提示符中,并使用上述两个用户建议的程序只产生 my code does
作为输出,这不是我想要的输出。有什么办法可以让这个程序适用于带有换行符的文本块,并让它在一次输入后停止(在这种情况下,整个文本块只是一个输入)?
和这里的其他人交流后,我发现我对“一次输入”或“一次”的定义很模糊,不明确,一点也不具体。因此,C 不能做我想让它做的事,这只不过是预料之中的事情。我接受建议使用换行符作为终止程序的信号的答案,因为这与我的想法最接近。谢谢大家
您的 return 0
不会产生任何影响,因为执行将停留在 while
直到 c
变为 EOF。所以你需要让 c
等于 EOF。根据 OS.
尝试 ctrl-D 或 ctrl-Z
My question is that how do I change the code so that my program ends just after copying once (or, even better, generalising it to copying n times)?
引入一个像这样的计数器:
#define MAX_INPUTS 10
...
int cnt = 1;
while (c != EOF && cnt < MAX_INPUTS) {
putchar(c);
c = getchar();
++cnt;
}
This code works fine when run, but the program never stops.
这不是真的,如果你不满足while语句的条件:
while (c != EOF)
程序将终止。
现在如何将 EOF 发送到输入?
视情况而定。您要对 EOF 执行哪个标准输入操作?如果标准输入是终端输入,只需按 control-D
。如果您要发送的唯一内容是 EOF,请使用 echo -n | (your program)
。如果你从你的 C 程序发送它,你几乎无法退出程序,此时它的 stdout 的状态将是 EOF,这将反映在它被重定向到的任何 stdin 中。我很确定你不能在没有获得底层缓冲区的情况下从 C 中发送 EOF,这不是标准化的,因此会让你做一些肮脏的编程。
另一种解决方案是在 while 条件中签入或一些可数字字符,例如:
#include <stdio.h>
int main()
{
int c;
c = getchar();
while (c != EOF && c!= 'A') {
putchar(c);
c = getchar();
}
}
在这种情况下,如果您输入“A
”,程序将结束。
函数 getChar() 在这种情况下总是在等待新字符,在这种情况下 c 永远不会获得 EOF 值。您可以设置一个字符来完成(例如 'e' 退出),或者您可以在退出循环时用计数器计数。不要使用 while(1) 因为这不是一个好习惯。
Ypur 最新编辑建议您可能需要这样的东西:
#include <stdio.h>
int main()
{
int c;
c = getchar();
while (1) {
if (c != EOF && c != '\n') { // '\n' is End of line (Enter)
putchar(c);
c = getchar();
}
else
return 0;
}
}
或更简单:
int main()
{
do
{
int c = getchar();
if (c != EOF && c != '\n') { // '\n' is End of line (Enter)
putchar(c);
}
else
{
return 0;
}
} while (1);
}
对于初学者来说这个循环
while (c != EOF) {
putchar(c);
c = getchar();
}
不是无穷无尽的。 while循环中有一个条件,如果不满足则循环终止。
要生成等于 EOF
的函数 getchar
的输出,您应该在 Windows 中输入组合键 Ctrl + c 或在 Unix 系统中输入组合键 Ctrl + d。
在循环体中或循环后添加 return 语句不会主要影响程序控制流。
注意main中的return语句可以省略。来自 C 标准(5.1.2.2.3 程序终止)
1 If the return type of the main function is a type compatible with
int, a return from the initial call to the main function is equivalent
to calling the exit function with the value returned by the main
function as its argument;11) reaching the } that terminates the main
function returns a value of 0.
例如这两个程序
int main( void )
{
return 0;
}
和
int main( void )
{
}
有效且等效。
由于您只想读取一行输入,因此可以在 end-of-line 字符 '\n'
.
处终止循环
c = getchar();
while (c != '\n') {
putchar(c);
c = getchar();
}
如果您使用 Windows 终端向您的程序输入数据,这就足够了。如果您将输入重定向到您的程序,以便它来自文件,它将读取文件直到第一个换行符。但是,如果文件不包含换行符,您的程序将在文件末尾得到 EOF
。所以终止条件也应该检查 EOF
.
c = getchar();
while (c != '\n' && c != EOF) {
putchar(c);
c = getchar();
}
如果您想阅读 file/terminal 的前 n
行,您需要一个计数器。那么你的代码会变得有点复杂,我认为中间有退出的无限循环会是一个更好的实现。
int line_counter = 0;
int max_lines = 5;
while (1) {
int c = getchar();
if (c == EOF)
break;
putchar(c);
if (c == '\n')
{
++line_counter;
if (line_counter == max_lines)
break;
}
}
另一种分隔输入的方法是使用空行。这将输入格式重新定义为具有文本“段落”。这会使代码更复杂一些——它还应该保存它读取的前一个字符。要检测标记段落结束的空行:如果前一个字符和当前字符都是 end-of-line 个字符,则文本段落刚刚结束。
int record_counter = 0;
int max_records = 5;
int prev_c = '\n';
while (1) {
int c = getchar();
if (c == EOF)
break;
putchar(c);
if (prev_c == '\n' && c == '\n')
{
++record_counter;
if (record_counter == max_records)
break;
}
prev_c = c;
}
我最近开始从 Brian Kernighan 和 Dennis Ritchie 的 The C Programming Language 那里学习 C。在那本书中,有一个完整的小节(1.5.1,第 2 版),作者在其中创建了一个文件复制程序(但我将其用作文本(由用户输入)复制程序)。他们的代码基本上是这样的
#include <stdio.h>
int main()
{
int c;
c = getchar();
while (c != EOF) {
putchar(c);
c = getchar();
}
}
此代码在 运行 时运行良好,但程序永远不会停止。该程序一直在等待输入并继续复制它们,无休止地,永不终止。现在我想创建一个程序,让这种无休止的复制终止。为此,我稍微调整了代码。这是我的代码
#include <stdio.h>
int main()
{
int c;
c = getchar();
while (c != EOF) {
putchar(c);
c = getchar();
}
return 0;
}
我认为在末尾显式写入 return 0;
可能会完成这项工作,但输出似乎根本没有改变。我还尝试使用 if-else 条件并将它们循环如下
#include <stdio.h>
int main()
{
int c;
c = getchar();
while (1) {
if (c != EOF){
putchar(c);
c = getchar();
}
else
return 0;
}
}
但在这种情况下,程序也完全没有改变。
我的问题是如何更改代码,以便我的程序在复制一次后立即结束(或者,更好的是,将其概括为复制 n 次)?
在这里,我必须澄清“一次”(或“n 次”)的意思。当我使用命令提示符(我使用 Windows)来 运行 编译文件时,程序需要一个输入。我通过键盘输入,然后按 Enter 以查看复制的输入。在此之后,程序再次要求我输入一些内容。我不希望这发生。我希望程序在复制我的输入一次后自行结束。这就是我所说的“一次”的意思(上面的定义也可以很容易地扩展为“n 次”)。
@anatolyg 和 @Jabberwocky 建议使用 \n(新行转义字符)使程序运行。但是当输入包含换行符时,此解决方案失败,例如
我的代码可以
这么不行
我在问
在这里寻求帮助
将其作为输入复制到命令提示符中,并使用上述两个用户建议的程序只产生 my code does
作为输出,这不是我想要的输出。有什么办法可以让这个程序适用于带有换行符的文本块,并让它在一次输入后停止(在这种情况下,整个文本块只是一个输入)?
和这里的其他人交流后,我发现我对“一次输入”或“一次”的定义很模糊,不明确,一点也不具体。因此,C 不能做我想让它做的事,这只不过是预料之中的事情。我接受建议使用换行符作为终止程序的信号的答案,因为这与我的想法最接近。谢谢大家
您的 return 0
不会产生任何影响,因为执行将停留在 while
直到 c
变为 EOF。所以你需要让 c
等于 EOF。根据 OS.
My question is that how do I change the code so that my program ends just after copying once (or, even better, generalising it to copying n times)?
引入一个像这样的计数器:
#define MAX_INPUTS 10
...
int cnt = 1;
while (c != EOF && cnt < MAX_INPUTS) {
putchar(c);
c = getchar();
++cnt;
}
This code works fine when run, but the program never stops.
这不是真的,如果你不满足while语句的条件:
while (c != EOF)
程序将终止。 现在如何将 EOF 发送到输入?
视情况而定。您要对 EOF 执行哪个标准输入操作?如果标准输入是终端输入,只需按 control-D
。如果您要发送的唯一内容是 EOF,请使用 echo -n | (your program)
。如果你从你的 C 程序发送它,你几乎无法退出程序,此时它的 stdout 的状态将是 EOF,这将反映在它被重定向到的任何 stdin 中。我很确定你不能在没有获得底层缓冲区的情况下从 C 中发送 EOF,这不是标准化的,因此会让你做一些肮脏的编程。
另一种解决方案是在 while 条件中签入或一些可数字字符,例如:
#include <stdio.h>
int main()
{
int c;
c = getchar();
while (c != EOF && c!= 'A') {
putchar(c);
c = getchar();
}
}
在这种情况下,如果您输入“A
”,程序将结束。
函数 getChar() 在这种情况下总是在等待新字符,在这种情况下 c 永远不会获得 EOF 值。您可以设置一个字符来完成(例如 'e' 退出),或者您可以在退出循环时用计数器计数。不要使用 while(1) 因为这不是一个好习惯。
Ypur 最新编辑建议您可能需要这样的东西:
#include <stdio.h>
int main()
{
int c;
c = getchar();
while (1) {
if (c != EOF && c != '\n') { // '\n' is End of line (Enter)
putchar(c);
c = getchar();
}
else
return 0;
}
}
或更简单:
int main()
{
do
{
int c = getchar();
if (c != EOF && c != '\n') { // '\n' is End of line (Enter)
putchar(c);
}
else
{
return 0;
}
} while (1);
}
对于初学者来说这个循环
while (c != EOF) {
putchar(c);
c = getchar();
}
不是无穷无尽的。 while循环中有一个条件,如果不满足则循环终止。
要生成等于 EOF
的函数 getchar
的输出,您应该在 Windows 中输入组合键 Ctrl + c 或在 Unix 系统中输入组合键 Ctrl + d。
在循环体中或循环后添加 return 语句不会主要影响程序控制流。
注意main中的return语句可以省略。来自 C 标准(5.1.2.2.3 程序终止)
1 If the return type of the main function is a type compatible with int, a return from the initial call to the main function is equivalent to calling the exit function with the value returned by the main function as its argument;11) reaching the } that terminates the main function returns a value of 0.
例如这两个程序
int main( void )
{
return 0;
}
和
int main( void )
{
}
有效且等效。
由于您只想读取一行输入,因此可以在 end-of-line 字符 '\n'
.
c = getchar();
while (c != '\n') {
putchar(c);
c = getchar();
}
如果您使用 Windows 终端向您的程序输入数据,这就足够了。如果您将输入重定向到您的程序,以便它来自文件,它将读取文件直到第一个换行符。但是,如果文件不包含换行符,您的程序将在文件末尾得到 EOF
。所以终止条件也应该检查 EOF
.
c = getchar();
while (c != '\n' && c != EOF) {
putchar(c);
c = getchar();
}
如果您想阅读 file/terminal 的前 n
行,您需要一个计数器。那么你的代码会变得有点复杂,我认为中间有退出的无限循环会是一个更好的实现。
int line_counter = 0;
int max_lines = 5;
while (1) {
int c = getchar();
if (c == EOF)
break;
putchar(c);
if (c == '\n')
{
++line_counter;
if (line_counter == max_lines)
break;
}
}
另一种分隔输入的方法是使用空行。这将输入格式重新定义为具有文本“段落”。这会使代码更复杂一些——它还应该保存它读取的前一个字符。要检测标记段落结束的空行:如果前一个字符和当前字符都是 end-of-line 个字符,则文本段落刚刚结束。
int record_counter = 0;
int max_records = 5;
int prev_c = '\n';
while (1) {
int c = getchar();
if (c == EOF)
break;
putchar(c);
if (prev_c == '\n' && c == '\n')
{
++record_counter;
if (record_counter == max_records)
break;
}
prev_c = c;
}