我正在编写一个程序,该程序应该读取两个可以包含换行符和各种其他字符的字符串。因此,我使用 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 可能不是正确的函数,或者我尝试错误。假设这甚至是可能的。

有帮助吗?

解决方案

从终端收到EOF后,您将不会收到任何其他数据。没有办法取消输入 - 文件的结尾就是结束。

因此,您应该定义每个变量在单独的行上输入,并让用户按Enter键而不是EOF。您仍然需要检查是否已收到eof,因为这意味着用户实际输入了EOF,而您将看不到任何其他内容 - 在这种情况下,您需要突破循环并打印错误消息。

其他提示

EOF 不是一个 特点 - 这是输入函数返回的一个特殊值,用于指示 状况, ,表明已到达该输入流上的“文件结尾”。正如马丁诉。Löwis 表示,一旦发生“文件结尾”情况,就意味着该流上将不再有可用的输入。

造成混乱的原因是:

  • 当“文件”是交互式终端时(例如,Ctrl-Z 或 Ctrl-D);和
  • EOF value 是可以返回的值之一 getchar() 函数族。

您将需要使用实际的字符值来分隔输入 - ASCII nul 字符 '\0' 如果它不能在输入本身中显示为有效值,则可能是一个不错的选择。

我在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,因为终端输入缓冲区不为空。

您可以使用空字符('\ 0')来分隔变量。各种UNIX工具(例如 find )能够以这种方式分离它们的输出项,这表明它是一种相当标准的方法。

这样做的另一个好处是你可以将流读入一个缓冲区然后创建一个 char * 的数组来指向各个字符串,每个字符串都将正确 '\ 0' - 终止,无需手动更改缓冲区中的任何内容。这意味着更少的内存分配开销,这可能会使您的程序运行速度明显更快,具体取决于您正在读取的变量数量。当然,只有在需要同时将所有变量保存在内存中时才需要这样做&#8212;如果你一次一个地处理它们,你就没有这个特别的优势。

EOF根本不可能实现你的目标。

虽然它在某些方面表现得像个,但EOF不是流中的字符,而是表示流的 end 的环境定义的宏。我还没有看到你的代码,但我知道你做的是这样的:

while ((c=getchar()) != EOF) {
    // do something
}
while ((c=getchar()) != EOF) {
    // do something else
}

第一次键入EOF字符时,要结束第一个字符串,流将不可撤销地关闭。也就是说,流的状态是它已关闭。

因此,第二个while循环的内容永远不会运行。

而不是停止在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)
]
$
  

如何在程序中输入null?

您可以使用以下方法实现-print0函数:

putchar(0);

这将打印ASCII字符'\ 0'到sdtout。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top