1

I'm new at programming so there are some basics and maybe common sense that I don't know. I have a question about how to use fgets right. Based on the explanation of fgets, it seems that fgets should stop whenever it reads n-1 characters, hit the EOF or hit a newline character. For example, I create a text file like below:

red  100
yellow  400
blue  300
green 500
purple 1000
...

The color and the integer is separated by a tab. When I create this text file, I need to hit enter at the end of each line to start a new line. In this case, hitting enter equals to add a newline character, '\n', is that right?

If it is right that there is a '\n' at the end of each line, I run the fgets code as below:

fgets(string, 100, fp);

Since the characters contain in each line is much less than 100, the fgets should hit the newline character before reach the maxlength limit and it should stop and return a NULL. Is that correct?

If my understanding above are not right, there is no '\n' at the end of each line, or fgets does not stop at the end of each line, what is the number of maxlength (i.e., the N in the fgets(string, N, stream) function) should I pick to make sure that the file input properly due to my ultimate goal is to parsing each line and store each line into a structure. By the way, there are 100 lines in the file.

Renix
  • 23
  • 1
  • 1
  • 5
  • Your question is unclear. What do you mean "generate a .txt file"? Show some example code, break that chunk of text down into readable paragraphs, make it more accessible to us. Ask as tersely as you possibly can. – cadaniluk Jan 27 '17 at 20:30
  • The number you should pick for `n` in `fgets` is the number of bytes length of the buffer. If that limit is reached before the EOL in the file, then no `newline` will be at the end of the input string, and the next call to `fgets` will continue from the same place in the file. But the question is a muddle. Output is not input. – Weather Vane Jan 27 '17 at 20:35
  • C is for low level programming, you don't have strings, you have an array of chars (with constant size) or char pointer (that you need to allocate memory to store chars), the `n` you send in fgets should not be bigger than the size allocated in the var for the array of chars, so it works as a limit. – cpatricio Jan 27 '17 at 20:35
  • 2
    @cpatricio C has _strings_. They are sequences of characters with a null character at the end. – chux - Reinstate Monica Jan 27 '17 at 20:55
  • 1
    "What the number should I pick for n if I don't know how many characters will be included in each line?" --> As some point, robust code need to assess if it being hacked. If code imposes no limit, then a call to `my_favorite_input_function()` allows outside agents to overwhelm system resources. Pick a large `n` - suggest twice as large as suggested by the programs needs: `#define LINE_SIZE 1000` or 80 or 8675309 and deem any input where `(strlen(buffer) >== LINE_SIZE - 1)` is true as nefarious and exit with a failure. – chux - Reinstate Monica Jan 27 '17 at 21:06
  • 1
    This post has at least 5 far ranging questions. Suggest narrowing it and posting what you have attempted. – chux - Reinstate Monica Jan 27 '17 at 21:17
  • @DavidBowling [Yes](https://en.wikipedia.org/wiki/867-5309/Jenny) `#define JENNY 8675309` – chux - Reinstate Monica Jan 28 '17 at 04:50

3 Answers3

3
 #include <stdio.h>

 int main()
 {
    char str[150],str2[100][150];
    int i=0,j=0,value[100];
    FILE* fp;
    fp = fopen("file.txt", "r");
    while (fgets(str,150, fp)) {
        i++;
        printf("%3d: %s\n", i, str);
        /** if you want to split value and string*/
        sscanf(str,"%s %d",&str2[j],&value[j]);
        printf("%d %s\n",value[j],str2[j]);
        j++;
    }
    fclose(fp);
    return 0;
}

You can use sscanf() to easily split values and fgets() to read file.

Sayed Sohan
  • 1,385
  • 16
  • 23
2
fp = fopen("sample.txt", "r");
while (1) {
        if (fgets(line,150, fp) == NULL) break;
        i++;
        printf("%3d: %s", i, line);
}
printf("%d\n",i);
Teja
  • 13,214
  • 36
  • 93
  • 155
  • 3
    Shouldn't it be `while(!feof(fp))` or `while(fgets(..))`? I always think that it's a good habit to avoid statement like `break` and `continue` whenever possible. – Claudio Cortese Jan 27 '17 at 20:35
  • 6
    @ClaudioCortese it should be the latter. Please see [Why is “while ( !feof (file) )” always wrong?](http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) – Weather Vane Jan 27 '17 at 20:41
  • 2
    Post the definition of `line` to bring clarity to `fgets(line,150, fp)`. – chux - Reinstate Monica Jan 27 '17 at 20:51
  • @chux What should be clarified? It is obvious that `line` is a c-string of size 150 – Claudio Cortese Jan 27 '17 at 22:49
  • 3
    @ClaudioCortese OP is "new at programming", hence the post. OP may not realized array size requirements, be off by one, or may think a pointer will do. or others. Posting a solution that shows proper usage clarifies the answer as many things are not obvious to those new with C. – chux - Reinstate Monica Jan 27 '17 at 23:10
1
// hello.c
//
// Usage:
//
// gcc -Wall hello.c && ./a.out /tmp/somefile.txt

#include <stdlib.h>     // for perror, ...
#include <stdio.h>      // for printf, ...
#include <assert.h>     // for assert
#include <sys/time.h>   // for gettimeofday

static inline long long int nowUs () {
  long long int now;
  struct timeval timer_us;
  if (gettimeofday(&timer_us, NULL) == 0) {
    now = ((long long int) timer_us.tv_sec) * 1000000ll +
      (long long int) timer_us.tv_usec;
  }
  else now = -1ll;

  return now;
}

int main (const int argc, const char * argv[]) {
  assert(2 == argc);
  long long int started = nowUs();
  size_t count = 0;
  char msg[128], * fgets_rv;
  FILE * fp = fopen(argv[1], "r");

  while ((fgets_rv = fgets(msg, sizeof(msg), fp))) {
    assert(fgets_rv == msg);
    count++;
  }
  if (ferror(fp)) 
    perror(argv[1]);
  else if (feof(fp)) {
    printf("Read %zu lines of file '%s' in %lldµs\n", 
        count, argv[1], nowUs() - started);
  }
  else {
    printf("UNEXPECTED\n");
  }
  fclose(fp);
  return 0;
}

Sample output:

alec@mba ~/process/sandbox $ gcc -Wall hello.c && ./a.out /tmp/bigfile.t02
Read 100000 lines of file '/tmp/bigfile.t02' in 16521µs
Did Alik
  • 199
  • 2
  • 7