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

C语言使用strncpy复制文件读取字符串时仅拷贝16字节故障求助

问题排查与修复方案

直接原因:字符串复制长度硬编码

你代码中strncpy(str, a, 16);的第三个参数直接写死为16,不管源字符串长度多大,最多只会复制16字节内容。你换成memmove也出现同样问题,是因为你给memmove传的长度参数同样是16,和使用什么复制函数无关。

其他核心错误

除了硬编码长度的问题,你的代码还有多处严重逻辑错误,就算改了长度参数也无法正常运行:

  • 指针传递错误:C语言是值传递,你给openFile传入char* str,函数内修改str的地址只是修改了形参副本,主函数里的str根本拿不到你分配的内存地址,后续printf、free都是操作野指针,会出现乱码、崩溃等未定义行为。
  • realloc使用错误:realloc(str, sizeof(char) * size);存在两个问题,一是realloc可能返回新的内存地址,你没有接住返回值,原指针还是指向旧地址;二是主函数里的str是未初始化的野指针,realloc接收野指针本身就是未定义行为。
  • 缓冲区越界风险:你给变量a分配了size字节内存,但调用fgets时传入的长度是size+1,会发生缓冲区越界,可能破坏其他内存数据。
  • 字符串无结束符:你读取的文件内容没有手动补'\0'结束符,printf输出字符串时会读到内存中的垃圾数据,就是你看到的末尾随机乱码。

修复后代码示例

调整openFile函数(采用返回指针的更简洁实现)

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

char* openFile(int* err_code){
    FILE *arquivo = fopen("input.txt", "r");
    if (arquivo == NULL){
        if(err_code) *err_code = 1;
        return NULL;
    }

    fseek(arquivo, 0, SEEK_END);
    long size = ftell(arquivo); // ftell返回long类型,避免溢出不要用int接收
    rewind(arquivo);

    // 多分配1字节存储字符串结束符'\0'
    char *str = malloc(sizeof(char) * (size + 1));
    if(!str){
        fclose(arquivo);
        if(err_code) *err_code = 2;
        return NULL;
    }

    // 直接读size字节内容,避免fgets被换行截断
    fread(str, sizeof(char), size, arquivo);
    str[size] = '\0'; // 手动补字符串结束符

    printf("读取内容:%s, 长度:%ld\n" , str, size);
    fclose(arquivo);
    if(err_code) *err_code = 0;
    return str;
}

主函数调整

int main(){
    int err;
    char *str = openFile(&err);
    if(!str){
        if(err == 1) printf("error opening file.\n");
        else printf("内存分配失败\n");
        return 0;
    }
        
    printf("\n完整输出:%s\n", str);
    free(str);
    return 0;
}

如果你一定要用参数返回字符串,可将openFile第一个参数改为char** str类型,调用时传&str,函数内操作*str即可。


内容的提问来源于stack exchange,提问作者Otávio Zampar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 21:36:03