C语言凯撒密码程序出现printf与scanf语句跳过问题求助
解决凯撒密码程序中的输入跳过问题
你碰到的输入跳过问题确实是输入缓冲区残留的换行符导致的,但fflush(stdin)是C标准里未定义的行为(只有对输出流使用fflush才符合标准规范),不能依赖它来清空输入缓冲区。咱们一步步拆解问题,顺便修正代码里的其他逻辑bug:
问题根源分析
scanf(" %c", message)的错误使用:你用%c格式符读取消息,但%c只会读取单个字符,而message是字符数组,应该用%s读取字符串(或者更安全的fgets)。另外,之前的scanf("%d", &choice)会在输入缓冲区留下换行符,即便scanf(" %c"里的空格能跳过前导空白,也无法处理多字符的消息输入。fflush(stdin)的不可靠性:C标准没有规定fflush对输入流的作用,不同编译器(比如MSVC和GCC)的处理逻辑完全不一样,所以这不是通用的解决方案。
正确的解决思路
方法1:手动清空输入缓冲区
在读取key之前,用循环读取并丢弃缓冲区里的所有剩余字符(直到遇到换行符或文件结束符):
// 在scanf("%d", &key)之前添加这段代码 int c; while ((c = getchar()) != '\n' && c != EOF);
方法2:用fgets读取字符串(更安全)
fgets可以读取整行输入,自动处理换行符,还能避免输入溢出问题(记得要手动去掉fgets读取的末尾换行符)。
修正后的完整代码
我把你的代码里的输入问题、逻辑嵌套错误、字母循环处理问题一起修正了:
#include <stdio.h> #include <stdlib.h> #include <string.h> // 用于strlen和strcspn函数 int main() { char message[50]; int i, key, choice; printf("Enter 1. to Encrypt, or 2. to Decrypt: "); scanf("%d", &choice); // 清空scanf留下的换行符 int c; while ((c = getchar()) != '\n' && c != EOF); printf("Enter a message to process: "); // 用fgets读取整行消息,避免输入截断和缓冲区问题 fgets(message, sizeof(message), stdin); // 去掉fgets读取的末尾换行符 message[strcspn(message, "\n")] = '\0'; printf("\nEnter key: "); scanf("%d", &key); for (i = 0; message[i] != '\0'; ++i) { char ms = message[i]; if (ms >= 'a' && ms <= 'z') { if (choice == 1) { // 加密:用模运算处理字母循环,避免超出范围 ms = 'a' + (ms - 'a' + key) % 26; } else if (choice == 2) { // 解密:加26确保模运算结果为正 ms = 'a' + (ms - 'a' - key + 26) % 26; } message[i] = ms; } else if (ms >= 'A' && ms <= 'Z') { if (choice == 1) { ms = 'A' + (ms - 'A' + key) % 26; } else if (choice == 2) { ms = 'A' + (ms - 'A' - key + 26) % 26; } message[i] = ms; } // 非字母字符保持不变 } // 把结果输出移到循环外,避免重复打印 if (choice == 1) { printf("\nEncrypted message: %s\n", message); } else if (choice == 2) { printf("\nDecrypted message: %s\n", message); } return 0; }
关键修正点说明
- 用
while(getchar())循环清空缓冲区,替代不可靠的fflush(stdin) - 用
fgets读取消息,解决单字符读取的问题,同时避免输入溢出 - 修复了加密解密的逻辑嵌套错误(原代码的条件判断会导致逻辑混乱)
- 用模运算处理字母循环(比如
z加密后不会变成非字母字符) - 将结果输出移到循环外面,避免每次循环都重复打印结果
内容的提问来源于stack exchange,提问作者ddisec
相关产品推荐
相关产品推荐

