仅通过 EOF 结束 while 循环一次

问题描述 投票:0回答:1

我正在尝试解决这个问题,但不幸的是我找不到任何解决方案。

我有一个循环,我想用

EOF
来打破它,但它总是需要两次而不是一次。

    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;
}
c loops while-loop scanf eof
1个回答
0
投票

您观察到的行为是特殊字符 Ctrl-D 的终端处理的副作用,默认情况下与

EOF
终端功能相关联,如
termios
手册页中所述:

     EOF     Special character on input and is recognized if the ICANON flag
             is set.  When received, all the bytes waiting to be read are 
             immediately passed to the process, without waiting for a
             newline, and the EOF is discarded.  Thus, if there are no bytes
             waiting (that is, the EOF occurred at the beginning of a line),
             a byte count of zero is returned from the read(), representing
             an end-of-file indication.  If ICANON is set, the EOF character
             is discarded when processed.  NL Special character on input and 
             is recognized if the ICANON flag is set.  It is the line
             delimiter `\n'.

当您在循环中使用

scanf("%d", ...)
读取输入时,
scanf
函数会读取字符,跳过初始空格并转换数字,直到从终端获取非数字输入(默认情况下是行缓冲的)。如果您在非空行末尾键入 Ctrl-D,该行内容将刷新到进程,并且
scanf
最终将尝试继续从标准输入读取,而如果您在空行的开头,或者刷新之后,来自终端的读取请求将返回 0,流读取函数将其解释为文件结尾。
因此,如果您不在行首,则可能需要输入 

Ctrl-D

两次。

© www.soinside.com 2019 - 2024. All rights reserved.