【问题标题】:C - run into infinite loop when using .txt files as inputC - 使用 .txt 文件作为输入时陷入无限循环
【发布时间】:2013-07-28 14:28:42
【问题描述】:

我一个月前刚开始学习 C,这是我为检测数据列表的峰值而编写的代码。当我在终端中执行“input data.txt”时,它以某种方式进入了无限循环,但是当我通过标准输入(即键盘)手动输入完全相同的数据时,它工作得非常好。任何想法为什么它会陷入无限循环?

谢谢!

int main(void)
{
    int data1 = 0;
    int data2 = 0;
    int data3 = 0;
    int counter = 1;

    scanf("%d %d %d", &data1, &data2, &data3);
    puts("Number  Magnitude");

    while (data3!= EOF){
        if ((data1<=data2)&&(data2>data3)){
            printf("%*d%*d\n", 4,counter,11, data2);
            counter++;

        }
        data1 = data2;
        data2 = data3;
        scanf("%d", &data3);

     }
return 0;
}

【问题讨论】:

  • 在您不输入的情况下如何将输入输入到程序中?
  • 欢迎来到 Stack Overflow。请尽快阅读About 页面。请注意,如果您运行./input data.txt,您的程序仍在从键盘读取,而不是从文件读取。要从命名文件中读取,您需要使用 int main(int argc, char **argv) 然后打开文件。您可能应该尝试./input &lt;data.txt,因为它将标准输入设置为命名数据文件。另一个建议(关于检查您的 scanf() 调用是否成功)也完全有效。
  • 我在终端中使用“
  • 如果你使用&lt;input data.txt,那么输入来自文件input,正在运行的程序是data.txt。你确定你说你在做什么?
  • 我刚查了一下,scanf返回data1、data2、data3为0,0,0,是不是说扫描不正常?

标签: c file-io infinite-loop


【解决方案1】:

从标准输入尝试输入时如何停止输入?使用 Ctrl-Z?

你需要测试你的scanf返回的结果:

返回值 成功时,该函数返回参数列表中成功填充的项目数。由于匹配失败、读取错误或到达文件结尾,此计数可以与预期的项目数匹配或更少(甚至为零)。

如果发生读取错误或读取时到达文件结尾,则设置正确的指示符(feof 或 ferror)。并且,如果在任何数据可以成功读取之前发生任何一种情况,则返回 EOF。 (http://www.cplusplus.com/reference/cstdio/scanf/)

将循环中的最后一行更改为

if (scanf("%d", &data3) < 1)
   break;

--这也意味着你的while语句可以改成

while (1) /* forever */

【讨论】:

  • 当使用标准输入时,我使用 ctrl-D 因为我在 linux 中,或者只是在数据末尾添加一个 -1(EOF 的值)。我刚刚检查了我的 scanf 没有正确扫描文件,当我打印 data1、data2 和 data3 的值时,scanf 返回 0、0、0。在数据文件中有多个峰值的情况下,我认为我不能在 if 语句中使用 break?
  • break 在没有更多输入时停止您的程序。在此之前,您需要弄清楚如何找到“多个峰值”。你能给出一个有效数据的列表,并标出多个峰值吗?
  • 当然。 1 3 5 6 7 4 3 2 0 5 2 0。预计将 7 和 5 识别为峰值。
  • 好的。正如我所想,我的break 与这个(下一个)问题无关。看来您的原始问题已解决,因此请继续尝试自己实施下一步。如果您遇到困难,请发布一个新问题。 (提示:值的什么顺序使它成为峰值?)
【解决方案2】:

我在这里可能会感到困惑,但您在使用 scanf 时从默认输入/输出(可能是终端)扫描,而不是文件。尝试创建一个文件指针并使用 fscanf。例如

FILE *data;
data=fopen("data.txt", "r+");
fscanf(data,"%d",&data1);
fclose(data);

【讨论】:

  • 刚刚注意到您正在重新定义标准输入,因此 nvm.一个无限循环可能来自依赖于 data3 退出的循环。尝试做一个 and 语句并说 while data1、data2 和 data3 不是 eof。
【解决方案3】:
scanf("%d", &data3);

上面函数的默认输入流被重定向到

printf("%*d%*d\n", 4,counter,11, data2);

函数的输出。 你必须区分它。

详细代码是关于这个的。让输入函数(fscanf)从文件中读取数字就可以了

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
    int data1 = 0, data2 = 0, data3 = 0;
    int counter = 1;
    puts("Number Magnitude");

    FILE *fp = fopen(argv[1], "r+");
    if(fscanf(fp, "%d %d", &data1, &data2) != EOF){
        while (fscanf(fp, "%d", &data3) != EOF) {
            if((data1 <= data2) && (data2 > data3)){
                printf("%*d%*d\n", 4, counter++, 11, data2);
            }
            data1 = data2;
            data2 = data3;
        }
    }
    fclose(fp);
    return 0;
}

输出如下:

$ cat data.txt

3 3 4 5 5 5 4 2 1 191 3 43 2 3 0

$ ./a.out 数据.txt

数字大小 1 5 2 191 3 43 4 3

【讨论】:

  • 你能告诉我如何准确区分它吗?抱歉,我对 C 很陌生
  • 感谢代码,但我的代码将由在线自动测试仪进行测试,因此我无法知道输入文件的名称,但我知道输入文件可由以下人员读取scanf & 被告知用 .txt 文件测试我的代码
  • 把文件名传给a.out就可以了
【解决方案4】:

首先,您将值分配给data1data2data3,并且您还要求用户输入值。您要么要求输入值,要么为这些变量分配一些确定的值。同样在您的 while 循环中,EOF 未定义,因此请将其更改为某个值或适当的条件。

【讨论】:

  • 欢迎来到 Stack Overflow。请尽快阅读About 页面。我很好奇为什么你认为EOF 是未定义的——是因为代码没有显示#include &lt;stdio.h&gt;?如果是这样,那么在某种程度上你是正确的,但是当很容易猜出包含哪些问题时,人们经常会从问题中省略#include 行。如果代码是 SSCCE (Short, Self-Contained, Correct Example) 会更容易,但添加一个缺少的标头并不太麻烦。你是对的,在使用 scanf() 之前初始化 dataN 变量是多余的;但是,它没有害处。
  • 是的,我的代码中确实有#include ,但我把它排除在外。我被告知要始终初始化变量,因此我将值分配给 dataN。我发现我遇到的唯一问题是我的 scanf 不扫描文件中的任何数据(data1、2、3 始终为 0,因此是无限循环),但是当我通过标准输入输入数据时它会扫描跨度>
猜你喜欢
  • 2015-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-16
  • 2014-12-12
  • 2020-05-13
相关资源
最近更新 更多