Thread: Reading text file line by line and acting on each line...

  1. #1
    Registered User
    Join Date
    Dec 2010
    Posts
    4

    Reading text file line by line and acting on each line...

    Hi,

    Basically I'm trying to read a text file into a C program line by line and then act on each line.

    The text file I am reading looks like this:
    Code:
    RUN 5
    SET 1 1
    RUN 5
    SET 2 1
    RUN 5
    SET 1 0
    RUN 3
    SET 3 0
    RUN 2
    SET 2 0
    RUN 5
    Each line can have one of two formats; either SET 3 1, which is setting node 3 equal to 1. Or Run 5 which means run 5 times.

    I am trying to read in a line, store the 3 letter word (set or run) as a string, if it is "Set" then storing the two numbers that follow, if it is "Run" then storing the one number that follows.

    The stored info can then be used to do the necessary processes.

    Any ideas?

    I've already had a play around with fgets, fread and fscanf but to no avail. Here is a piece of code I used earlier in the program to read in data from a slightly different text file and store it in structures:
    Code:
     
        typedef struct
            {
             char GateType[4];
             int OutputNode;
             int InputNode1;
             int InputNode2;
            } LogicGate;
    
    ...
    
    while(fscanf(fp, "%s %d %d %d", &LogicGates[index].GateType, &LogicGates[index].OutputNode, &LogicGates[index].InputNode1, &LogicGates[index].InputNode2) == 4)
    This worked fine and was easy because of the uniformity of that file..
    AND 6 1 3
    XOR 5 3 4
    AND 7 5 2
    XOR 8 6 7
    where each line had four components.

    Is there a way of modifying this to suit? or do I need to do something completely different?

    Thanks,

  2. #2
    Registered User
    Join Date
    May 2010
    Location
    Naypyidaw
    Posts
    1,314
    Read a word. scanf %s does that.
    Depending on the word(RUN,SET), you know how many more input to read.

    Eg.

    Code:
    char command[21];
    while( scanf("%20s",command) != EOF ) {
      if( strcmp(command,"RUN") == 0 ) {        // RUN 
             ret =  scanf("%d %d",&node,&value);
       } else if( ... ) {
    
      }
    }

  3. #3
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    IF you know that the format isn't going to get too crazy from here, you can just do
    Code:
    fscanf("%s %d %d", this, &that, &theother);
    because scanf will just simply not load in a second number if it's not there.

    OR, you can read in a line with fgets, parse the word at the front of the line, and then call an appropriate sscanf depending on what that word is.

  4. #4
    Registered User
    Join Date
    May 2010
    Location
    Naypyidaw
    Posts
    1,314
    because scanf will just simply not load in a second number if it's not there.
    Is it? But i don't think so.

  5. #5
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by Bayint Naung View Post
    Is it? But i don't think so.
    Is it what?
    data.txt
    Code:
    SET 10 4
    RUN 5
    SET 3 3
    check.c
    Code:
    #include <stdio.h>
    
    int main(void) {
        FILE *fp;
        char word[4];
        int first, second;
        fp = fopen("data.txt", "r");
        while (fscanf(fp, "%s %d %d", word, &first, &second) > 0) {
            printf("Word: %s  First: %d  Second: %d\n", word, first, second);
        }
        fclose(fp);
        return 0;
    }
    Run and be amazed.

  6. #6
    Registered User
    Join Date
    May 2010
    Location
    Naypyidaw
    Posts
    1,314
    Nothing to be amazed.
    It works since scanf() %d stops when encountering letter on next line, and it pushes back (ungetc()). the character.
    If next line is allowed to start with number(not OP requirement though), the code won't work.
    Edit: ok provided that you did mention,
    >IF you know that the format isn't going to get too crazy from here, you can just do
    your solution is simpler for OP if format is simple.
    Last edited by Bayint Naung; 12-13-2010 at 09:39 AM.

  7. #7
    Registered User
    Join Date
    Dec 2010
    Posts
    4
    Thankyou so much, both of you.

    It works a treat

  8. #8
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    Since your file is line oriented, I would go with a safer solition just in case a line contains wonkiness.
    Code:
    #define BUF_SIZE 255
    char *pnt, buffer[BUF_SIZE + 1];
    int got;
    char cmd[11];
    ...
    for (...) {
        if (!fgets(buffer, BUF_SIZE, fh))
            break;
        if (!(pnt = strchr(buffer, '\n'))) {
            printf("No end-of-line detected. Too long for buffer or file terminates prematurely.\n");
            exit_slow();
            }
        *pnt = '\0';
        got = sscanf(buffer, "%.10s %d %d %d", cmd, &num1, &num2, &num3);
        ...
        }
    I'd have to check whether %.10s is the correct way to limit the number of bytes saved into cmd... But you could do that.
    Then you check if got has whatever number of parameters expected... num1, num2, num3 values may be invalid based on that.
    Last edited by nonoob; 12-13-2010 at 02:18 PM.

Popular pages Recent additions subscribe to a feed

Tags for this Thread