如何用C语言读取txt到数组按长度升序排序及空输出问题排查
代码问题定位与修正
核心问题排查
- 存储结构定义错误
你定义的char pw[n];是长度为9999的一维字符数组,仅能存储1条最长9998字符的字符串,完全无法容纳10000条独立的密码记录。后续排序中使用strlen(pw[i])时,本质是把pw数组内第i个字节的数值当做字符串指针计算长度,属于非法内存访问,大概率导致程序读到空值或触发内存异常,最终表现为输出为空。 - 文件读取逻辑失效
循环代码while(!feof(fp)){ fgets(pw, n , fp); }会在每读一行后,直接把内容覆盖到同一个一维数组的起始位置,循环执行完所有文件行后,pw中仅残留最后读取的那1行内容,完全没有完成多密码的存储。 - 字符串交换逻辑类型不匹配
你定义的临时变量是单字符类型char temp;,却使用strcpy(temp, pw[i])执行字符串拷贝。strcpy要求目标参数是可容纳完整字符串的字符数组地址,传入单个字符的地址会直接破坏栈内存结构,导致程序异常。 - 缺少文件打开错误校验
代码中未判断fopen的返回值,如果目标txt文件路径不存在、无读取权限,fp会为NULL,后续所有文件读操作全部失效,自然没有内容可输出。 - feof使用逻辑错误
feof仅会在之前的读操作已经触发文件末尾标记后返回真值,将其作为循环开头的判断条件,极易多执行一次空读取,污染存储内容。
可运行的修正实现
#include <stdio.h> #include <string.h> #define MAX_PW_COUNT 10000 // 最大存储密码数量 #define MAX_PW_LEN 128 // 单条密码最大长度,适配绝大多数常规场景 void bubbleSortASC() { int pwCount = 0; // 实际读取到的密码总数 char pw[MAX_PW_COUNT][MAX_PW_LEN]; // 二维数组存储多字符串 char temp[MAX_PW_LEN]; // 字符串交换用临时缓冲区 int i, j; FILE* fp; // 打开文件并做合法性校验 fp = fopen("C:\\Users\\inanm\\Desktop\\project-work-2018555459\\10-million-password-list-top\\10000.txt", "r"); if (fp == NULL) { printf("文件打开失败,请检查路径与权限\n"); return; } // 逐行读取文件,按序存入数组 while (pwCount < MAX_PW_COUNT && fgets(pw[pwCount], MAX_PW_LEN, fp) != NULL) { // 移除fgets自动读入的换行符,避免长度计算偏差 size_t lineLen = strlen(pw[pwCount]); if (lineLen > 0 && pw[pwCount][lineLen - 1] == '\n') { pw[pwCount][lineLen - 1] = '\0'; } pwCount++; } fclose(fp); // 冒泡排序:按密码长度升序排列 for (i = 0; i < pwCount - 1; i++) { for (j = i + 1; j < pwCount; j++) { if (strlen(pw[i]) > strlen(pw[j])) { strcpy(temp, pw[i]); strcpy(pw[i], pw[j]); strcpy(pw[j], temp); } } } // 输出排序后的前10条结果 printf("Ascending order of first 10 passwords are : \n"); for (i = 0; i < 10 && i < pwCount; i++) { printf("%s ", pw[i]); } printf("\n"); }
修正要点说明:
- 用二维数组替换原有一维字符数组,适配多字符串存储需求
- 读取时按索引顺序存储每一行内容,避免内容相互覆盖
- 临时交换缓冲区改为和单条密码等长的字符数组,满足strcpy的参数要求
- 增加fopen返回值校验,避免空指针访问
- 用fgets的返回值作为循环判断依据,替代易出错的feof逻辑
内容的提问来源于stack exchange,提问作者Nerox
相关产品推荐
相关产品推荐

