0

So I have the txt file from which I need to read the number of students written in that file, and because every student is in separate line, it means that I need to read the number of lines in that document. So I need to:

  1. Print all lines from that document

  2. Write the number of lines from that document.

So, I write this:

#include "stdafx.h"
#include <stdio.h>

int _tmain(int argc, _TCHAR* Argo[]){

    FILE *student;
    char brst[255];

    student = fopen("student.txt", "r");

    while(what kind of condition to put here?)
    {
        fgetc(brst, 255, (FILE*)student);
        printf("%s\n", brst);
    }

    return 0;
}

Ok, I understand that I can use the same loop for printing and calculating the number of lines, but I can't find any working rule to end the loop. Every rule I tried caused an endless loop. I tried brst != EOF, brst != \0. So, it works fine and print all elements of the document fine, and then it start printing the last line of document without end. So any suggestions? I need to do this homework in C language, and I am using VS 2012 C++ compiler.

Kamiccolo
  • 7,758
  • 3
  • 34
  • 47
DoktorD96
  • 21
  • 1
  • 7
  • 2
    Do you know the [`fgets` function](https://msdn.microsoft.com/en-us/library/c37dh6kf.aspx)? You can control a loop like this: `while(fgets(brst, sizeof brst, student) != NULL) { //... process }` – Weather Vane Oct 19 '16 at 19:13
  • **while(fgets(brst, sizeof brst, student) != NULL) ** I used this as a rule, and now it printed every second line?? – DoktorD96 Oct 19 '16 at 19:22
  • That is probably because your loop still contains its original char-by-char `fgetc`. – Weather Vane Oct 19 '16 at 19:29

3 Answers3

1

OP's code is close but needs to use fgets() rather than fgetc() and use the return value of fgets() to detect when to quit, it will be NULL @Weather Vane. Also add a line counter.

#include <stdio.h>

int main(void) {
  FILE *student = fopen("student.txt", "r");
  unsigned line_count = 0;
  if (student) {
    char brst[255];

    //  fgetc(brst, 255, (FILE*)student);
    while (fgets(brst, sizeof brst, student)) {
      line_count++;
      printf("%u %s", line_count, brst);
    }
    fclose(student);
  }
  printf("Line Count %u\n", line_count);
  return 0;
}
Community
  • 1
  • 1
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • 1
    @DoktorD96 please notice that chux has not put any `\n` newline in the first `printf` statement within the loop. This is because `fgets` adds any `newline` it finds, at the end of the input string. If you are storing data you will not want any `newline` present and an easy way to remove it is with `brst [ strcspn(brst, "\r\n") ] = 0;` – Weather Vane Oct 19 '16 at 20:28
0

Use feof() to check for an eof condition. You are correctly reading the file line-by-line, but use fgets(), not fgetc() - and the cast is not needed. Then use sscanf() to assign the line data to variables (or some "safe" form of it).

Constantine Georgiou
  • 2,412
  • 1
  • 13
  • 17
  • 1
    I am sorry, but [`feof`](https://msdn.microsoft.com/en-us/library/xssktc6e.aspx) does ***not*** check for an end of file condition. It is one if the most misused functions ever. Please see [Why is “while ( !feof (file) )” always wrong?](http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong). – Weather Vane Oct 19 '16 at 19:33
0

Try this:

#include "stdafx.h"
#include <stdio.h>
int _tmain(int argc, _TCHAR* Argo[]){
FILE *student;
char brst[255];
char* result = NULL;

  //Ensure file open works, if it doesn't quit
if ((student = fopen("student.txt", "r")) == NULL)
{
  printf("Failed to load file\n");
  return 1;
}

  //Read in the file
for ( (result = fgets( brst, sizeof(brst), student)); 
      !feof(student); 
      (result = fgets( brst, sizeof(brst), student)) )
{
  if ( result == NULL ) break; //I've worked on embedded systems where this actually ment waiting on data, not EOF, so a 'continue' would go here instead of break in that case
  printf("%s\n", brst);
}
fclose( student );
return 0;
}

feof() is only true after you've read past the end of the file. Using a for with two identical reads, and feof() on the conditional is a simple way to ensure you read the file as expected.

Luke Dupin
  • 2,275
  • 23
  • 30
  • 1
    But it is horrible way to go. – Weather Vane Oct 19 '16 at 19:31
  • Weather, why is it horrible? The code communicates the intentions clearly and is contained nicely. – Luke Dupin Oct 19 '16 at 19:36
  • 2
    I ran your code, and if the last line in the text file contains no `newline` ending, as it might not, the line is not displayed. Usually, one uses the `while(fgets(...) != NULL)` idiom without any `feof` malarky. – Weather Vane Oct 19 '16 at 19:43
  • `printf("%s\n", brst);` relies on the last call to `fgets( brst, sizeof(brst), student)` to have _not_ messed up `brst` and that `fgetc()` works at least one. That is not specified behavior. Use the return value from `fgets()` rather than `feof()` to detect when to finish the loop and do not rely on data in `brst` after that failed call. Code needs a modification. – chux - Reinstate Monica Oct 19 '16 at 20:00
  • Checking the fgets return value is important and I agree with that, I was in a hurry so I didn't add those. I however disagree with only using the return value of fgets(). One of the embedded systems I worked on had an implementations of fgets() that return NULL to mean waiting on data, not end of file. feof() always means end of file, thus why I use that. – Luke Dupin Oct 19 '16 at 22:30