You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 11:44:54