Thread: Reading data from a text file into a C struct

  1. #1
    Registered User
    Join Date
    Dec 2011
    Posts
    17

    Reading data from a text file into a C struct

    Hi,

    I'm trying to write a program which will read data from a text file into a C struct, but it's been about two years since I last used C, and I'm quite rusty.

    Currently, I have two files: main.c and structs.h

    My main.c file is the 'menu' for the program, and is what the user will interact with. The structs.h file contains two structs, in which the data from a .txt file specified by the user will be stored.

    I'm currently trying to allow the user to specify which .txt file they would like to work with, but am having problems getting my program to load the file correctly.

    main.c currently looks like this:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    /*
     * 
     */
    extern int errno;
    
    int main(int argc, char** argv) {
        
        char text[500]; /* Create a character array that will store all of the text in the file */
        char line[100]; /* Create a character array to store each line individually */
        
        FILE *file; /* Create a pointer to the file which will be loaded, to allow access to it */
        char fileName[30]; /* Create a character array to store the name of the file the user want to load */
        
        
        printf("Enter the name of the file containing ship information: ");
        scanf("%s", fileName);
        
        /*Try to open the file specified by the user. Use error handling if file cannot be found*/
        file = fopen("fileName", "r"); /* Open the file specified by the user in 'read' mode*/
        if(file == NULL){
            perror("The following error occurred: ");
            printf("Value of errno: %d\n", errno);
        }
        else {
            fclose(file);
            return 0;
        }
        
        printf("File loaded. "); /* Display a message to let the user know 
                                  * that the file has been loaded properly */
        
        fscanf(file, "%s", text); /* Read all the text from the file and store in the character array  */
        printf(text); /* print out the contents of the 'text' array to show that the info is being saved there */
        
       // fclose(fileName); /* Is this needed, given that I don't have a fileStream? */
        return (EXIT_SUCCESS);
    }
    At the moment, when I run the program, it asks the user to specify which file they would like to load, but, when I enter the name of the file, I get the error message,
    The following error occurred: no such file or directory
    Value of errno: 2
    Apparently the program can't find the file I've asked it to load... I wonder if it's because I haven't put the .txt file in a place that the program can see?

    My root directory for the program is folder called cs237assignment- which currently contains three folders- build, dist and nbproject; the .c and .h files which are part of my program, and the fixed_1.txt file which I am trying to get it to load.

    Is this the right place to put the .txt file? Or should I put it somewhere else to make it visible to my program?

    Thanks for your help in advance!

  2. #2
    Registered User
    Join Date
    Sep 2008
    Posts
    200
    In the fopen() call:

    Code:
    file = fopen("fileName", "r"); /* Open the file specified by the user in 'read' mode*/
    You're not using your variable fileName - because it's in quotes it's trying to open a file that's literally called "fileName", which you don't have.

  3. #3
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    The text file should be in the same folder as your executable, at least for testing... otherwise your user has to enter a full path.

    Couple of obvious problems... (Referring to the code sample in message 1)

    Line 12 ... char line[100] will store only one line of text, 100 chars long. If you want multiple lines use char line[nLines][nLength]

    Line 22 ... unless your file is named "filename" that's not going to work.

    Lines 23 to 30 ... follow the logic of that very closely... it will correctly report an error if the file does not open... but what does it do when the file does open? OOPS...

    line 35 ... look up fscanf() in your documentation. I think you'll find it stops reading at the first invisible character (space, tab, return, etc.)

  4. #4
    Registered User
    Join Date
    Dec 2011
    Posts
    17
    Ok, thanks for pointing out that I was trying to open a string rather than the file my variable was referring to- I've corrected that.
    My next question is, now that my program is opening the .txt file, how do I get it to read the contents into structs that I have defined in a structs.h header file?

    The format of the data in the .txt file is such that the first line displays the date and time, with each element separated by a space (i.e. "07 12 2011 14 43 39").
    Then, the rest of the file displays a list of boats with their ID, latitude, longitude, course over the ground (in degrees) and speed over the ground (in knots).
    The date and time is on one line, and then each of the boats are on a separate line- so every item in the file is separated by a new line, with each of the attributes for each item separated by a space.

    I have two structs in my structs.h file: shipInfo and dateTime:

    shipInfo has attributes for ID (char), latitude, longitude, direction and speed (all of which are floats).
    dateTime has attributes for day, month, year, hour, minute, second (all of which are ints).

    Thanks for your help with this.

  5. #5
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Ok... If you want good answers please post your revised code, your struct definitions and a few sample lines from the file.

    Most of us here are pretty good at figuring stuff out but, far as I know, none of us are remote readers

    To give you some sense of it... based on the limited information you give...
    Code:
    struct t_data
      {
         float lat;
         float lon;
         float vel;
         float dir; 
       }
    
    struct t_data data[500];  //array of structs
    int i;     // loop index
    
    // open the file
    
    i = 0;
    
    while(fscanf(file,"%f %f %f %f", &data[i].lat, &data[i].lon, &data[i].vel, &data[i].dir) > 3)
      i++;
    
    
    // close the file
    I've just used a quicky stack array, for illustration purposes ... for the real task you may want something more sophisticated like an array started with malloc() and then adjusted with realloc() in blocks of 10 or 20 structs as your array grows.

  6. #6
    Registered User
    Join Date
    Dec 2011
    Posts
    17
    So this is my structs.h file:
    Code:
    #ifndef STRUCTS_H
    #define    STRUCTS_H
    
    #ifdef    __cplusplus
    extern "C" {
    #endif
    
    typedef struct{
        char AISID[10];
        float latitude;
        float longitude;
        float direction;
        float speed;
    }shipInfo; /* Create a structure that will store all of the info for each individual ship */
    
    typedef struct{
        int day;
        int month;
        int year;
        int hour;
        int minute;
        int second;    
    }dateTime; /* Create a structure that will store the date and time for the ships in a file
    
    
    #ifdef    __cplusplus
    }
    #endif
    
    #endif    /* STRUCTS_H */
    and my main.c now looks like this:
    Code:
    int main(int argc, char** argv) {
        
        char text[500]; /* Create a character array that will store all of the text in the file */
        char line[100]; /* Create a character array to store each line individually */
        
        FILE *file; /* Create a pointer to the file which will be loaded, to allow access to it */
        char fileName[30]; /* Create a character array to store the name of the file the user want to load */
        
        
        printf("Enter the name of the file containing ship information: ");
        scanf("%s", fileName);
        
        /*Try to open the file specified by the user. Use error handling if file cannot be found*/
        file = fopen(fileName, "r"); /* Open the file specified by the user in 'read' mode*/
        if(file == NULL){
            perror("The following error occurred: ");
            printf("Value of errno: %d\n", errno);
        }
        else {
            printf("File loaded. "); /* Display a message to let the user know 
                                  * that the file has been loaded properly */
        }
        while(fgets(line, 100, file)!="\n"){
            
        }
        
        /*
        fscanf(file, "%s", text); /* Read all the text from the file and store in the character array 'text' 
        printf(text); /* print out the contents of the 'text' array to show that the info is being saved there 
        */
        
       fclose(file);
            return 0;
        return (EXIT_SUCCESS);
    }
    If I'm right, I need to insert code into the while loop at the end of my main method, which will read a line of text, then use strtok to split the line up into tokens, and store each token into one of the variables in one of the structs.

    Only the first line of data in the .txt file will be stored in the 'dateTime' struct, and each subsequent line will be stored in the 'shipInfo' struct.

    An example of the first few lines in the .txt file:

    13 11 2011 13 04 00
    GW1927 52.408 -4.117 1.000 0.000
    GS452 51.750 -4.300 5.000 10.000

  7. #7
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    fgets() already stops at the first newline char it finds, so change your while loop to:

    Code:
    while((fgets(buffer, sizeof(buffer), filePointer)) != NULL) 
    {
         //your code
    }
    Where "buffer" is your char array to hold the line of text, and filePointer is the name of your file pointer.

    And use sscanf() from there, on your buffer, to pick out the input you want - I wouldn't use strtok. You have a fixed format, so sscanf() itself, will do nicely.

  8. #8
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by someone2088 View Post
    If I'm right, I need to insert code into the while loop at the end of my main method, which will read a line of text, then use strtok to split the line up into tokens, and store each token into one of the variables in one of the structs.

    Only the first line of data in the .txt file will be stored in the 'dateTime' struct, and each subsequent line will be stored in the 'shipInfo' struct.

    An example of the first few lines in the .txt file:
    Well that is one way of doing it but it tends to be slowish and the values in each token-string will still need coversion from text to storage format. A far simpler method would be to read the file with fscanf() as I described in message #5. If you prefer to use fgets() to read a line at a time, you can use the same concept except with sscanf() operating on your line buffer.

    If you don't already have the documentation for your compiler and it's libraries, you should acquire them... look up the scanf() family of functions and see what they can (and can't) do for you.

  9. #9
    Registered User
    Join Date
    Dec 2011
    Posts
    17
    Thanks for your reply.

    It's been about 2 years since I last used C, so I'm not too sure of how to use sscanf(), is it just a case of:

    sscanf(arrayElementToWriteTo, stringElementToWriteToArray);

    Or what it the correct way to use sscanf? Thanks!

  10. #10
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by someone2088 View Post
    Thanks for your reply.

    It's been about 2 years since I last used C, so I'm not too sure of how to use sscanf(), is it just a case of:

    sscanf(arrayElementToWriteTo, stringElementToWriteToArray);

    Or what it the correct way to use sscanf? Thanks!
    This is why I suggested you make an effort to download the documentation for your compiler's libraries... This will give you exact information, including minor variances, about the function and it's correct use (well, all of them, actually).

    If you're on Pelles C (like me)... just put the cursor on scanf(), sscanf() etc. and press F1... what a dream setup that is!

    If you're on most Linux systems... man 2 scanf should fetch the info for you (If memory serves)

    If you're not (like most)... you may need to go to your compiler's home page and manually download the documentation.

    Alternatively ... CLICK ... but this is generic information, which may not be as accuate as your compiler's own stuff.

  11. #11
    Registered User
    Join Date
    Dec 2011
    Posts
    17
    I'm on Sun Solaris, using NetBeans. Apparently the server has two compilers installed- SunStudio cc compiler and gcc; NetBeans can access both compilers.

  12. #12
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by someone2088 View Post
    I'm on Sun Solaris, using NetBeans. Apparently the server has two compilers installed- SunStudio cc compiler and gcc; NetBeans can access both compilers.
    So try ... man 2 scanf ... from the command line and see what happens.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Reading data from Text File
    By DarrinTE in forum C Programming
    Replies: 8
    Last Post: 03-25-2011, 03:11 PM
  2. reading text file to struct help needed!
    By werdy666 in forum C++ Programming
    Replies: 2
    Last Post: 01-25-2009, 11:37 AM
  3. Reading data from a text file
    By Dark_Phoenix in forum C++ Programming
    Replies: 8
    Last Post: 06-30-2008, 02:30 PM
  4. Reading in data from Text file
    By fortune2k in forum C Programming
    Replies: 214
    Last Post: 04-10-2008, 11:12 AM
  5. Using fscanf for reading numerical data from text file
    By Unregistered in forum C Programming
    Replies: 2
    Last Post: 06-15-2002, 05:18 PM