Thread: Read file data and store to an array

  1. #1
    Registered User
    Join Date
    Mar 2021
    Posts
    9

    Smile Read file data and store to an array

    Hi everyone,

    I am a bit new with C and I am trying to read a file which is (x,y) coordinates and store them individually into an array for further calculations on x or y.

    Code:
    case 1:
                
                FILE *fptr;
                int num;
                num = 0;
    
    
                printf("Please enter the name of the file to open: ");
                fscanf(stdin,"%s", file);
                fptr = fopen(file, "r");
    
    
                if (fptr == NULL)
                {
                    printf("Unable to open %c", file);
                    exit(1);
                }
    
    
                struct Coord coords[20];
                while (!feof(fptr))
                {
                    fscanf(fptr, "%d %d ", &coords[i].x, &coords[i].y);
                    i++;
                }
                     
                printf("\n");
    The code above is what I have tried which doesn't print anything.

    The file (part of it-with 15 rows including the x,y)looks like this:

    x y
    5 7
    15 4
    7 2
    10 6

    Can someone help me understand what I am doing wrong and I should do. I have been stuck on this for couple hours. Thank you

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    Quote Originally Posted by aidan4
    The file (part of it-with 15 rows including the x,y)looks like this:

    x y
    5 7
    15 4
    7 2
    10 6
    That's a problem: your file format contains a header, but you're reading it as if there was no header.

    I might suggest parsing it like this:
    Code:
    int read_coords(FILE *fptr, struct Coord coords[], int max_num)
    {
        char header[BUFSIZ];
        if (!fgets(header, BUFSIZ, fptr))
        {
            return -1;
        }
        if (strcmp(header, "x y\n") != 0)
        {
            return -1;
        }
    
        int num = 0;
        while (num < max_num && fscanf(fptr, "%d %d", &coords[num].x, &coords[num].y) == 2)
        {
            ++num;
        }
        return num;
    }
    So -1 is used as a sentinel value to indicate an error, otherwise you return the number of coordinates successfully read. Notice that I include the max_num parameter so that you can avoid buffer overflow.

    Moreover, I suggest wrapping the entire snippet of code into a function that calls read_coords (and possibly other functions). This would be helpful for organising your code rather than trying to write everything in a huge switch which I suspect you're doing, and also makes your variables more local so it is easier to see what you're doing, e.g., you presumably declared the variable named file, but the declaration is far away so you excluded it from your code snippet.

    Speaking of that variable, this is vulnerable to buffer overflow:
    Code:
    fscanf(stdin,"%s", file);
    If you really want to use fscanf with %s, then you need to specify the field width, e.g.,
    Code:
    fscanf(stdin, "%255s", file);
    where file is an array of 256 chars. You should also check the return value of fscanf before proceeding to use the value read.

    Quote Originally Posted by aidan4
    The code above is what I have tried which doesn't print anything.
    You aren't actually printing anything other than prompts and error messages (and an easily missed newline) in the code you showed though. If no prompt is printed, then it implies that this code is not even being run.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Mar 2021
    Posts
    9
    Is max_num param represent the number of coordinates that the file has?

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    No, it represents the maximum number of coordinates that will be read from the file. Ideally this will be equal to the number of coordinates in the file.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User
    Join Date
    Mar 2021
    Posts
    9
    Thank you for your response and helping me. I have tried the function and declared the num_max to be 15 as the file has 15 coordinates. I also added a printf at the end of the function to be able to print the values but I am not getting anything. May I know what's wrong with what I did?
    Code:
    int read_file(FILE *fptr, struct Coord coords[],int num_max){
        char ch[256];
        int num, i;
        num = 0;
    
    
        
        if (!fgets(ch,256,fptr))
        {
            return -1;
        }
        
        if (strcmp(ch, "x y\n") != 0)
        {
            return -1;
        }
    
    
        while (num< num_max && fscanf(fptr, "%d %d", &coords[num].x, &coords[num].y)==2)
        {
            ++num;
    
    
        }
    
    
        for (i = 0; i < num_max; i++)
        {
            printf(">>%d %d ", coords[i].x, coords[i].y);
        }
    
    
    
    
        fclose(fptr);
        return num;
    }
    and this is where I called it in the main function:
    Code:
    FILE * fptr;
                printf("Please enter the name of the file to open: ");
                fscanf(stdin, "%255s", file);
                fptr = fopen(file, "r");
                read_file(fptr,coords,maxNum);
    Last edited by aidan4; 03-05-2021 at 03:05 PM.

  6. #6
    Registered User
    Join Date
    Mar 2010
    Posts
    583
    That looks like it should work.

    What does read_file return? There are several code paths that could result in it printing nothing. The two error exits from read_file, and the situation where num stays as 0 because the fscanf hasn't matched any numbers. It could be something as simple as you having input the filename incorrectly.

    I think you should reinstate the check you had to start with with to make sure the fopen has succeeded, and add a couple of printfs in each of the other error returns to see what went wrong.

    One other thing to know is that printf can buffer its output and not print it straight to the screen if there are no newlines in the output. That could be happening here. I'd follow the loop with a printf("\n"), but you can also call fflush(stdout) if you really want to avoid having a newline for some reason.

  7. #7
    Registered User
    Join Date
    Mar 2021
    Posts
    9
    the function actually doesn't return anything. What would cause fscanf not to match any numbers? The file is being opened successfully. I checked that part

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    Well, I wrote the code in post #2 as an example intended to be adapted, so I did not compile and test it, hence it is possible that it might contain a bug or two. I decided to write a program to test it:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    struct Coord
    {
        int x;
        int y;
    };
    
    int read_coords(FILE *fptr, struct Coord coords[], int max_num)
    {
        char header[BUFSIZ];
        if (!fgets(header, BUFSIZ, fptr))
        {
            return -1;
        }
        if (strcmp(header, "x y\n") != 0)
        {
            return -1;
        }
    
        int num = 0;
        while (num < max_num && fscanf(fptr, "%d %d", &coords[num].x, &coords[num].y) == 2)
        {
            ++num;
        }
        return num;
    }
    
    void print_coords(FILE *fptr, const struct Coord coords[], int num)
    {
        fprintf(fptr, "x y\n");
        for (int i = 0; i < num; ++i)
        {
            fprintf(fptr, "%d %d\n", coords[i].x, coords[i].y);
        }
    }
    
    int main(void)
    {
        const char *filename = "input.txt";
        FILE *fp = fopen(filename, "r");
        if (!fp)
        {
            fprintf(stderr, "Error: could not open '%s'\n", filename);
            return EXIT_FAILURE;
        }
    
        struct Coord coords[15];
        int num = read_coords(fp, coords, 15);
        if (num < 0)
        {
            fprintf(stderr, "Error: '%s' is missing the header or has an invalid header\n", filename);
            fclose(fp);
            return EXIT_FAILURE;
        }
    
        fclose(fp);
    
        print_coords(stdout, coords, num);
    
        return 0;
    }
    Using a file with this context as input.txt:
    Code:
    x y
    5 7
    15 4
    7 2
    10 6
    Compiling and running the above program prints this result:
    Code:
    x y
    5 7
    15 4
    7 2
    10 6
    which is exactly as expected, so there is no bug in my example from post #2 that would result in the lack of output you observed.

    Therefore, if you want further help in debugging, I suggest that you post the smallest and simplest compilable program that demonstrates this lack of output that you're observing.

    EDIT:
    Quote Originally Posted by aidan4
    the function actually doesn't return anything.
    That's obviously false: it returns the number of coordinates successfully read so that the caller can then use that number when working with the array of coordinates. Or, if there is an error, it returns -1, hence you need to check that the function does not return -1 before you go on to use the coordinates read. You can see an example of how that is done in my code above.
    Last edited by laserlight; 03-05-2021 at 05:40 PM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Mar 2021
    Posts
    9
    Thank you again for your response. I tried to implement your code to see how it works and try to implement mine based on that. However, using yours the read_coords returns -1 from this
    Code:
    if(!fgets(header, BUFSIZ, fptr))    {
            return -1;
        }
    


    which I guess if I understand means it's not reading the char from the file

    Last edited by aidan4; 03-05-2021 at 06:44 PM.

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    Great. So now you need to check the file content: is it really what you expect it to be? For example, could it be tab separated instead of space separated?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    Registered User
    Join Date
    Mar 2021
    Posts
    9
    It is separated by tabs.

  12. #12
    Registered User
    Join Date
    Mar 2021
    Posts
    9
    How could I read the file if it is separated by tabs?

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    What does this do?
    Code:
    if (strcmp(header, "x y\n") != 0)
    {
        return -1;
    }
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #14
    Registered User
    Join Date
    Mar 2021
    Posts
    9
    It is comparing the two strings to see if they are equal, if not it returns -1

  15. #15
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    Yes. Do you understand why I put it there, and what the significance of the strings are?

    The easiest solution to your problem right now is to delete that code, but it is more important to understand than to just get it working without a clue.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Read data from file and store in array
    By meagangramlin in forum C++ Programming
    Replies: 1
    Last Post: 11-25-2020, 06:00 PM
  2. How to read file and store into an array
    By ec661 in forum C Programming
    Replies: 5
    Last Post: 05-06-2019, 02:47 AM
  3. Read text file, scan and store data into variables?
    By wisdom30 in forum C Programming
    Replies: 8
    Last Post: 04-18-2011, 11:23 PM
  4. Read text file and store it in an array
    By look2hook in forum C Programming
    Replies: 2
    Last Post: 12-03-2010, 11:47 PM
  5. read and store text file as an array
    By abotaha in forum C++ Programming
    Replies: 1
    Last Post: 08-02-2010, 08:57 PM

Tags for this Thread