M1芯片MacBook上C代码EOF触发后循环异常问题(Xcode/Terminal)
M1 Mac下C语言代码输入EOF后终端循环输出异常
在搭载M1芯片的MacBook上运行以下C语言代码时,执行编辑文件操作并按Ctrl+D发送EOF信号后,文件编辑成功,但终端会反复循环输出菜单和编辑提示:
Menu:
- Display file
- Edit file
- Create new file
- Exit
Choice: Enter the new text (end with Ctrl+D in Unix or Ctrl+Z in Windows):
问题原因
按下Ctrl+D时,stdin被标记为EOF状态。后续main函数中的scanf("%d", &choice)会读取失败,choice的值保持上一次的输入(即2,对应编辑文件选项),从而无限循环执行editFileContents函数。
解决方案
需要在编辑操作完成后清除stdin的EOF标记,同时处理scanf读取失败的情况,避免choice值残留。
修改后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_FILENAME_LENGTH 256 #define MAX_TEXT_LENGTH 1024 void deleteFile(char *filename){ if (remove(filename) == 0) { printf("File %s deleted:\n", filename); } else { perror("Could not delete the file"); } } void displayFileContents(char *filename) { FILE *file = fopen(filename, "r"); if (file == NULL) { printf("Could not open the file '%s'\n", filename); return; } char line[MAX_TEXT_LENGTH]; while (fgets(line, sizeof(line), file) != NULL) { printf("%s", line); } fclose(file); } void editFileContents(char *filename) { FILE *file = fopen(filename, "a+"); if (file == NULL) { printf("Could not open the file '%s'\n", filename); return; } char newContents[MAX_TEXT_LENGTH]; printf("Enter the new text (end with Ctrl+D in Unix or Ctrl+Z in Windows):\n"); while (fgets(newContents, sizeof(newContents), stdin) != NULL) { size_t len = strlen(newContents); if (len > 0 && newContents[len - 1] == '\n') { newContents[len - 1] = '\0'; } fprintf(file, "%s\n", newContents); } // 清除stdin的EOF标记,恢复输入功能 clearerr(stdin); fclose(file); } int createNewFile(char *filename) { FILE *file = fopen(filename, "r"); if (file != NULL) { printf("File already exists\n"); fclose(file); return 0; // out of createFile } else { FILE *file = fopen(filename, "w"); if (file == NULL) { printf("Could not create the file '%s'\n", filename); return 1; // out of createFile } fclose(file); } editFileContents(filename); return 2; } int main() { char filename[MAX_FILENAME_LENGTH]; printf("Enter the filename to work on\n"); scanf("%s", filename); int choice; while (1){ printf("\nMenu:\n"); printf("1. Display file\n"); printf("2. Edit file\n"); printf("3. Create new file\n"); printf("4. Exit\n"); printf("Choice: "); // 处理scanf读取失败的情况,重置choice并清除输入缓冲区 if (scanf("%d", &choice) != 1) { choice = -1; // 设置为无效选项,触发default提示 // 清除stdin中残留的字符,避免影响下一次输入 int c; while ((c = getchar()) != '\n' && c != EOF); } switch (choice) { case 1: displayFileContents(filename); break; case 2: editFileContents(filename); break; case 3: createNewFile(filename); break; case 4: printf("Exiting...\n"); return 0; // out of main() default: printf("Invalid choice. Try again.\n"); } } }
关键修改点
- 在
editFileContents函数末尾添加clearerr(stdin),清除stdin的EOF标记,让后续输入操作恢复正常。 - 在
main函数中增加scanf读取失败的判断:若读取失败,将choice设为无效值,并清空输入缓冲区的残留字符,避免影响下一次菜单选择。
内容的提问来源于stack exchange,提问作者N1MA
相关产品推荐
相关产品推荐

