使用fscanf解析temperatures.txt文件遇格式匹配问题求助
解析temperatures.txt文件的问题修复
问题概述
需要解析temperatures.txt文件,每行格式为州,城市:温度,但原代码的while循环中fscanf格式设置错误,无法正确读取内容,同时存在多处类型不匹配、内存操作错误。
原代码中的核心错误点
fscanf参数与格式字符串不匹配:- 传递
cityState[29](数组越界的单个字符)而非数组首地址cityState;传递Temperatures[29](int值)而非int指针,类型完全不匹配。 - 格式字符串
%s:%d无法正确处理包含逗号的州城市字符串(%s仅读取到空白符,实际需要读取到冒号前的所有字符)。
- 传递
- 指针类型错误:
tnode_ptr = &Data;将char数组地址赋值给NODE*指针,类型完全不匹配。 - 结构体与内存操作错误:
TEMPSTACK中Temperatures定义为int*,但insert函数中用strcpy处理int值,混淆字符串与数值操作。init_dbllist中错误地对char* cityState使用数组下标赋值,导致内存分配逻辑混乱。
- 循环逻辑错误:第二个
while (&filename != '\0')循环条件无意义,无法正确遍历读取的数据。
修复方案
1. 修正fscanf读取逻辑
使用%[^:]格式符读取冒号前的所有字符(包括逗号),配合单个int变量存储温度:
char cityState[100]; // 扩大数组避免溢出 int temp; while (fscanf(fp, "%[^:]:%d", cityState, &temp) == 2) { // 处理读取到的州城市和温度 }
2. 修正结构体定义
将TEMPSTACK中的int* Temperatures改为单个int值,存储单条温度数据:
typedef struct tempstack TEMPSTACK; struct tempstack { int temperature; struct tempstack* next; };
3. 修正指针与内存操作
- 移除错误的
tnode_ptr初始化,直接在读取循环中调用insert。 - 修正
init_dbllist中cityState的内存分配逻辑:
node_ptr->cityState = (char*)malloc(1); *node_ptr->cityState = '\0';
4. 修正insert函数逻辑
去掉错误的strcpy操作,直接赋值温度值,并按栈顶插入逻辑维护链表:
newreq->temperature = temp; newreq->next = newserv->top; newserv->top = newreq;
5. 修正traverse函数
正确遍历每个节点对应的栈数据:
void traverse(NODE* node_ptr) { node_ptr = node_ptr->next; while (node_ptr->cityState[0] != DUMMY_TRAILER) { printf("City, State: %s\n", node_ptr->cityState); printf("--------------------\n"); TEMPSTACK* stack_ptr = node_ptr->top; while (stack_ptr != NULL) { printf("Temperature: %d\n", stack_ptr->temperature); stack_ptr = stack_ptr->next; } printf("\n"); node_ptr = node_ptr->next; } }
完整修正后的代码
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdlib.h> #define DUMMY_TRAILER '\177' #ifdef _MSC_VER #include <crtdbg.h> #endif // 栈节点:存储单个温度数据 typedef struct tempstack TEMPSTACK; struct tempstack { int temperature; struct tempstack* next; }; // 双向链表节点:存储州城市信息及对应温度栈 typedef struct node NODE; struct node { char* cityState; struct tempstack* top; // 栈顶指针 struct node* next; struct node* prev; // 双向链表前驱指针 int count; }; // 函数声明 NODE* init_dbllist(void); void insert(NODE* node_ptr, char* cityState, int temp); void traverse(NODE* node_ptr); int main(void) { char cityState[100]; int temp; FILE* fp; char filename[20]; printf("Please enter a filename: "); scanf("%s", filename); fp = fopen(filename, "r"); if (!fp) { printf("Failed to open file!\n"); return 1; } NODE* node_ptr = init_dbllist(); // 正确读取文件内容 while (fscanf(fp, "%[^:]:%d", cityState, &temp) == 2) { insert(node_ptr, cityState, temp); } fclose(fp); traverse(node_ptr); #ifdef _MSC_VER printf(_CrtDumpMemoryLeaks() ? "Memory Leak\n" : "No Memory Leak\n"); #endif return 0; } // 初始化双向循环链表(带哨兵节点) NODE* init_dbllist(void) { NODE* head = (NODE*)malloc(sizeof(NODE)); if (!head) { printf("Error in init_dbllist!\n"); exit(1); } head->cityState = (char*)malloc(1); *head->cityState = '\0'; // 哨兵头节点 NODE* tail = (NODE*)malloc(sizeof(NODE)); if (!tail) { printf("Error in init_dbllist!\n"); exit(1); } tail->cityState = (char*)malloc(2); *tail->cityState = DUMMY_TRAILER; tail->cityState[1] = '\0'; // 哨兵尾节点 head->next = tail; head->prev = tail; tail->next = head; tail->prev = head; head->top = NULL; tail->top = NULL; return head; } // 插入数据:找到对应州城市节点,将温度压入栈;若节点不存在则创建新节点 void insert(NODE* node_ptr, char* cityState, int temp) { NODE* curr = node_ptr->next; NODE* prev_node = node_ptr; // 查找已存在的州城市节点(按字符串顺序) while (curr->cityState[0] != DUMMY_TRAILER && strcmp(cityState, curr->cityState) > 0) { prev_node = curr; curr = curr->next; } NODE* target_node; if (curr->cityState[0] != DUMMY_TRAILER && strcmp(cityState, curr->cityState) == 0) { target_node = curr; } else { // 创建新节点 target_node = (NODE*)malloc(sizeof(NODE)); if (!target_node) { printf("Fatal malloc error!\n"); exit(1); } target_node->cityState = (char*)malloc(strlen(cityState) + 1); if (!target_node->cityState) { printf("Fatal malloc error!\n"); exit(2); } strcpy(target_node->cityState, cityState); target_node->top = NULL; // 插入双向链表 target_node->next = curr; target_node->prev = prev_node; prev_node->next = target_node; curr->prev = target_node; } // 创建新栈节点并压入栈顶 TEMPSTACK* new_stack_node = (TEMPSTACK*)malloc(sizeof(TEMPSTACK)); if (!new_stack_node) { printf("Fatal malloc error!\n"); exit(3); } new_stack_node->temperature = temp; new_stack_node->next = target_node->top; target_node->top = new_stack_node; } // 遍历双向链表及对应栈 void traverse(NODE* node_ptr) { node_ptr = node_ptr->next; while (node_ptr->cityState[0] != DUMMY_TRAILER) { printf("City, State: %s\n", node_ptr->cityState); printf("Temperature List:\n"); TEMPSTACK* stack_ptr = node_ptr->top; while (stack_ptr != NULL) { printf(" %d\n", stack_ptr->temperature); stack_ptr = stack_ptr->next; } printf("--------------------\n"); node_ptr = node_ptr->next; } }
测试验证
使用提供的temperatures.txt文件运行代码,将正确输出每个州城市对应的所有温度数据,按栈的顺序(最后读取的温度先输出)显示。
内容的提问来源于stack exchange,提问作者Henry Lj
相关产品推荐
相关产品推荐

