user1881401
user1881401

Reputation: 85

Storing data from file into an array of struct

I am trying to create a program where it reads in a file with unknown lines and then splits the data by the spaces and then adds it to the struct. I am having trouble with the reading the data in and adding it to the struct. I get a few errors when trying to compile with GCC. Here they are.

program1.c: In function ‘initialize’:
program1.c:54:3: warning: format ‘%d’ expects argument of type ‘int *’, but argument 5 has type ‘int’ [-Wformat=]
   if(fscanf(fp, "%s %f %d %s\n", *data[counter].type, data[counter].literAmount, *data[counter].miles, *data[counter].color) !=4) {
   ^
program1.c:57:2: warning: format ‘%f’ expects argument of type ‘double’, but argument 3 has type ‘float *’ [-Wformat=]
  printf("data stored is: %s %f %d %s\n", *data[counter].type, data[counter].literAmount, data[counter].miles, *data[counter].color);
  ^
program1.c:57:2: warning: format ‘%d’ expects argument of type ‘int’, but argument 4 has type ‘int *’ [-Wformat=]

Here is the code to the program.

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

typedef struct importedData {
    char *type[20];
    float *literAmount;
    int *miles;
    char *color[20];
}DATA;



int main() {
    int userInput;
    initialize();
    //Do while loop to loop through  menu until exit.
    do {
    //Print statements to put out the output options
        printf("Choose the option you would like to preform \n");
    printf("1.Sort data from the float value & print high to low \n2.Sort data by the float value & print low to high\n3.Sort data by the int value & print high to low\n4.Sort data by the int value & print low to high");
    scanf("%d", &userInput); //Scanner to take in the keyboard input


    } while (userInput != 5);


    return 0;
}

int numberOfLines() {
    FILE *fp = fopen("hw3.data", "r"); //Opens file name and in the read format
    int c = 0; //Count the number of characters
    int count = 0; //Number of lines

    if(fp == NULL) { //If file was not able to be opened program will exit
        printf("Unable to read file. Closing");
        return 0;
    }
    while((c = fgetc(fp)) != EOF) { //Get the character and make sure it isnt the END OF FILE
        if(c == '\n') { //If the charcter is set to \n (New Line) will add one to counter
            count++;
        }
    }
    fclose(fp);
    return count;
}

int initialize() {
    DATA *data = malloc(numberOfLines() * sizeof(*data));
    FILE *fp = fopen("hw3.data", "r"); //Opens file name and in the read format
    int counter = 0;
    int totalIteragions = numberOfLines();
    while(counter < totalIteragions) {
        if(fscanf(fp, "%s %f %d %s\n", *data[counter].type, data[counter].literAmount, *data[counter].miles, *data[counter].color) !=4) {
        return -1;
    } 
    printf("data stored is: %s %f %d %s\n", *data[counter].type, data[counter].literAmount, data[counter].miles, *data[counter].color);
    }
}

Could someone explain to me why this error is occurring and how to fix it and in the future catch errors like this? Thanks for all your help.

EDIT: I don't have to make the variables in the struct pointers do I? I am assuming since I make an array of structs using malloc the memory locations will already be allocated so when you enter in data it will store it to each one of those memory locations. Correct?

Upvotes: 1

Views: 3408

Answers (1)

Iskar Jarak
Iskar Jarak

Reputation: 5325

Printing and scanning are different.

With scanf, you are reading an integer into a location in memory, so the argument matching %d should be a int*, not int.

With printf, you are printing an integer, so the argument matching %d should be an int, not an int*. Same deal with %f - you should pass either a float or a double, not a float * when trying to print.

There are many other issues with your code and I am inclined to agree with Matt McNab - you appear to be throwing * around randomly. I suggest looking for a introductory guide on pointers before going any further. Then read about realloc (no need to iterate the file twice...)

Example struct with 100% less *s:

typedef struct importedData {
    char type[20]; // better be careful reading into this
    float literAmount;
    int miles;
    char color[20]; // this too
} DATA;

Scanning/printing:

if(fscanf(fp, "%s %f %d %s\n", data[counter].type, &data[counter].literAmount, &data[counter].miles, data[counter].color) !=4) {
    return -1;
} 
printf("data stored is: %s %f %d %s\n", data[counter].type, data[counter].literAmount, data[counter].miles, data[counter].color);

However, there is a huge issue with this - you'd be reading potentially more than 20 characters into a 20 character array, which is very bad.

See other questions on this site for how to deal with that.

Upvotes: 1

Related Questions