如何用C++管理并排序TXT文件中的16208条寄存器数据?
C++处理TXT文件排序与搜索解决方案
核心结论:不用手动实现动态扩容数组
C++标准库的std::vector就是现成的动态扩容容器,完全能替代手动管理的数组,不用自己写扩容逻辑,直接用就行。
步骤拆解:读取、排序、搜索全流程
1. 定义记录结构(推荐)
把每行寄存器记录封装成结构体,方便后续操作,比如假设每行包含日期和其他内容:
struct Registro { std::string fecha; // 假设日期是排序/搜索的关键字 std::string contenido; // 存储整行内容,也可以拆分其他字段 };
2. 修改CArchivo类,用std::vector存储数据
在头文件中添加容器成员和新方法:
#pragma once #include <vector> #include <string> #include <algorithm> // 用于std::sort class CArchivo{ public: errno_t error; FILE* archivo; std::vector<Registro> registros; // 存储所有记录的容器 void abrirArchivo(const char nombreArchivo[15]); void cerrarArchivo(); void imprimirArchivo(); void leerTodosLosRegistros(); // 新增:读取所有记录到vector void ordenarRegistros(); void guardarRegistros(); void buscarRegistros(std::string fechaInicial, std::string fechaFinal ); int contarRegistros(); CArchivo(); ~CArchivo(); };
3. 实现读取记录的方法
替换原有计数和读取逻辑,直接把数据存入vector:
void CArchivo::leerTodosLosRegistros() { if (error != 0) { printf("Error en la apertura del archivo"); return; } registros.clear(); char buffer[75]; // 用fgets返回值判断,比feof更可靠,避免多读空行 while (fgets(buffer, 75, archivo) != nullptr) { std::string linea(buffer); Registro reg; reg.contenido = linea; // 假设日期是前10位,比如"2024-05-20...",按需调整 reg.fecha = linea.substr(0, 10); registros.push_back(reg); } // 重置文件指针到开头,方便后续操作 fseek(archivo, 0, SEEK_SET); }
4. 实现排序功能
利用标准库std::sort,自定义排序规则:
void CArchivo::ordenarRegistros() { if (registros.empty()) { printf("No hay registros para ordenar\n"); return; } // 按日期升序排序,可修改规则适配你的需求 std::sort(registros.begin(), registros.end(), [](const Registro& a, const Registro& b) { return a.fecha < b.fecha; // 如果按整行内容排序,替换为:return a.contenido < b.contenido; }); printf("Registros ordenados exitosamente\n"); }
5. 实现日期范围搜索
排序后可用二分查找提高效率,也可以直接遍历:
void CArchivo::buscarRegistros(std::string fechaInicial, std::string fechaFinal) { if (registros.empty()) { printf("No hay registros para buscar\n"); return; } printf("Registros en rango %s a %s:\n", fechaInicial.c_str(), fechaFinal.c_str()); // 高效二分查找版(适合大数据量) auto it_inicio = std::lower_bound(registros.begin(), registros.end(), fechaInicial, [](const Registro& reg, const std::string& fecha) { return reg.fecha < fecha; }); auto it_fin = std::upper_bound(registros.begin(), registros.end(), fechaFinal, [](const std::string& fecha, const Registro& reg) { return fecha < reg.fecha; }); for (auto it = it_inicio; it != it_fin; ++it) { printf("%s", it->contenido.c_str()); } // 简单遍历版(适合小数据量) // for (const auto& reg : registros) { // if (reg.fecha >= fechaInicial && reg.fecha <= fechaFinal) { // printf("%s", reg.contenido.c_str()); // } // } }
6. 实现保存排序后的数据
void CArchivo::guardarRegistros() { FILE* archivoSalida; errno_t err = fopen_s(&archivoSalida, "registros_ordenados.txt", "w"); if (err != 0) { printf("Error al abrir archivo de salida\n"); return; } for (const auto& reg : registros) { fprintf(archivoSalida, "%s", reg.contenido.c_str()); } fclose(archivoSalida); printf("Registros guardados exitosamente\n"); }
原代码问题修正
- feof误用:
do-while(feof)会导致多读一次空行,改用while(fgets(...) != nullptr)判断更准确。 - 文件指针重置:读取或计数后,文件指针会停在末尾,需用
fseek(archivo, 0, SEEK_SET)重置到开头。 - 混合IO:尽量统一用C++的
std::ifstream/std::ofstream,比C风格的FILE*更安全简洁。
完整调用示例
int main() { CArchivo arch; arch.abrirArchivo("tu_archivo.txt"); arch.leerTodosLosRegistros(); arch.ordenarRegistros(); arch.buscarRegistros("2024-01-01", "2024-01-31"); arch.guardarRegistros(); arch.cerrarArchivo(); return 0; }
内容的提问来源于stack exchange,提问作者Josafat Gs
相关产品推荐
相关产品推荐

