Как правильно использовать fscanf в цикле while? - PullRequest
0 голосов
/ 22 января 2019

Когда я пытаюсь прочитать текстовый файл zip_code_sample.txt, используя fscanf, он работает не так, как задумано.Похоже, что fscanf ничего не делает, потому что когда я пытаюсь потом распечатать переменные, я ничего не получаю.Это даже не входит в цикл while.

Может кто-нибудь помочь мне с этой проблемой?Я пытался разобраться в этом уже несколько часов и читал другие посты о переполнении стека и многие статьи в Интернете, но ни одна из них не помогла мне это исправить.

Пример кода от 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;
}

1 Ответ

0 голосов
/ 22 января 2019

В функции 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 непосредственно этой переменной.В этом случае это не должен быть указатель.

...