stellarCodeBro
stellarCodeBro

Reputation: 19

How to correctly use fscanf in a while loop?

When I try to read the text file, zip_code_sample.txt, using fscanf it's not working as intended. It appears that fscanf isn't doing anything because when I try to print the variables afterwards I'm not getting anything. It's not even making it into the while loop.

Can someone help me with this problem? I've been trying to figure this out for a few hours now and read other posts on Stack Overflow and many articles online but none have helped me fix this.

Sample code from zip_code_sample.txt:

64720   Allenton
63730   Annada
64401   Alexandria
64830   Anabel
64402   Arbela

Source code:

#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;
}

Upvotes: 0

Views: 745

Answers (1)

Jay
Jay

Reputation: 24895

In the function readFile,

length++;

should be

(*length)++;

length++ doesn't increment the value of length, rather it will be incrementing the pointer causing it to point to the wrong memory location and it all should be going downhill from there.

Additional Issues:

char * zip;
char * town;

You just have a char *. You should actually be allocating some memory to these variables.

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;

It is not clear why you have int *zip. In the code below, you are just assigning the output of atoi directly to this variable. In which case, it should not be a pointer.

Upvotes: 1

Related Questions