最新消息:20190717 VPS服务器:Vultr新加坡,WordPress主题:大前端D8,统一介绍入口:关于

feof, fgets and fread

工作和技术 crifan 634浏览 0评论

feof, fgets and fread[ZT]

Prev: File Input and Output,
fopen and fclose

Next: rewind, fputc and fputs



Detecting the End of the File Using feof

Here’s a function you’ll be using in the future. You pass it a FILE pointer, and if you’ve reached the end of the file, feof returns 1, else it returns 0.

I’ll be using this function in the next section but in the meantime, There are a few more functions I’d like to cover…



Reading One Line at a Time Using fgets

Reading one character at a time can be a little inefficient, so we can use fgets to read 1 line at a time.

fgets takes three arguments. The first, has to be a char * – the name of a sized char array would work too. The second is an int – the maximum number of characters read per line.

The third and last, is a stream – a FILE * for example (try it with stdin and see what happens).

fgets returns NULL if the end of the file is reached, else it returns a char *.

You can’t use an !=EOF check here, as we’re not reading one character at a time (but you can use feof).

For this example, I made a file called numbers2.txt in Notepad:

111 222 333
444 555 666
777         888        999

Although it’s not obvious at first, I put tabs in the last line.

#include <stdio.h>

int main() {
  char c[10];  <em>/* declare a char array */</em>
  FILE *file;  <em>/* declare a FILE pointer  */</em>

  file = fopen(&quot;numbers2.txt&quot;, &quot;r&quot;); 
  <em>/* open a text file for reading */</em>

  if(file==NULL) {
    printf(&quot;Error: can't open file.n&quot;);
    <em>/* fclose(file); DON'T PASS A NULL POINTER TO fclose !! */</em>
    return 1;
  }
  else {
    printf(&quot;File opened successfully. Contents:nn&quot;);
    
    while(fgets(c, 10, file)!=NULL) { <em>
      /* keep looping until NULL pointer... */</em>
      printf(&quot;String: %s&quot;, c);  <em>      
      /* print the file one line at a time  */</em>
    }

    printf(&quot;nnNow closing file...n&quot;);
    fclose(file);
    return 0;
  }
}

Output:

File opened successfully. Contents:

String: 111 222 3String: 33
String: 444 555 6String: 66
String: 777      888      9String: 99

Now closing file...

The main area of focus is the while loop – notice how I performed the check for the return of a NULL pointer. Remember that passing in char * variable, c as the first argument assigns the line read into c, which is printed off by printf. I specified a maximum number of characters to be 10 – I knew the number of characters per line in my text file is more than this, but I wanted to show that fgets reads 10 characters at a time in this case.

Notice how fgets returns when the newline character is reached – this would explain why 444 and 777 follow the word "String". Also, the tab character, t, is treated as one character.



atoi Revisited

Notice how I’ve slipped in an extra lesson after the string section! I thought the atoi function would be especially useful when reading numerical data from an external text file.

So far, all the information extracted was returned as strings. If our text file contained numbers, we could use atoi to convert them into integer format for use in our program.

Now, fgets treats each line in your text file as a string (it stops reading when it finds a line break).

You could put each number on a separate line like this:

6
7
8
9
10

– I put this into a file called numbers3.txt so let’s get a program to add them up…

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt; <em>/* required for atoi */</em>

int main() {
  char c[10];     
  int sum = 0;
  FILE *file;  

  file = fopen(&quot;numbers3.txt&quot;, &quot;r&quot;);

  if(file==NULL) {
    printf(&quot;Error: can't open file.n&quot;);    
    return 1;
  }
  else {
    printf(&quot;File opened successfully.n&quot;);
    
    while(fgets(c, 10, file)!=NULL) { 
      sum += atoi(c); <em>/* convert string to int then add it to sum */</em>
    }

    printf(&quot;Now closing file...n&quot;);
    fclose(file);
    printf(&quot;The sum of the numbers is: %dn&quot;, sum);
    return 0;
  }
}

Output:

File opened successfully.
Now closing file...
The sum of the numbers is: 40

So it looks like atoi has worked. Sometimes you can compile without including stdlib.h but your compiler may display a warning – MSVC++ did in my case.



Reading Large Amounts at a Time Using fread

The last reading function reads the entire text file.

fread takes four arguments:

The first is a char * – this could be an actual char pointer or a char array. There are differences between the two, as we’ll see later.

The second argument is the size of char, i.e. 1.

The third argument in the number of elements to read. This only has an effect if you passed a char array as opposed to a char pointer.

The last argument is the FILE pointer.

fread returns the number of characters read if you passed it a char array.

<font color="#0000ff">#include &lt;stdio.h&gt;

int main() {
  FILE *file;
  char c[30]; <em>/* make sure it is large enough to hold all the data! */</em>
  char *d;
  int n;

  file = fopen(&quot;numbers.txt&quot;, &quot;r&quot;);

  if(file==NULL) {
    printf(&quot;Error: can't open file.n&quot;);
    return 1;
  }
  else {
    printf(&quot;File opened successfully.n&quot;);
    
    n = fread(c, 1, 10, file); </font><font color="#0000ff"><em>/* passing a char array, 
                                  reading 10 characters */</em>
    c[n] = '';              </font><em><font color="#0000ff"> /* a char array is only a 
                                  string if it has the</font></em><em>
<font color="#0000ff">                                  null character at the end */</font></em>
<font color="#0000ff">    printf(&quot;%sn&quot;, c);         <em>/* print out the string      */</em>
    printf(&quot;Characters read: %dnn&quot;, n);

    fclose(file);          <em>/* to read the file from the beginning, */</em>
<em>/* we need to close and reopen the file */</em>
    file = fopen(&quot;numbers.txt&quot;, &quot;r&quot;);

    n = fread(d, 1, 10, file);</font><em>
<font color="#0000ff">            /* passing a char pointer this time - 10 is irrelevant */</font></em>
<font color="#0000ff">    printf(&quot;%sn&quot;, d);
    printf(&quot;Characters read: %dnn&quot;, n);

    fclose(file);
    return 0;
  }
}</font>

Output:

File opened successfully.
111
222
33
Characters read: 10

111
222
333

444
5ive
Characters read: 10

I’ve explained most of the statements in the comments (that’s what comments are there for!).

Passing a char pointer reads in the entire text file, as demonstrated. Note that the number fread returns in the char pointer case is clearly incorrect. This is because the char pointer (d in the example) must be initialized to point to something first.

An important line is: c[n] = ''; Previously, I put 10 instead of n (n is the number of characters read). The problem with this was if the text file contained less than 10 characters, the program would put the null character at a point past the end of the file.

There are several things you could try with this program:

After reading the memory allocation section, try allocating memory for d using malloc() and freeing it later with free().

Read 25 characters instead of 10: n = fread(c, 1, 25, file);

Not bother adding a null character by removing: c[n] = '';

Not bother closing and reopening the file by removing the fclose and fopen after printing the char array.

Prev: File Input and Output,
fopen and fclose

Next: rewind, fputc and fputs

转载请注明:在路上 » feof, fgets and fread

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
56 queries in 0.123 seconds, using 18.85MB memory