【问题标题】:How to correctly use fscanf in a while loop?如何在while循环中正确使用fscanf?
【发布时间】:2019-01-22 06:26:12
【问题描述】:

当我尝试使用 fscanf 读取文本文件 zip_code_sample.txt 时,它没有按预期工作。似乎 fscanf 没有做任何事情,因为当我之后尝试打印变量时,我什么也没得到。它甚至没有进入 while 循环。

有人可以帮我解决这个问题吗?几个小时以来,我一直在努力解决这个问题,并阅读了 Stack Overflow 上的其他帖子和许多在线文章,但没有一个能帮助我解决这个问题。

来自zip_code_sample.txt的示例代码:

64720   Allenton
63730   Annada
64401   Alexandria
64830   Anabel
64402   Arbela

源代码:

#include <errno.h>
#include <stdlib.h>   // For _MAX_PATH definition
#include <stdio.h>
#include <string.h>

typedef struct cityStruct { unsigned int zip; char * town; } city;
typedef struct zipTownsStruct {
    int * zips;      // indexes to main array cities sorted by zip
    city * * towns;  // pointers to main array cities sorted by town name
    city * cities;   // main array of cities in order from file not sorted
} zipTowns;

void getArrs(zipTowns * arrs, int size) {  
    if((arrs->zips = (int *) malloc(sizeof(int) * size)) == NULL) {
        fprintf(stderr, "%s\n", strerror(errno));
        exit(errno);
    }
    if((arrs->towns = (city **) malloc(sizeof(city*) * size)) == NULL) {
        fprintf(stderr, "%s\n", strerror(errno));
        exit(errno);
    }
    if((arrs->cities = (city *) malloc(sizeof(city) * size)) == NULL) {
        fprintf(stderr, "%s\n", strerror(errno));
        exit(errno);
    }
}

int getArgsInfoOpenFile(int argc, char * argv[], FILE ** infile, int * size) {
    int retval = 0;
    if(argc != 3) { // test for correct arguments number 3: exename, filename, size
        return -1;
    }
    if ((*infile = fopen("zip_code_sample.txt", "r")) == NULL) { // attempt to open file
        fprintf(stderr, "%s\n", strerror(errno));
        exit(errno);
    }
    return retval;
}

void readFile(zipTowns arrs, FILE * infile, int * length) {
    char * zip;
    char * town;
    while(fscanf(infile,"%s %s", zip, arrs.cities[*length].town) == 2) {
        arrs.cities[*length].zip = atoi(zip);
        printf("Zip: %s City: %s\n", arrs.cities[*length].zip, arrs.cities[*length].town); 
        printf("Zip: %s City: %s\n", zip, town); 
        length++;
    }
}

int main(int argc, char * argv[]) {
    zipTowns arrs; // all the arrays in one struct
    int length = 0; // current count of items in arrays 
    FILE * infile = NULL;
    int ret = 0, size = atoi(argv[2]);
    if(size > 999999 || size < 1) {
        printf("Illegal array size. Choose a size less than one million and greater than 0.\n");
        return -1;
    }

    if (getArgsInfoOpenFile(argc, argv, &infile, &size)) {
        printf("error in command line arguments\n");
        ret = -1;
    }else {
        getArrs(&arrs, size);
        readFile(arrs, infile, &length);
    }
    return 0;
}

【问题讨论】:

  • 您应该在结构中包含数组的长度,而不是将其分开。它会减少你犯错误的机会。
  • readFile -- char * zip; 指向哪里?它正在使用什么有效的内存块? town 指向哪里?它在哪里初始化?
  • 您使用的是哪个编译器?你从你的代码中得到了多少警告。我收到 6 个警告(我告诉 GCC 将其视为错误)——其中 2 个是关于未使用的参数(不太重要),一个是关于“未使用但已设置”的变量,其他则相当严重(试图打印一个使用%s 的整数;和两个未初始化的变量,它们都是指针。未初始化的指针是不愉快的秘诀。我将您的代码保存在文件read11.c 中并使用gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes read11.c -o read11 编译它。
  • 我在main() 以外的函数之前添加了static 来处理“缺少原型”的警告/错误。

标签: c scanf


【解决方案1】:

在函数readFile中,

length++;

应该是

(*length)++;

length++ 不会增加长度的值,而是会增加指针,导致它指向错误的内存位置,这一切都应该从那里走下坡路。

其他问题:

char * zip;
char * town;

你只有一个char *。您实际上应该为这些变量分配一些内存。

typedef struct zipTownsStruct {
    int * zips;      // indexes to main array cities sorted by zip
    city * * towns;  // pointers to main array cities sorted by town name
    city * cities;   // main array of cities in order from file not sorted
} zipTowns;

不清楚为什么你有int *zip。在下面的代码中,您只是将atoi 的输出直接分配给该变量。在这种情况下,它不应该是一个指针。

【讨论】:

猜你喜欢
  • 2021-10-19
  • 1970-01-01
  • 2017-10-05
  • 1970-01-01
  • 2021-03-25
  • 2013-10-29
  • 2012-11-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多