You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 15:02:53