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

为何无法用fwrite函数将字符串字面量存入TXT文件?代码问题咨询

结构体字符串写入文件的问题解答

核心问题:能否用fwrite存储字符串字面量?

可以,但不能直接写入字符串指针,必须写入字符串的实际字节内容。fwrite是按二进制写入指定内存块的内容,如果写的是char*指针,只会把指针的地址值(比如0x7ffe1234)写入文件,而不是字符串本身。

当前代码的问题分析

你的代码无法正确写入名字到文件,有两个关键原因:

1. 所有结构体的name指针指向同一个局部数组

char nam[50];
// ...
s[i].name = nam;

循环中每次输入名字都会覆盖nam数组的内容,而且所有student结构体的name指针都指向这个数组的地址。这会导致:

  • 循环结束后,所有结构体的name都指向最后一次输入的名字;
  • 当create函数执行完毕,局部数组nam被销毁,这些name指针会变成野指针,访问时会触发未定义行为。

2. fwrite写入的是指针地址而非字符串内容

fwrite(&s[i], sizeof(student), 1, fp);

student结构体中的name是char*类型,存储的是字符串的内存地址。用fwrite写入整个结构体时,只会把这个地址值写入文件,而不是地址指向的字符串内容。所以打开ask.txt看到的是乱码或十六进制地址,不是实际的名字。

解决办法

根据需求,有两种常见的修正方式:

方式一:将结构体的name改为固定大小字符数组

把char* name改成char name[50],让结构体直接存储字符串内容,这样fwrite整个结构体就能把名字写入文件:

typedef struct student
{
    int rno;
    char name[50]; // 用固定数组存储字符串
} student;

void create(){
    student *s;
    FILE *fp;
    int n, i;
    printf("Enter number: ");
    scanf("%d", &n);
    s = (student*)calloc(n, sizeof(student));
    fp = fopen("ask.txt", "w");
    for (i=0; i < n; i++){
        printf("Enter rollno: ");
        scanf("%d", &s[i].rno);
        fflush(stdin);
        printf("Enter name: ");
        scanf("%s", s[i].name); // 直接写入结构体的数组
        fwrite(&s[i], sizeof(student), 1, fp);
    }
    fclose(fp);
    free(s); // 记得释放堆内存
}

这种方式简单直接,适合字符串长度可控的场景。

方式二:保留char*指针,分开写入字符串内容

如果必须使用char*指针,需要手动写入字符串的长度和内容,而不是直接写结构体:

typedef struct student
{
    int rno;
    char *name;
} student;

void create(){
    student *s;
    FILE *fp;
    int n, i;
    char nam[50];
    printf("Enter number: ");
    scanf("%d", &n);
    s = (student*)calloc(n, sizeof(student));
    fp = fopen("ask.txt", "w");
    for (i=0; i < n; i++){
        printf("Enter rollno: ");
        scanf("%d", &s[i].rno);
        fflush(stdin);
        printf("Enter name: ");
        scanf("%s", nam);
        s[i].name = strdup(nam); // 复制字符串到堆内存,避免覆盖

        // 分步写入:先写学号,再写字符串长度,最后写字符串内容
        fwrite(&s[i].rno, sizeof(int), 1, fp);
        size_t name_len = strlen(s[i].name) + 1; // +1包含字符串终止符'\0'
        fwrite(&name_len, sizeof(size_t), 1, fp);
        fwrite(s[i].name, sizeof(char), name_len, fp);
    }
    fclose(fp);
    // 记得释放每个name的堆内存
    for (i=0; i < n; i++){
        free(s[i].name);
    }
    free(s);
}

这种方式适合字符串长度不固定的场景,但读取文件时也要对应分步读取:先读学号,再读长度,分配内存后读字符串内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 11:20:38