C语言scanf读取姓名薪资时salary乱码、无法连续输入的解决方法
错误根因
原有scanf格式串存在两个致命逻辑问题:
- 格式串中
%*c和%d之间多写了一个普通逗号字符,按照scanf的匹配规则,必须在输入流中读到完全对应的逗号,才会继续执行后续%d的整数读取逻辑。实际输入时,姓名行读完后的下一个有效字符是薪资数字的开头,不存在逗号,因此%d匹配直接失败,salary1从未被写入值,输出的是栈上的未初始化野值,也就是你看到的无意义乱码。 scanf匹配失败时不会移动输入流的读指针,失败位置前的所有字符都会残留在输入缓冲区中。后续用相同逻辑读取第二名员工信息时,残留的旧输入会直接被新的scanf调用读取,触发连续匹配失败,表现为程序无法正常接收新输入。
另外原写法用%*c硬吞单个字符处理姓名后的换行容错性极差,只要用户输入姓名后多敲了空格、多按了一次回车,就会出现吞错字符、残留空白的问题。
修复方案
去掉格式串里多余的逗号,利用scanf中空白符会自动跳过任意数量连续空白(包括换行、空格、制表符)的特性处理换行残留,替换硬吞字符的逻辑。
单条员工信息读取的正确写法:
char name1[50]; // 数组长度比最大读取长度多1,预留字符串结束符\0的位置 int salary1; printf("Enter name and salary of 'Employee 1':\n"); // 开头加空格,跳过缓冲区中可能残留的空白;%49[^\n]最多读49个非换行字符作为姓名 // 格式串中的空格自动跳过姓名后的所有连续空白,最后%d读取整数薪资 scanf(" %49[^\n] %d", name1, &salary1);
连续读取两名员工信息的可运行示例:
#include <stdio.h> int main() { char name1[50], name2[50]; int salary1, salary2; printf("Enter name and salary of 'Employee 1':\n"); scanf(" %49[^\n] %d", name1, &salary1); printf("Enter name and salary of 'Employee 2':\n"); scanf(" %49[^\n] %d", name2, &salary2); // 回显验证 puts(name1); printf("%d\n", salary1); puts(name2); printf("%d\n", salary2); return 0; }
避坑要点
- 用
%[^\n]读取带空格的字符串时,指定的最大读取长度必须比字符数组长度小1,预留位置给自动追加的字符串结束符\0,避免缓冲区溢出。 - 不要在
scanf格式串中随意添加无意义的普通字符,只要输入流中不存在完全匹配的对应字符,就会直接触发匹配失败,导致后续所有输入逻辑异常。 - 处理输入中的换行、空格等空白内容时,优先用格式串中的空白符做自动匹配,不要用
%*c硬吞固定长度字符,大幅提升输入逻辑的容错性。
内容的提问来源于stack exchange,提问作者John Doe
相关产品推荐
相关产品推荐

