Reading from file in C

Thread Starter

Dritech

Joined Sep 21, 2011
869
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:
while(index != EOF)
  {
      index = fgetc(filePointer);
      putchar(index);
  }
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:

Thread Starter

Dritech

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

#include<stdio.h>


Code:
 int main()
   {
       FILE *ptr_file;
       char buf[1000];
       ptr_file =fopen("file.txt","r");
       if (!ptr_file)
       return 1;
       while (fgets(buf,1000, ptr_file)!=NULL)
       printf("%s",buf);
     fclose(ptr_file);
       return 0;
   }
Should I use this to achieve what I want?
 

Papabravo

Joined Feb 24, 2006
13,924
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.
 

Papabravo

Joined Feb 24, 2006
13,924
I found this code which reads line by line instead of character by character:

#include<stdio.h>


Code:
 int main()
   {
       FILE *ptr_file;
       char buf[1000];
       ptr_file =fopen("file.txt","r");
       if (!ptr_file)
       return 1;
       while (fgets(buf,1000, ptr_file)!=NULL)
       printf("%s",buf);
     fclose(ptr_file);
       return 0;
   }
Should I use this to achieve what I want?
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.
 

djsfantasi

Joined Apr 11, 2010
6,504
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:
#include <SD.h>
#include<SPI.h>

void setup() {
  // put your setup code here, to run once:

}

String  readln(File filePtr)
/*
   Function to read a line from a file;
   skipping lines which begin with '\'
  
   Any non-printable characters are ignored, such as a CR
   Hence, the end of line is defined as ending with LF
*/
{
  String inputstring="";
  byte inputchar;
  boolean Done=false;
  boolean endofline=true;

  inputchar='\0';

  while ((! Done) && (filePtr.available())) {
    inputchar=filePtr.read();
    if ((inputchar=='/') && endofline) {
    // skip character found, have chars for number
      while ((inputchar != '\10') && (filePtr.available())) {
        inputchar=filePtr.read();
        endofline=true;
        }
    } else {
      if (inputchar == 10 ) {
        // EOL found; last number found
        Done = true;
      } else {
        if (inputchar >= '\32' && inputchar <='\126') {
           // character is printable; append to string. convoluted Arduino code.
           inputstring=String(inputstring+String(char(inputchar)));
       } else { 
         }
        }
       } 
      }
  return inputstring;
}

void loop() {
  // put your main code here, to run repeatedly:

}
 

Thread Starter

Dritech

Joined Sep 21, 2011
869
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
 

Thread Starter

Dritech

Joined Sep 21, 2011
869
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:
#include <stdio.h>

      
        token = strtok(NULL, s);
    }
 
       return 0;
   }
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:

Thread Starter

Dritech

Joined Sep 21, 2011
869
Use the library function "strtok" with semicolon as a delimiter.
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)
 

Thread Starter

Dritech

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

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

Papabravo

Joined Feb 24, 2006
13,924
You could also use a literal string in the function call. Example:
Code:
unsigned char buf[81] ;

    strtok(buf, ",;/") ;
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:
unsigned char buf[81] ;

    strtok(buf, DELIM) ;
 

Papabravo

Joined Feb 24, 2006
13,924
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.
 

WBahn

Joined Mar 31, 2012
25,911
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.
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.
 

WBahn

Joined Mar 31, 2012
25,911
Thanks for the replies.

In line " while (fgets(buf,1000, ptr_file)!=NULL) " what is happening exactly?

(code from: http://www.codingunit.com/c-tutorial-file-io-using-text-files )

Is it checking for end of single line or for EOF?
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.
 
Top