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
相关产品推荐
相关产品推荐

