cfileioscanftxt

Trying to read txt file line by line in C Language


Basically my input file is in the format:

I 15 3 15 10 10 20  
S -5 3 15 82  
I -20 80 -4 10  
S 4 -20 8

The number of ints in a row can vary, but there is always one char at the beginning of each row

Based off the char value, 'I' or 'S', I insert or search for the given integers in that respective row. Seen as there is no EOL condition similar to EOF, how would I go about stopping at the end of the line? Ideally I would like to use fscanf.

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

void readFileLines(char** argv)
{
    FILE* fp = fopen(argv[1], "r");
    char read;
    while(fscanf(fp, "%c\t", &read) != EOF)
    {
        //scan first letter in line until EOF
        if(read == 'I')
        {
            //loop through all values in Line
            int data;
            printf("Inputting...");
            while(fscanf(fp, "%i\t", &data) != EOL) //ERROR (EOL DOESNT WORK)
            {
                //iterate rest of line values til end of line
                printf("%d\t", data);
                
            }
        }
        else if(read == 'S')
        {
            int data;
            printf("Searching...");
            while(fscanf(fp, "%d\t", &data) != EOL) // ERROR (EOL DOESNT WORK)
            {
                printf("%d\t", data);
          
            }
        }

        printf("\n");
        //iterate through to next line in order to scan different letteer
    }
   }

int main(int argc, char** argv)
{
    
     readFileLines(argv);

    return EXIT_SUCCESS;
}

I heard that fgets could be useful in this scenario by utilizing the \n at the end of each line as a way to indicate when the line ends, but I'm not too sure how that method works. Please let me know!


Solution

  • I heard that fgets could be useful in this scenario by utilizing the \n at the end of each line as a way to indicate when the line ends, but i'm not too sure how that method works.

    fgets(), sometimes in combination with sscanf(), is pretty widely recommended as superior to fscanf(), especially for line-based input. You can find documentation for it on line, in a variety of places.

    But in your particular case, you don't actually have to consider your input as a series of lines. You can instead consider it as a sequence of individual, whitespace-separated input items, some of them numbers, and others an 'I' or 'S' character. Reading one field at a time via fscanf is fairly approachable here, with many fscanf pitfalls mooted, and you would not have the disadvantage of worrying about line length. You would want here to take better advantage of fscanf()'s return value, which does not only signal end-of-input, but in other cases tells you how many input items were successfully scanned and converted.

    Thus, you might do something like this:

        char c;
    
        // expecting I or S:
        int num_items = fscanf(fp, " %c", &c);
        if (num_items == 1) {
            // successfully read an 'I' or an 'S' ...
        } else if (num_items == EOF) {
            // end of input ...
        } else {
            // invalid input ...
        }
    

    ... and like this:

        // expecting numbers:
        // loop:
            int num;
            num_items = fscanf(fp, "%d", &num);
            if (num_items == 1) {
                // successfully read one number ...
            } else if (num_items == EOF) {
                // end of input ...
            } else {
                // Probably an 'I' or 'S' (which remains unread) -- end of record ...
            }