C语言读取十六进制数排序时strtok拆分token丢失值问题求助
问题原因
- 缓冲区溢出:你定义的
char input[] = {};是长度为0的空数组,没有预留任何存储数据的空间,调用fgets向其写入最多255字节的文件内容时,会直接越界写入非法内存,破坏程序运行时的内存数据,导致后续strtok拆分字符串时读取到被篡改的内容。且你提前定义的长度为255的buffer数组完全没有被使用,属于无效代码。 strtok循环逻辑错误:你在循环中先调用strtok(NULL, " ")获取下一个token,没有判断返回值是否为NULL就直接传入strtol做数值转换,当所有有效token拆分完成后strtok会返回NULL,此时调用strtol属于空指针非法访问,还会多记录一次无效的0值。- 分隔符设置不全:
fgets读取文件内容时会自动将行尾的换行符\n一同写入缓冲区,你仅设置空格作为拆分分隔符,会导致最后一个十六进制数尾部附带换行符,无法被正确拆分识别。 - 排序逻辑缺陷:排序代码中设置了
if (decimal[i] == 0){break;}的判断逻辑,若输入的十六进制数包含合法的0值,排序会提前终止,无法处理所有有效元素。
修复方案
针对以上问题的修改点如下:
- 抛弃零长度的
input数组,改用提前定义的buffer作为fgets的读取缓冲区,预留足够的存储空间。 - 调整
strtok的循环逻辑,每次获取token后先判断是否为NULL,再执行数值转换操作,避免空指针访问。 - 将
strtok的分隔符修改为" \n",同时兼容空格和换行符,消除行尾换行符的影响。 - 修正排序逻辑,移除错误的0值中断判断,直接用实际读取到的有效元素个数作为循环边界。
修复后的完整代码如下:
#include <stdio.h> #include <string.h> #include <stdlib.h> int main() { FILE *in_file = fopen("input.txt", "r"); FILE *out_file = fopen("output.txt", "w"); int bufferLength = 255; char buffer[bufferLength]; if (in_file == NULL) { printf("Error! Could not open file\n"); exit(-1); } fgets(buffer, bufferLength, in_file); int decimal[1000] = {0}; int no = 0; char * token = strtok(buffer, " \n"); while(token != NULL) { int n = (int) strtol(token, NULL, 16); decimal[no] = n; printf("N is : %d , token is : %s \n", n, token); no++; token = strtok(NULL, " \n"); } int temp = 0; // 排序数组 for (int i = 0; i < no; i++) { for (int j = i+1; j < no; j++) { if(decimal[i] > decimal[j]) { temp = decimal[i]; decimal[i] = decimal[j]; decimal[j] = temp; } } } // 输出元素 for (int j = 0; j < no; j++){ fprintf(out_file,"%X ", decimal[j]); } fclose(in_file); fclose(out_file); return 0; }
内容的提问来源于stack exchange,提问作者Mostafa Khaled
相关产品推荐
相关产品推荐

