scanf()为何跳过首行?修改%[^ ]格式符后仍无效求助
解决scanf读取字符串时的乱码与错位问题
嘿,我来帮你排查这个问题!你的代码里有两个核心错误,导致了输出乱码和内容错位的情况,咱们一步步拆解:
1. scanf的地址参数完全错误
你写的scanf("%[^ ]", &materia[i][50]);这里犯了一个关键错误:&materia[i][50]指向的是第i个字符串数组的第51个字符的地址(数组下标从0开始),而你的每个字符串数组只有50个字符的空间(char materia[V][50];),这就属于内存越界访问了。
当你往这个越界的地址写入数据时,会覆盖其他内存区域的内容,这就是为什么第一个输出会出现R╒fu这种乱码——它其实是破坏了其他内存的数据。
正确的写法应该是传入第i个字符串的首地址,也就是materia[i]或者&materia[i][0]:
scanf("%[^ ]", materia[i]);
2. fflush(stdin)是未定义行为,不能用来清空输入缓冲区
标准C规定fflush只能用于输出流(比如stdout),用它来清空输入流(stdin)是未定义行为,不同编译器可能有不同表现,所以这个方法根本不可靠。
要正确处理输入缓冲区里的换行符,有两种更安全的方式:
- 在
scanf的格式串开头加一个空格:" %[^ ]",空格会自动跳过所有空白字符(包括换行、空格、制表符) - 或者在读取整数后,用
getchar()吃掉遗留的换行符:printf("Enter number of Materi: "); scanf("%d", &V); // 吃掉回车换行 getchar();
另外,用fgets来读取字符串会更安全,它可以避免缓冲区溢出的问题,同时自动处理换行(不过要注意去掉fgets读取到的末尾换行符):
fgets(materia[i], sizeof(materia[i]), stdin); // 去掉末尾的换行符 materia[i][strcspn(materia[i], " ")] = '\0';
修正后的完整代码
#include<stdio.h> #include<string.h> // 要包含strcspn的头文件 #include<windows.h> int main(int argc, const char *argv[]) { int i; int V; printf("Enter number of Materi: "); scanf("%d", &V); getchar(); // 吃掉输入整数后的换行符 char materia[V][50]; for(i = 0; i < V; i++) { printf("Materia %d name : ", i+1); // 用带空格的格式串跳过空白,同时传入正确的地址 scanf(" %[^ ]", materia[i]); } for(i = 0; i < V; i++) { printf("Materia - %d: %s\n", i+1, materia[i]); } system("pause"); return 0; }
这样修改后,你的输入输出就能正常对应了,不会再出现乱码和错位的情况。
内容的提问来源于stack exchange,提问作者Christian Halim
相关产品推荐
相关产品推荐

