如何在C语言中实现文本文件特定内容的搜索与存储算法
C语言文本文件搜索与数据提取实现方案
需求明确
- 核心功能:遍历文本文件,根据**测量模块(如A11)和测量量类型(如R1)**定位目标条目
- 需提取存储的数据:
- 测量模块所在行的上一行内容(如设备ID 9403133410)
- 测量量类型行后的连续3行数据(数值、时间、日期)
- 命令逻辑约束:
- 未执行
v命令打开文件时,任何搜索操作输出Not opened file - 搜索结果默认按日期时间排序,无需额外激活
n命令
- 未执行
文本文件示例片段
9403133410 A11 R1 25.6 14:35:22 2024-05-20 B07 T2 30.1 15:01:10 2024-05-20 A11 R1 24.8 16:20:05 2024-05-19
输入输出要求
- 输入:
search <模块ID> <测量类型>(如search A11 R1) - 输出:
- 文件未打开时:
Not opened file - 无匹配条目时:
No matching entries found - 匹配成功时:按日期时间升序排列的提取数据,格式示例:
Found 2 matching entries (sorted by datetime): Entry 1: Device ID: 9403133410 Module: A11 Measurement Type: R1 Value: 24.8 Time: 16:20:05 Date: 2024-05-19 Entry 2: Device ID: 9403133410 Module: A11 Measurement Type: R1 Value: 25.6 Time: 14:35:22 Date: 2024-05-20
- 文件未打开时:
完整代码实现
基础代码(原文件读取逻辑)
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_LINE 256 FILE *fp = NULL; void cmd_v(const char *filename) { if (fp != NULL) fclose(fp); fp = fopen(filename, "r"); if (!fp) { printf("Failed to open file\n"); } } int main() { char cmd[MAX_LINE]; while (1) { printf("> "); fgets(cmd, MAX_LINE, stdin); cmd[strcspn(cmd, "\n")] = '\0'; if (strncmp(cmd, "v ", 2) == 0) { cmd_v(cmd + 2); } else if (strcmp(cmd, "q") == 0) { if (fp) fclose(fp); exit(0); } } return 0; }
完善后的功能代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #define MAX_LINE 256 #define MAX_ENTRIES 100 // 存储提取数据的结构体 typedef struct { char device_id[MAX_LINE]; char module[MAX_LINE]; char type[MAX_LINE]; char value[MAX_LINE]; char time[MAX_LINE]; char date[MAX_LINE]; time_t timestamp; // 用于排序的时间戳 } MeasurementData; FILE *fp = NULL; MeasurementData entries[MAX_ENTRIES]; int entry_count = 0; // 将日期时间转换为时间戳 time_t get_timestamp(const char *date, const char *time_str) { struct tm tm = {0}; sscanf(date, "%d-%d-%d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday); sscanf(time_str, "%d:%d:%d", &tm.tm_hour, &tm.tm_min, &tm.tm_sec); tm.tm_year -= 1900; tm.tm_mon -= 1; return mktime(&tm); } // 按时间戳升序排序 void sort_entries() { for (int i = 0; i < entry_count - 1; i++) { for (int j = i + 1; j < entry_count; j++) { if (entries[i].timestamp > entries[j].timestamp) { MeasurementData temp = entries[i]; entries[i] = entries[j]; entries[j] = temp; } } } } // 搜索并提取数据 void search_data(const char *target_module, const char *target_type) { if (!fp) { printf("Not opened file\n"); return; } entry_count = 0; char line[MAX_LINE]; char prev_line[MAX_LINE] = {0}; int state = 0; // 0:初始态 1:找到目标模块 2:找到目标类型 3-5:读取后续3行 fseek(fp, 0, SEEK_SET); while (fgets(line, MAX_LINE, fp) != NULL && entry_count < MAX_ENTRIES) { line[strcspn(line, "\n\r")] = '\0'; if (strlen(line) == 0) continue; switch (state) { case 0: strncpy(prev_line, line, MAX_LINE - 1); if (strcmp(line, target_module) == 0) state = 1; break; case 1: if (strcmp(line, target_type) == 0) { strncpy(entries[entry_count].device_id, prev_line, MAX_LINE - 1); strncpy(entries[entry_count].module, target_module, MAX_LINE - 1); strncpy(entries[entry_count].type, target_type, MAX_LINE - 1); state = 2; } else { strncpy(prev_line, line, MAX_LINE - 1); state = 0; } break; case 2: strncpy(entries[entry_count].value, line, MAX_LINE - 1); state = 3; break; case 3: strncpy(entries[entry_count].time, line, MAX_LINE - 1); state = 4; break; case 4: strncpy(entries[entry_count].date, line, MAX_LINE - 1); entries[entry_count].timestamp = get_timestamp(entries[entry_count].date, entries[entry_count].time); entry_count++; strncpy(prev_line, line, MAX_LINE - 1); state = 0; break; } } sort_entries(); if (entry_count == 0) { printf("No matching entries found\n"); return; } printf("Found %d matching entries (sorted by datetime):\n", entry_count); for (int i = 0; i < entry_count; i++) { printf("\nEntry %d:\n", i + 1); printf("Device ID: %s\n", entries[i].device_id); printf("Module: %s\n", entries[i].module); printf("Measurement Type: %s\n", entries[i].type); printf("Value: %s\n", entries[i].value); printf("Time: %s\n", entries[i].time); printf("Date: %s\n", entries[i].date); } } void cmd_v(const char *filename) { if (fp != NULL) fclose(fp); fp = fopen(filename, "r"); if (!fp) { printf("Failed to open file\n"); } else { printf("File opened successfully\n"); } } int main() { char cmd[MAX_LINE]; while (1) { printf("> "); fgets(cmd, MAX_LINE, stdin); cmd[strcspn(cmd, "\n")] = '\0'; if (strncmp(cmd, "v ", 2) == 0) { cmd_v(cmd + 2); } else if (strncmp(cmd, "search ", 7) == 0) { char *module = strtok(cmd + 7, " "); char *type = strtok(NULL, " "); if (module && type) { search_data(module, type); } else { printf("Invalid format: use 'search <module> <type>'\n"); } } else if (strcmp(cmd, "q") == 0) { if (fp) fclose(fp); exit(0); } else { printf("Unknown command. Available: v <filename>, search <module> <type>, q\n"); } } return 0; }
关键实现说明
- 状态机遍历:通过状态变量跟踪文件读取进度,确保精准匹配模块、类型并提取后续数据
- 时间戳排序:将日期时间转换为
time_t类型,实现默认按时间升序排序 - 命令扩展:新增
search命令,支持直接输入模块和类型进行搜索 - 边界处理:包含文件未打开提示、条目数量上限、无效命令提示等异常处理
内容的提问来源于stack exchange,提问作者Kurk3
相关产品推荐
相关产品推荐

