【问题标题】:C Program just freeze when I use scanf in a loop当我在循环中使用 scanf 时,C 程序只是冻结
【发布时间】:2021-11-10 14:11:32
【问题描述】:

我正在为 coursera 上的一个问题编写一个简单的算法,当我开始通过 scanf() 输入值时,我的程序只是冻结。它没有执行甚至不存在循环。当它在我的笔记本电脑上不起作用时,我在一个在线编译器中尝试了它,但它在那里也不起作用。我在 Coursera 的类似算法问题上遇到了同样的问题。

附:需要完整的代码来回答这个问题。

    int main()
    {
        int distance;
        scanf("%d", &distance);
        int range;
        scanf("%d", &range);
        int pumps;
        scanf("%d", &pumps);
        int disPump[pumps];
        for(int i = 0; i < pumps; i++){
            scanf("%d", &disPump[i]);
        }
        //Program is never reaching this line and is just freezing
        printf("Loop terminated."); 
        int minRefuel = calcRefuel(distance, range, disPump, pumps);
    }

int calcRefuel(int distance, int range, int disPump[], int pumps){
    
    // Array will be sorted here in ascending order using bubble sort.
    for(int i = 0; i < pumps - 1; i++){
        for(int j = 0; j < pumps - i - 1; j++){
            if(disPump[j] > disPump[j+1]){
                int temp = disPump[j];
                disPump[j] = disPump[j+1];
                disPump[j+1] = temp;
            }
        }
    }

    // main algorithm starts here.
    int distCovered = 0;
    int refill = 0;
    while(1){
        int nearestPump = locatePump(range, disPump, pumps, distCovered);
        distCovered += nearestPump;
        refill++;
        if((distCovered+range) >= distance){
            break;
        }
    }
    return refill;
}

int locatePump(int range, int disPump[], int pumps, int distCovered){
    range += distCovered;
    int i = 0;
    // Doubt about while.
    while(range >= disPump[i] && range < disPump[i+1]){
        i++;
    }
    return disPump[i] - distCovered;
}

【问题讨论】:

  • 可能卡在calcRefuel 并且没有刷新之前的输出。发帖minimal reproducible example.
  • 另外你应该检查scanf返回值以确保输入被接受。
  • 试试printf("output with no newline"); fflush(stdout); 或者,也许更简单:printf("outout with newline\n");
  • "这意味着它从未到达函数 calcRefuel。"不一定,这可能意味着打印输出尚未刷新,程序挂在calcRefuel 中。尝试在阅读后回显输入,以确认程序正在查看您认为您提供的内容。
  • fflush(stdout) 允许 printf 用于调试。

标签: c algorithm


【解决方案1】:

在你的问题中,你说你的程序在没有到达循环结束时就冻结了。

在您的自我回答中,您进一步表示,当您在笔记本电脑上进行测试时,该程序可以正常工作。

我的猜测是您对程序中发生的事情感到困惑,因为您的程序没有提供任何反馈。它从不打印任何提示用户输入的消息,因此您不知道程序当前处于什么状态以及程序接下来期待哪个输入。这可能会导致您的程序被“冻结”的错误印象。我建议您在程序中添加一些printf 语句:

#include <stdio.h>

int main(void)
{
    int distance;
    printf( "Please enter the distance: \n" );
    scanf("%d", &distance);

    int range;
    printf( "Please enter the range: " );
    scanf("%d", &range);

    int pumps;
    printf( "Please enter the number of pumps: " );
    scanf("%d", &pumps);

    int disPump[pumps];
    for(int i = 0; i < pumps; i++){
        printf( "Please enter the number for pump #%d: ", i + 1 );
        scanf("%d", &disPump[i]);
    }
    printf("Loop terminated.");
    int minRefuel = calcRefuel(distance, range, disPump, pumps);
}

这样,您应该始终知道程序当前处于什么状态以及程序接下来期待哪个输入。

但是,这种方法仍然存在一个问题。正如在 cmets 部分中已经指出的那样,如果您的程序陷入无限循环,那么您可能不会在屏幕上看到最新的 printf 语句。这是因为stdout 已缓冲,输出可能尚未从缓冲区中刷新。

由于这个原因,有可能该行的输出

printf("Loop terminated.");

如果您的程序以某种方式卡在函数 calcRefuel 中,则不会显示。

由于stdout 在写入终端时通常是行缓冲的,因此最简单的解决方法是添加一个换行符,如下所示:

printf("Loop terminated.\n");

您还可以使用以下命令显式刷新stdout 的缓冲区:

fflush( stdout );

另一种方法是打印到stderr 而不是stdout,它是无缓冲的。您可以使用fprintf 而不是printf 来完成此操作。

【讨论】:

    【解决方案2】:

    正如人们所说,没有任何语法错误或逻辑错误。这只是一些与编译器相关的问题。我尝试在另一台笔记本电脑上编写相同的代码并且它正在工作。我发布这个的原因是因为它甚至没有在在线编译器中工作,也许这是一个巧合。所以,我想到了一些我不知道的东西并在这里发布。

    【讨论】:

    • 一些在线编译器不允许您以交互方式运行程序,这意味着您需要在运行程序之前指定程序的所有输入(stdin)。
    【解决方案3】:

    它在在线编译器https://www.onlinegdb.com/online_c_compiler 中对我有用。 picture您需要在终端中启动程序并输入值。

    【讨论】:

    • 这对我不起作用。使用的其他功能是否会影响代码?也许当编译器编译整个代码并生成可执行文件时,会发生一些阻碍输入的异常情况。
    • 我猜你说它冻结了。它不会崩溃,因此它正在等待您的输入。我认为您正在使用没有激活输入流的环境,例如 cout 无法与 qt 调试器一起使用。尝试在另一个终端打开它,并在调用哪个 scan f 时放入一些 cmets。
    • @Dirghayu 其他功能可能会影响main() 代码。未定义的行为可能会导致各种未指定的损坏,或者没有。
    猜你喜欢
    • 2015-06-05
    • 1970-01-01
    • 1970-01-01
    • 2017-04-26
    • 1970-01-01
    • 2021-10-13
    • 2021-11-30
    • 1970-01-01
    • 2023-04-08
    相关资源
    最近更新 更多