You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现仅通过一次EOF(Ctrl+D)终止C语言输入循环?

解决EOF终止循环需两次输入的问题

我现在卡在一个问题上,怎么都找不到解决办法。我写了个靠EOF终止的循环,但每次都得按两次Ctrl-D才能终止,不是一次就生效。

我最初的循环写法是这样的:

do {
    int input = scanf("%d", &elements[count++]);
    if (input == EOF) {
        break;
    }
    if (input == 0) {
        wrongInput = true;
        return;
    }
} while (1);

后来又试了另一种写法,还是不行:

while ((int input = scanf("%d", &elements[count++])) != EOF) {
    if (input == 0) {
        wrongInput = true;
        return;
    }
}

每次都得按两次Ctrl-D,以下是完整代码:

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

int count = 0;

int elements[1000000];

int diff = 0;
int optCount = 0;
int firstElement[1000000];
int secondElement[1000000];

bool wrongInput = false;

void inputArr() {

    bool emptyCheck = false;
    // Perform a do-while loop

    do {
        int input = scanf("%d", &elements[count++]);
        if (input == EOF) {
            break;
        }
        if (input == 0) {
            wrongInput = true;
            return;
        }
        if (input != 1) {
            emptyCheck = true;
        }
    } while (1);

    // Resize the array size to count
    elements[count];
    if (emptyCheck == true) {
        elements[count--];
    }
}

void farthestMax(int b[], int n) {
    // To store maximum element in the range i to n
    int suffix_max[n];
    suffix_max[n - 1] = b[n - 1];
    for (int i = n - 2; i >= 0; i--)
    {
        suffix_max[i] = (suffix_max[i + 1] > b[i]) ? suffix_max[i + 1] : b[i];
    }

    for (int i = 0; i < n; i++)
    {
        int low = i + 1, high = n - 1, ans = -1;

        while (low <= high)
        {
            int mid = (low + high) / 2;

            // If current element in the suffix_max is greater than b[i] then move right
            if (suffix_max[mid] > b[i])
            {
                ans = mid;
                low = mid + 1;
            }
            else
                high = mid - 1;
        }

        // Print the required answer
        int currentDiff = ans - i;
        if (ans != -1) {
            if (currentDiff == diff) {
                firstElement[optCount] = i;
                secondElement[optCount] = ans;

                optCount++;
            }
            if (currentDiff > diff) {
                diff = currentDiff;
                optCount = 1;
                firstElement[0] = i;
                secondElement[0] = ans;
            }
        }
    }
}

int main() {
    printf("Input numbers:\n");
    inputArr();
    if (wrongInput == true) {
        printf("Wrong input.\n");
        return EXIT_FAILURE;
    }
    printf("\n");
    farthestMax(elements, count);
    if (optCount == 0) {
        printf("Cant find.\n");
    } else {
        for (int i = optCount - 1; i >= 0; i--) {
            printf("%d: %d - %d\n", diff + 1, firstElement[i], secondElement[i]);
        }
        printf("Options: %d\n", optCount);
    }

    return EXIT_SUCCESS;
}

问题根源

这是因为输入完最后一个数字后,输入缓冲区里还留着换行符。第一次按Ctrl-D时,scanf会读取到这个换行符,但%d格式符会自动跳过空白字符(包括换行),所以scanf会一直等待有效输入,直到你再次按Ctrl-D,此时才会触发EOF。

另外,代码里还有个逻辑错误:do-while循环中每次调用scanf都会先执行count++,哪怕scanf返回EOF,这会导致count多计数一次,后续处理数组时可能出现越界问题。

解决方案

1. 调整count自增时机

只有当scanf成功读取到整数(返回值为1)时,才让count加1,避免无效计数。

2. 修正数组大小调整的无效代码

原代码里的elements[count]和elements[count--]完全无效,静态数组的大小是固定的,无法通过这种方式调整,只需要保证count是实际读取的元素个数即可。

修改后的inputArr函数:

void inputArr() {
    bool emptyCheck = false;
    int input;
    do {
        // 先调用scanf获取结果,再判断是否自增count
        input = scanf("%d", &elements[count]);
        if (input == EOF) {
            break;
        }
        if (input == 0) {
            wrongInput = true;
            return;
        }
        // 仅读取成功时自增count
        count++;
        if (input != 1) {
            emptyCheck = true;
        }
    } while (1);
}

补充说明

在终端输入时,第一次按Ctrl-D是提交当前输入行的内容,第二次才会发送EOF信号。如果输入完数字后直接按Ctrl-D,第一次只是提交了空行,第二次才触发EOF。修改后的代码即使遇到这种情况,也不会出现count多计数的问题,循环能正确终止。

内容的提问来源于stack exchange,提问作者Teodor Otkovic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 14:15:55