Reading from file in C

Discussion in 'Programmer's Corner' started by Dritech, Apr 2, 2015.

  1. Dritech

    Thread Starter Well-Known Member

    Sep 21, 2011
    756
    5
    Hi all,

    I am trying to read from a text file in C. So far I managed to read all the contents of the text file using the code below:

    Code (Text):
    1. while(index != EOF)
    2.   {
    3.       index = fgetc(filePointer);
    4.       putchar(index);
    5.   }
    Is there a way to skip lines starting with a particular symbol (example skip all lines starting with the / symbol) ?

    Any help would be appreciated.
     
    Last edited: Apr 2, 2015
  2. Dritech

    Thread Starter Well-Known Member

    Sep 21, 2011
    756
    5
    I found this code which reads line by line instead of character by character:

    #include<stdio.h>


    Code (Text):
    1.  int main()
    2.    {
    3.        FILE *ptr_file;
    4.        char buf[1000];
    5.        ptr_file =fopen("file.txt","r");
    6.        if (!ptr_file)
    7.        return 1;
    8.        while (fgets(buf,1000, ptr_file)!=NULL)
    9.        printf("%s",buf);
    10.      fclose(ptr_file);
    11.        return 0;
    12.    }
    Should I use this to achieve what I want?
     
  3. Papabravo

    Expert

    Feb 24, 2006
    10,135
    1,786
    Since you are looking at the characters one at a time, you have to process them one at a time. So the first thing you have to do is check for the skip character. It might be the first character of the first line so that is a special case. All the other skip characters will follow an end of line character, a newline (0x0A) or a CRLF (0x0D, 0x0A). Once you see the skip character you consume characters and throw them on the floor until the next end of line.
     
  4. Papabravo

    Expert

    Feb 24, 2006
    10,135
    1,786
    You can use that if you want. What happens if the file has a line longer than 1000 characters? The character by character approach does not suffer from that problem.
     
  5. djsfantasi

    AAC Fanatic!

    Apr 11, 2010
    2,793
    829
    Here's some sample code from an Arduino. It's C is a little different, so the code may look 'funny'. However, the function will read and return a line from the file, ignoring all lines that begin with a '/'. Note that when it finds a line that starts with a slash, it keeps reading and discarding characters until the next line is read (and will skip if...)

    Another way to approach it is to read the line into a buffer, as your example code above and discard it if the first character is a '/'. You can get it in that example, by testing buf[0].

    Code (Text):
    1.  
    2. #include <SD.h>
    3. #include<SPI.h>
    4.  
    5. void setup() {
    6.   // put your setup code here, to run once:
    7.  
    8. }
    9.  
    10. String  readln(File filePtr)
    11. /*
    12.    Function to read a line from a file;
    13.    skipping lines which begin with '\'
    14.  
    15.    Any non-printable characters are ignored, such as a CR
    16.    Hence, the end of line is defined as ending with LF
    17. */
    18. {
    19.   String inputstring="";
    20.   byte inputchar;
    21.   boolean Done=false;
    22.   boolean endofline=true;
    23.  
    24.   inputchar='\0';
    25.  
    26.   while ((! Done) && (filePtr.available())) {
    27.     inputchar=filePtr.read();
    28.     if ((inputchar=='/') && endofline) {
    29.     // skip character found, have chars for number
    30.       while ((inputchar != '\10') && (filePtr.available())) {
    31.         inputchar=filePtr.read();
    32.         endofline=true;
    33.         }
    34.     } else {
    35.       if (inputchar == 10 ) {
    36.         // EOL found; last number found
    37.         Done = true;
    38.       } else {
    39.         if (inputchar >= '\32' && inputchar <='\126') {
    40.            // character is printable; append to string. convoluted Arduino code.
    41.            inputstring=String(inputstring+String(char(inputchar)));
    42.        } else {
    43.          }
    44.         }
    45.        }
    46.       }
    47.   return inputstring;
    48. }
    49.  
    50. void loop() {
    51.   // put your main code here, to run repeatedly:
    52.  
    53. }
    54.  
    55.  
     
  6. Dritech

    Thread Starter Well-Known Member

    Sep 21, 2011
    756
    5
    Thanks for the replies.
    I did manage to eliminate lines by modifying the code in post #2.
    Now I have another problem.
    I am scanning/reading line by line form the text file. Each line is being stored in an array.
    Now lets say I have "50;20;30" in the array, how can I store each value in different integers?

    i.e.
    int a = 50
    int b = 20
    int c = 30
     
  7. djsfantasi

    AAC Fanatic!

    Apr 11, 2010
    2,793
    829
    How is your array defined? Does each entry hold three values?
     
  8. Papabravo

    Expert

    Feb 24, 2006
    10,135
    1,786
    Use the library function "strtok" with semicolon as a delimiter.
     
  9. Dritech

    Thread Starter Well-Known Member

    Sep 21, 2011
    756
    5
    The array is defined as char buf[1000];
    The character between the three integers can be either a semicolon or a comma.
    I found the 'strtok' function which may we used, but I only managed to sort the integers with one type of character. Below is the code that I used:

    Code (Text):
    1. #include <stdio.h>
    2.  
    3.      
    4.         token = strtok(NULL, s);
    5.     }
    6.  
    7.        return 0;
    8.    }
    9.  
    Note that this is the part where I tested the strtok and atoi functions.

    Is there a way where I can separate tokens with different characters and not just a comma ?
     
    Last edited: Apr 3, 2015
  10. Dritech

    Thread Starter Well-Known Member

    Sep 21, 2011
    756
    5
    I did make use of the strtok function, but I only managed to use one type of character as a delimiter. Is there a way to use more than one type (ex: comma and semicolon)
     
  11. Papabravo

    Expert

    Feb 24, 2006
    10,135
    1,786
    Dritech likes this.
  12. Dritech

    Thread Starter Well-Known Member

    Sep 21, 2011
    756
    5
    Thanks for the reply. I inserted the characters/symbols in the delimiter array.
    i.e. instead of writing:
    char s[] = ",";

    I wrote:
    char s[] = ",;/";
     
  13. Papabravo

    Expert

    Feb 24, 2006
    10,135
    1,786
    You could also use a literal string in the function call. Example:
    Code (Text):
    1.  
    2. unsigned char buf[81] ;
    3.  
    4.     strtok(buf, ",;/") ;
    5.  
    Remember the name of an array, buf, is a synonym for &buf[0]
    You could even use the literal string in 100 separate calls and the compiler would optimize that to a single pointer to a constant string. Sometimes clarity of that kind is helpful. The downside is to change 100 occurrences if you want to add a character.

    You could also #define DELIM ",;/" and call
    Code (Text):
    1.  
    2. unsigned char buf[81] ;
    3.  
    4.     strtok(buf, DELIM) ;
    5.  
     
  14. WBahn

    Moderator

    Mar 31, 2012
    17,715
    4,788
    That's why you would do

    #define DELIMITERS ",;/"

    and then use

    strtok(buf, DELIMITERS);
     
  15. Papabravo

    Expert

    Feb 24, 2006
    10,135
    1,786
    Of course. I grew up in the era of assembly language and limited length identifiers. No excuse for it anymore, and there hasn't been for decades.
     
  16. WBahn

    Moderator

    Mar 31, 2012
    17,715
    4,788
    Huh. I didn't see any part of your prior post after "... if you want to add a character." That's why I responded with what I did. Using DELIM is just fine, I just didn't see that you had suggested it.
     
  17. Papabravo

    Expert

    Feb 24, 2006
    10,135
    1,786
    It's all good, and you inadvertently made an extremely valuable point.
     
  18. Dritech

    Thread Starter Well-Known Member

    Sep 21, 2011
    756
    5
  19. Papabravo

    Expert

    Feb 24, 2006
    10,135
    1,786
    Any C-Library function will have a page like this one where you can instantly answer those questions
    http://pubs.opengroup.org/onlinepubs/009695399/functions/fgets.html

    Look at the heading "RETURN VALUE" and tell me what you find.

    Then look at the description and tell me how many characters does fgets(...) consume from the stream.
     
  20. WBahn

    Moderator

    Mar 31, 2012
    17,715
    4,788
    What fgets() does is it reads characters from a stream and copies them into a buffer. The number of characters copied is limited by one of three things, whichever happens first: (1) the buffer is filled, which is defined by having read (N-1) characters where N is the second parameter passed to the function (the Nth position is needed for the NUL string terminator); (2) a newline is read, in which case the newline is copied to the buffer as the last character (followed, of course, by the NUL); (3) the end of the file is reached.

    The function normally returns a pointer to the buffer. It will return NULL if either an error occurs or if the end of file was reached without reading any characters from the stream.

    When you read a line from a file using fgets(), if the entire line was read then it will end with a newline character ('\n') that usually needs to be stripped off before you process the line further. If the buffer does not end with a newline character, then you know that you only read part of the line before the buffer filled up and that it will take at least one more read to get the rest of the line.
     
Loading...