我正在编写一个程序,它应该读取两个可以包含换行符和其他各种字符的字符串。因此,我使用EOF(Ctrl-Z或Ctrl-D)结束字符串。
这适用于第一个变量,但是使用第二个变量,然而,这似乎有问题,因为显然某些东西卡在输入缓冲区中而用户无法输入任何内容。
我尝试使用while (getchar() != '\n');
和几个类似的变体清理缓冲区,但似乎没有任何帮助。所有清洁尝试都导致无限循环,如果不进行清洁,则无法添加第二个变量。
这两个变量的字符都是在这样的循环中读取的:while((c = getchar()) != EOF)
,这表明它是我在缓冲区中停留的EOF。或者以其他方式影响程序的行为?我正在使用的逻辑有什么问题吗?
在经过几个小时的挣扎之后,我开始有点绝望了。
[编辑:在下方添加代码]
[编辑2:clearerr()似乎让这个EOF解决方案工作了。
它似乎以我在Linux下的原始形式运行,我昨天在Windows上试用它。]
代码:
#include <stdio.h>
#include <string.h>
int main(void)
{
int x = 0;
int c;
char a[100];
char b[100];
printf("Enter a: ");
while((c = getchar()) != EOF)
{
a[x] = c;
x++;
}
a[x] = '\0';
x = 0;
/*while (getchar() != '\n'); - the non-working loop*/
printf("\nEnter b: ");
while((c = getchar()) != EOF)
{
b[x] = c;
x++;
}
b[x] = '\0';
printf("\n\nResults:\na: %s\n", a);
printf("b: %s\n", b);
return(0);
}
[编辑3:]
动态内存问题:
我的程序也应该处理超过100个字符的字符串。最初我打算通过动态内存分配解决这个问题,但是当我遇到上述无限循环和内存相关崩溃的问题时,我把它留了出去并切换到char [100]。
我认为我尝试的通常是这样的:
while((c = getchar()) != EOF)
{
a = malloc(sizeof(char));
a[x] = c;
x++;
}
这是一种可能的(或明智的)方法吗?我正在尝试为那里处理的每个角色分配更多内存。独立。使用这样的代码(这个例子可能包含语法错误)我经历过崩溃,所以在我看来malloc可能不是正确的功能,或者我试错了。假设它甚至可能。
答案 0 :(得分:9)
从终端收到EOF后,您将不会收到任何其他数据。没有办法取消输入 - 文件的结尾就是结束。
因此,您应该定义每个变量在单独的行上输入,并让用户按Enter键而不是EOF。您仍然需要检查是否已收到eof,因为这意味着用户实际输入了EOF,而您将看不到任何其他内容 - 在这种情况下,您需要突破循环并打印错误消息。
答案 1 :(得分:2)
EOF
不是字符 - 它是一个特殊值,输入函数返回以指示条件,即“文件结束”已达到输入流。正如Martinv.Löwis所说,一旦发生“文件结束”条件,就意味着该流上不再有可用的输入。
出现混乱的原因是:
EOF
值是getchar()
系列函数可以返回的值之一。您需要使用实际字符值来分隔输入 - 如果ASCII nul字符'\0'
在输入中不能显示为有效值,则可能是一个不错的选择。
答案 2 :(得分:1)
我在linux框上运行代码,结果如下:
Enter a: qwer
asdf<Ctrl-D><Ctrl-D>
Enter b: 123
456<Ctrl-D><Ctrl-D>
Results:
a: qwer
asdf
b: 123
456
需要两个Ctrl-D,因为终端输入缓冲区不为空。
答案 3 :(得分:0)
EOF根本不可能实现你的目标。
虽然它在某些方面表现得像个,但EOF不是流中的字符,而是表示流的 end 的环境定义的宏。我还没有看到你的代码,但我知道你做的是这样的:
while ((c=getchar()) != EOF) {
// do something
}
while ((c=getchar()) != EOF) {
// do something else
}
第一次键入EOF字符时,要结束第一个字符串,流将不可撤销地关闭。也就是说,流的状态是它已关闭。
因此,第二个while循环的内容永远不会运行。
答案 4 :(得分:0)
您可以使用空字符('\0'
)来分隔变量。各种UNIX工具(例如find
)能够以这种方式分离它们的输出项,这表明它是一种相当标准的方法。
这样做的另一个好处是你可以将流读入一个缓冲区然后创建一个char*
的数组来指向各个字符串,每个字符串都将正确'\0'
- 终止无需手动更改缓冲区中的任何内容。这意味着更少的内存分配开销,这可能会使您的程序运行速度明显更快,具体取决于您正在读取的变量数量。当然,只有当你需要同时在内存中保存所有变量时才需要这样做 - 如果你一次一个地处理它们,你就不会得到这个特别的优势。
答案 5 :(得分:0)
而不是停止在EOF读取输入 - 这不是一个字符 - 停止在ENTER。
while((c = getchar()) != '\n')
{
if (c == EOF) /* oops, something wrong, input terminated too soon! */;
a[x] = c;
x++;
}
EOF是输入终止的信号。您几乎可以保证来自用户的所有输入都以'\ n'结尾:这是用户键入的最后一个键!!!
编辑:您仍然可以使用Ctrl-D和clearerr()
来重置输入流。
#include <stdio.h>
int main(void) {
char a[100], b[100];
int c, k;
printf("Enter a: "); fflush(stdout);
k = 0;
while ((k < 100) && ((c = getchar()) != EOF)) {
a[k++] = c;
}
a[k] = 0;
clearerr(stdin);
printf("Enter b: "); fflush(stdout);
k = 0;
while ((k < 100) && ((c = getchar()) != EOF)) {
b[k++] = c;
}
b[k] = 0;
printf("a is [%s]; b is [%s]\n", a, b);
return 0;
}
$ ./a.out Enter a: two lines (Ctrl+D right after the next ENTER) Enter b: three lines now (ENTER + Ctrl+D) a is [two lines (Ctrl+D right after the next ENTER) ]; b is [three lines now (ENTER + Ctrl+D) ] $
答案 6 :(得分:0)
如何在程序中输入null?
您可以使用以下方法实现-print0函数:
putchar(0);
这将打印ASCII字符'\ 0'到sdtout。