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

C语言文件写入内容异常换行 如何实现单行写入与追加记录

C语言任务写入异常问题修复方案

1. 关于文件打开模式"w"的使用判断

你的需求是保留已有任务记录、持续追加新条目,直接用"w"完全不合理:

  • "w"模式的逻辑是每次打开文件时直接清空全部原有内容,从头开始写入,只适合新建文件、覆盖写全量内容的场景,完全无法满足追加记录的需求。
  • 你当前先以"r"只读模式打开文件、再fseek到末尾写入的逻辑本身就是错的:"r"模式只授予读权限,没有写入权限,此时执行fprintf属于未定义行为,是写入乱码的核心诱因之一。
  • 适配你需求的正确打开模式是"a"(追加模式):文件存在时自动定位到文件末尾等待写入,不会清空原有内容;文件不存在时会自动创建新文件,不需要你单独开"r"判断文件是否存在。

2. 内容错位、异常换行的根本原因

你看到的首字符丢失、换行拆分问题,是三个低级错误叠加导致的:

  • 多余的getchar()吞掉了输入首字符:你在每个fgets前都加了独立的getchar(),会提前读走你输入内容的第一个字符,比如输入Math时首字符'M'被吞,fgets只能读到ath,就会出现你贴的异常里,ath HW、,o page 9-15的错位现象。
  • fgets()会自动读入输入末尾的回车符:你输入完内容按回车产生的\n换行符会被fgets一起存入字符数组,写入文件时这个隐藏的换行符会把内容强行拆到下一行,打乱逗号分隔的格式。
  • 缓冲区溢出风险:你定义的name/category/date/status数组长度只有20字节,但调用fgets时传入的读取长度是50,会读入超出数组容量的内容,造成内存越界,也会引发不可预期的写入异常。另外fflush(stdin)属于标准C未定义行为,不要用来清空输入缓冲区。

3. 修正后的可运行代码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void add_task()
{
    FILE *fptr;
    char name[20];
    char category[20];
    char info[50];
    char date[20];
    char status[20];
    char another = 'Y';
    int ch;

    // 直接以追加模式打开文件,兼容文件不存在自动创建的场景
    fptr = fopen("Tasks.txt", "a");
    if (fptr == NULL)
    {
        printf("\nSYSTEM ERROR");
        getchar();
        return;
    }

    while (another == 'Y' || another == 'y')
    {
        printf("\nTo Add a new task enter the details below\n");
        printf("Name of Task:");
        // 仅在循环开始/上一轮scanf结束后,吞掉缓冲区残留的换行符
        while((ch = getchar()) != '\n' && ch != EOF);
        
        fgets(name, sizeof(name), stdin);
        // 移除fgets读入的尾部换行符
        name[strcspn(name, "\n")] = '\0';

        printf("Category of Task:");
        fgets(category, sizeof(category), stdin);
        category[strcspn(category, "\n")] = '\0';

        printf("Information about task(Max 49 characters):");
        fgets(info, sizeof(info), stdin);
        info[strcspn(info, "\n")] = '\0';

        printf("Due Date of Task(yyyy/mm/dd):");
        scanf(" %s", date);
        printf("Status of Task\n TD = To-Do\n IP = In Progress\n CT = Completed Task\nEnter Status:");
        scanf(" %s", status);

        // 每条记录末尾加换行,避免多条记录挤在同一行
        fprintf(fptr, "%s,%s,%s,%s,%s\n", name, category, info, date, status);

        printf("\nDo you want to add another record (Y/N)");
        another = getchar();
    }
    fclose(fptr);

    printf("\n\n\tPress any key to exit");
    exit(0);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 08:06:21