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

C语言fscanf读取固定宽度含空格记录返回乱码是什么原因?

C语言fscanf读取固定宽度带空格记录异常解决方案

根因分析

你遇到的乱码问题由以下多个错误共同导致:

  • 格式串规则误用:%30[^\n]、%20[^\n]的[^\n]匹配逻辑是读到换行符才停止,不会按照你指定的宽度截断,第一个匹配项会把姓名之后的所有字段内容全部读入,导致后续所有字段读取错位,内存溢出产生乱码。
  • 字符串数组未预留结束符位置:比如acct_no数组长度仅为8,用%8s读取时会写入8个字符+1个字符串结束符\0,直接越界访问破坏内存结构。
  • 日期字段读写格式不匹配:写文件时用%d%d%d输出日、月、年三个整数,最终生成连续的数字串(如27111960),读文件时用%d%d%d会将整个连续数字识别为第一个整数,后两个日期字段读取完全错位。
  • %c未跳过前置空白:%c默认不会跳过空格、制表符等空白字符,前面字段的补位空格会被识别为账户类型的值,导致后续字段进一步错位。
  • 文件指针位置错误:a+模式打开文件时,默认指针指向文件末尾,直接调用fscanf读取不到任何有效内容,结构体变量未被赋值,输出随机内存值。
  • 代码低级错误:tmp变量未定义、free(pw_t)的pw_t变量不存在、Windows路径中的\未转义为\\,会导致路径识别错误。

修复方案

1. 调整宏定义与结构体

// 路径转义符修正
#define PATH "F:\\c\\projects\\Banking Management System\\data\\"
#define F_ACCT "accounts.txt"
#define FILENAME(file)  PATH file

// 写格式:日期固定宽度输出,%c前加空格跳过空白
#define F_ACCT_FPRINTF "%05d%-8s%-30s%02d%02d%04d%-20s%-20s%-20s %c%-15.2lf\n"
// 读格式:固定宽度用%c读取,日期按固定宽度拆分
#define F_ACCT_FSCANF  "%05d%8c%30c%2d%2d%4d%20c%20c%20c %c%lf\n"

// 字符串数组长度+1,预留结束符位置
typedef struct Date
{
    int dd;
    int mm;
    int ccyy;
} Date;

typedef struct Account
{
    int id;
    char acct_no[9];
    char name[31];
    Date birthday;
    char telephone_no[21];
    char mobile_no[21];
    char tfn[21];
    char acct_type;
    double acct_bal;
} Account;

2. 读取后手动处理字符串

读完每个%c读取的字符串后,手动去掉尾部补位空格,添加结束符:

// 工具函数:去掉字符串尾部空格并补结束符
void trim_tail_space(char *str, int len)
{
    int i = len -1;
    while(i >=0 && str[i] == ' ') i--;
    str[i+1] = '\0';
}

3. 修正主逻辑

int main(int argc, char *argv[])
{
    Account *ac_t=malloc(sizeof(Account));
    if (ac_t==NULL)
    {
        perror("Fatal error: ");
        exit(EXIT_FAILURE);
    }
    FILE *fp=fopen(FILENAME(F_ACCT),"a+");
    if (!fp)
    {
        free(ac_t);
        perror("ERROR:");
        exit(EXIT_FAILURE);
    }
    // 移动文件指针到开头
    fseek(fp, 0, SEEK_SET);
    int tmp = fscanf(fp,F_ACCT_FSCANF,
            &ac_t->id,
            ac_t->acct_no,
            ac_t->name,
            &ac_t->birthday.dd,
            &ac_t->birthday.mm,
            &ac_t->birthday.ccyy,
            ac_t->telephone_no,
            ac_t->mobile_no,
            ac_t->tfn,
            &ac_t->acct_type,
            &ac_t->acct_bal);
    // 处理字符串尾部空格
    trim_tail_space(ac_t->acct_no, 8);
    trim_tail_space(ac_t->name, 30);
    trim_tail_space(ac_t->telephone_no, 20);
    trim_tail_space(ac_t->mobile_no, 20);
    trim_tail_space(ac_t->tfn, 20);
    // 输出调试
    printf("\ntmp=%d", tmp);
    printf("\n[%d]",ac_t->id);
    printf("\n[%s]",ac_t->acct_no);
    printf("\n[%s]",ac_t->name);
    printf("\n[%d]",ac_t->birthday.dd);
    printf("\n[%d]",ac_t->birthday.mm);
    printf("\n[%d]",ac_t->birthday.ccyy);
    printf("\n[%s]",ac_t->telephone_no);
    printf("\n[%s]",ac_t->mobile_no);
    printf("\n[%s]",ac_t->tfn);
    printf("\n[%c]",ac_t->acct_type);
    printf("\n[%lf]",ac_t->acct_bal);
    system("pause");
    free(ac_t);
    fclose(fp);
    return 0;
}

内容的提问来源于stack exchange,提问作者Anil

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 03:36:03