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

C语言文件指针跨函数传递异常:读取hw4.data数据乱码求助

问题分析与修复

我尝试从hw4.data文件读取数据并查找指定姓名,用户通过命令行参数输入待查找姓名。程序其他功能正常,但无法在SCAN与LOAD函数间正确传递文件指针,且读取文件输出乱码。作业要求在main函数中定义文件,并在这两个函数间传递,相关代码及hw4.data格式如下:

原代码

#include <stdio.h>
#include <stdlib.h>

struct _data {
    char name[20];
    long number;
};

int SCAN(FILE *(*stream)) { // 遍历文件统计条目数量
    int size = 0;
    char s_temp[100];
    long l_temp;
    while (1) {
        fscanf(*stream, "%s %ld", s_temp, &l_temp);
        if (feof(*stream)) break;
        size++;
    }
    return size;
}

struct _data* LOAD(FILE *stream, int size) { // 遍历文件将条目加载到数据数组
    struct _data* d = malloc(size * sizeof(struct _data));
    int i;
    for (i = 0; i < size; i++) {
        fscanf(stream, "%s %ld", d[i].name, &d[i].number);
    }
    return d;
}

void SEARCH(struct _data *BlackBox, char* name, int size) { // 遍历数组查找指定姓名
    int i;
    int found = 0;
    for (i = 0; i < size; i++) {
        printf("%s %s\n", BlackBox[i].name, name);
        if (strcmp(BlackBox[i].name, name) == 0) {
            printf("*******************************************\nThe name was found at the %d entry.\n*******************************************\n", i);
            found = 1;
            break;
        }
    }
    if (found == 0) {
        printf("*******************************************\nThe name was NOT found.\n*******************************************\n");
    }
}

void FREE(struct _data* BlackBox, int size) { // 释放动态数组
    free(BlackBox);
}

int main(int argv, char* argc[]) {
    if (argv == 2) {
        printf("The argument supplied is %s\n", argc[1]);
        FILE* file = fopen("./hw4.data", "r");
        int size = SCAN(&file);
        struct _data* data = LOAD(&file, size);
        SEARCH(data, argc[1], size);
        fclose(file);
        return 0;
    } else {
        printf("*******************************************\n* You must include a name to search for.*\n*******************************************\n");
        return 0;
    }
}

hw4.data格式

ron 7774013
jon 7774014
tom 7774015
won 7774016

错误点与修复方案

1. 文件指针位置未重置

SCAN遍历文件后,指针已移到文件末尾(EOF),LOAD继续读取会直接读到EOF,导致读取失败出现乱码。解决:SCAN结束后用rewind重置指针到文件开头。

2. feof使用逻辑错误

原代码先执行fscanf再检查feof,当读到EOF时feof才置位,但此时已执行size++,会多统计1条数据。正确做法是检查fscanf返回值,成功读取2个字段才计数。

3. 文件指针传递冗余

SCAN无需二级指针,直接传递FILE*即可,文件指针本身是指向FILE结构体的指针,传递指针值足够操作文件。

4. main函数参数顺序错误

main标准参数是int argc, char* argv[],原代码写反argv和argc,导致命令行参数读取错误。

5. 缺失<string.h>头文件

SEARCH使用strcmp需要包含<string.h>,否则可能出现编译错误或未定义行为。

6. 未调用FREE释放内存

原代码未调用FREE释放动态数组,造成内存泄漏。


修正后的代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h> // 新增strcmp所需头文件

struct _data {
    char name[20];
    long number;
};

int SCAN(FILE *stream) { // 改为传递FILE*,无需二级指针
    int size = 0;
    char s_temp[100];
    long l_temp;
    // 检查fscanf返回值,成功读取2个字段才计数
    while (fscanf(stream, "%s %ld", s_temp, &l_temp) == 2) {
        size++;
    }
    // 重置文件指针到开头,供LOAD函数使用
    rewind(stream);
    return size;
}

struct _data* LOAD(FILE *stream, int size) {
    struct _data* d = malloc(size * sizeof(struct _data));
    if (d == NULL) { // 新增内存分配失败检查
        perror("malloc failed");
        exit(EXIT_FAILURE);
    }
    int i;
    for (i = 0; i < size; i++) {
        // 读取失败时处理
        if (fscanf(stream, "%s %ld", d[i].name, &d[i].number) != 2) {
            perror("fscanf failed");
            free(d); // 已分配的内存要释放
            exit(EXIT_FAILURE);
        }
    }
    return d;
}

void SEARCH(struct _data *BlackBox, char* name, int size) {
    int i;
    int found = 0;
    for (i = 0; i < size; i++) {
        if (strcmp(BlackBox[i].name, name) == 0) {
            printf("*******************************************\nThe name was found at the %d entry.\n*******************************************\n", i);
            found = 1;
            break;
        }
    }
    if (!found) {
        printf("*******************************************\nThe name was NOT found.\n*******************************************\n");
    }
}

void FREE(struct _data* BlackBox) { // size参数无意义,移除
    free(BlackBox);
}

int main(int argc, char* argv[]) { // 修正参数顺序
    if (argc == 2) {
        printf("The argument supplied is %s\n", argv[1]);
        FILE* file = fopen("./hw4.data", "r");
        if (file == NULL) { // 新增文件打开失败检查
            perror("fopen failed");
            return EXIT_FAILURE;
        }
        int size = SCAN(file);
        struct _data* data = LOAD(file, size);
        SEARCH(data, argv[1], size);
        FREE(data); // 调用释放内存
        fclose(file);
        return EXIT_SUCCESS;
    } else {
        printf("*******************************************\n* You must include a name to search for.*\n*******************************************\n");
        return EXIT_FAILURE;
    }
}

内容的提问来源于stack exchange,提问作者FunkyMunky

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 21:35:18