使用fgets()函数有特定规则吗?为何读取字符串会出现垃圾值?
问题原因与解决方案
你的问题核心是fgets会把输入时的换行符\n也读进字符串里,而gets和scanf("%s")不会,导致后续处理换行符时输出了奇怪的字符(也就是你说的“垃圾值”)。
为什么fgets会出现这种情况?
fgets的行为和gets/scanf有明确区别:
- fgets会读取输入中的所有字符,包括换行符
\n,直到达到你指定的长度-1(这里是99),或者遇到换行/EOF为止,之后自动在末尾加\0终止符。 - gets会自动丢弃输入末尾的换行符,不会把它存在字符串里,但gets不检查缓冲区长度,容易造成溢出,已经被C标准废弃了。
scanf("%s")只读取到空格或换行符就停止,同样不会把换行符读进字符串,但它无法读取带空格的字符串。
你输入字符串后按回车,这个回车的\n被fgets存在了s里,循环处理到\n时,它的ASCII值是10,远小于65('A'的ASCII),会进入第一个分支计算:10 +26 -k,这个结果对应的字符就是你看到的“垃圾值”。
fgets的使用规则
- 必须指定读取的最大长度(第二个参数),一般用
sizeof(s),避免缓冲区溢出,这是它比gets安全的核心原因。 - 记得处理可能存在的换行符,否则会影响后续字符串处理。
- fgets可以读取带空格的字符串,这是它比
scanf("%s")灵活的地方。
修复后的代码
在读取字符串后,手动去掉换行符即可:
#include<stdio.h> #include<string.h> int main() { int k,i; char s[100]; fgets(s, sizeof(s), stdin); // 查找换行符并替换为终止符 char *newline_pos = strchr(s, '\n'); if (newline_pos != NULL) { *newline_pos = '\0'; } scanf("%d", &k); for(i=0; s[i]!='\0'; i++) { // 只处理大写字母,避免非字母字符被错误转换 if (s[i] >= 'A' && s[i] <= 'Z') { if( (s[i]-k) < 'A') { printf("%c", s[i] +26 -k); } else printf("%c", s[i]-k); } else { printf("%c", s[i]); } } return 0; }
额外加了个判断,只处理大写字母,避免空格、数字等其他字符被错误转换,让程序更健壮。
内容的提问来源于stack exchange,提问作者MD NUR_ 33
相关产品推荐
相关产品推荐

