如何实现仅通过一次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
相关产品推荐
相关产品推荐

