复用数组时使用memset后内容无法输出到文件的原因及解决方法
1. feof循环条件误用
你当前的while (!feof(fit))是典型错误用法:C语言中feof仅在读取操作失败后才会置位,这意味着当fgets读到文件末尾返回NULL时,循环仍会执行一次。此时text中残留上一轮内容(或不确定值),xifrar_frase处理后生成的text_xifrat可能无效,进而导致输出异常或后续操作出错。
2. memset长度参数错误
代码中memset(text_xifrat, '\0', sizeof(text))存在隐患:如果text_xifrat的数组大小与text不一致(比如text_xifrat更小),这个操作会越界写入内存,破坏相邻变量(比如文件指针fit_x的内部结构),直接导致后续fprintf无法写入文件。
3. 加密函数可能未添加字符串终止符
如果xifrar_frase仅处理字符加密,未在text_xifrat的有效字符末尾添加'\0',那么text_xifrat不是合法的C字符串。此时fprintf会一直输出到内存中第一个'\0'为止,可能包含上一轮残留内容;而memset清空后,若加密函数仍未添加终止符,text_xifrat起始位置是'\0',自然无法输出有效内容。
1. 修正循环条件
用fgets的返回值直接判断循环,避免feof的陷阱:
else{ char text[MAX]; char text_xifrat[MAX]; // 假设大小与text一致,根据实际情况调整 while (fgets(text, MAX, fit) != NULL){ xifrar_frase(text, m_clau, text_xifrat); // 确保text_xifrat是合法字符串后再输出 fprintf(fit_x, "%s\n", text_xifrat); // 可选:清空数组(根据实际需求决定) memset(text, '\0', sizeof(text)); memset(text_xifrat, '\0', sizeof(text_xifrat)); // 修正长度参数 } }
2. 修复memset的长度参数
清空text_xifrat时,必须使用其自身的大小:sizeof(text_xifrat),绝对不能复用text的大小,避免内存越界。
3. 确保加密函数生成合法字符串
修改xifrar_frase函数,在处理完所有字符后,手动添加字符串终止符。例如:
void xifrar_frase(const char *input, const char *key, char *output) { int i = 0; // 加密逻辑... // 处理完后添加终止符 output[i] = '\0'; }
1. 无需每次清空(推荐)
对于字符串数组来说,大部分场景下不需要手动清空:
fgets会自动覆盖text的内容,并在末尾添加'\0',旧内容会被新的字符串终止符截断,不会影响后续处理。- 只要
xifrar_frase保证text_xifrat以'\0'结尾,上一轮的残留内容会被终止符截断,fprintf只会输出当前加密的有效内容。
2. 必须清空时的高效方案
如果确实需要清空数组:
- 使用
memset:这是标准且高效的方式,但必须确保长度参数是数组的实际大小(仅当变量是数组名时,sizeof(arr)才会返回数组总字节数;如果是指针,需要手动传入数组长度)。 - 局部数组初始化:如果是函数内的栈数组,可以在声明时直接初始化为全0:
char text[MAX] = {0};,但此操作仅在声明时有效,循环中无法重复使用。 - 避免使用
bzero:它是BSD扩展函数,不属于C标准,兼容性差,不如memset通用。
内容的提问来源于stack exchange,提问作者Jan Torres Rodríguez

