0

I am reading a file called strings.txt into the c program. I am running this on Ubuntu. The function fgets() works but fgetc() always returns EOF instead of the char. What am I doing wrong?

I know that fgetc returns EOF if that point is reached or if there is an error somewhere. But where is the error?

The strings.txt file is included as the second file below.

#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define MAX 1024

void *num_substring(void *hold);

int total = 0;
int n1,n2;
char *s1,*s2;
FILE *fp;
int at;

int readf(FILE *fp)
{
    char c;
    int words = 1;

    fp=fopen("strings.txt", "r");
    if(fp==NULL){
        printf("ERROR: can't open string.txt!\n");
        return 0;
    }
    else
    {
        s1=(char *)malloc(sizeof(char)*MAX);
        if(s1==NULL){
            printf("ERROR: Out of memory!\n");
            return -1;
        }
        s2=(char *)malloc(sizeof(char)*MAX);
        if(s2==NULL){
            printf("ERROR: Out of memory\n");
            return -1;
        }
        /*read s1 s2 from the file*/
        s1=fgets(s1, MAX, fp);
        s2=fgets(s2, MAX, fp);
        n1=strlen(s1);  /*length of s1*/
        n2=strlen(s2)-1; /*length of s2*/

        //error happens here and the while is never run
        c = fgetc(fp);
        while (c == EOF)
        {
            printf("c != EOF\n");
            if (c == '\n' || c == ' ')
            {
                words++;
                printf("word in loop count = %d\n", words);
            }

            c = fgetc(fp);
        }
...
}

int main(int argc, char *argv[])
{
    int count;

    count = readf(fp);
...
}

strings.txt

This is an apple. That is a pear. That is an orange. That is a kiwi fruit. This is an avocado. There is a peach on the tree. This is a banana. That is a berry. That is cherry. That is a haw. This is a lemon. There is a hickory on the tree. 
is
Jinzu
  • 1,325
  • 2
  • 10
  • 22
  • 3
    `fgetc()` returns an `int`, not `char` – Jeff Mercado Oct 18 '19 at 18:05
  • I looked here: http://ecomputernotes.com/c-program/write-a-program-to-count-the-numbers-of-words-in-a-file and the author has `char c; c = fgetc([file])` – Jinzu Oct 18 '19 at 18:11
  • 3
    It really should be `int`, the author is using the wrong type here. The idea is that `fgetc()` may return `EOF` which is well outside the range of `char`. Use a more canonical reference to verify the usage such as http://www.cplusplus.com/reference/cstdio/fgetc/ – Jeff Mercado Oct 18 '19 at 18:14
  • @Jinzu That author is wrong, dangerously wrong. It's a frequent error, but the correct answer is abundantly clear: *always* use a variable or object of type `int` to receive `getchar`'s return value. Using a value of type `char` will cause problems. – Steve Summit Oct 18 '19 at 18:21
  • I changed it to int but am still getting EOF when using fgetc. – Jinzu Oct 18 '19 at 18:22
  • 2
    It looks like your program calls `fgets` twice, to read two lines, then calls `fgetc` to read any remaining characters from the file. But since your text file contains just two lines, there's nothing else to read. So an EOF return from `fgetc` seems correct, unless I'm missing something. – Steve Summit Oct 18 '19 at 18:24
  • @SteveSummit: yes this did it – Jinzu Oct 18 '19 at 18:34
  • 1
    @Jinzu `s2=(char *)malloc(sizeof(char)*MAX);` --> `s2=malloc(MAX);` as sizeof (char) == 1 [always](https://en.cppreference.com/w/c/language/sizeof) and never [cast malloc in C](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – EsmaeelE Oct 18 '19 at 20:37
  • OT: regarding; `printf("ERROR: can't open string.txt!\n");` Error messages should be output to `stderr`, not `stdout`. Strongly suggest: `perror("ERROR: can't open string.txt!");` – user3629249 Oct 19 '19 at 18:45
  • in function: `int readf(FILE *fp)` returning any value when the function I/O has failed is an error. Much better to call `exit( EXIT_FAILURE );` as the code cannot continue when that function has failed – user3629249 Oct 19 '19 at 18:48
  • regarding: `while (c == EOF)` That loop will either never be entered or never exit. Suggest: `while (c != EOF)` – user3629249 Oct 19 '19 at 18:50
  • When calling the C library functions, like: `fgets()`, always check the returned value to assure no error occurred. – user3629249 Oct 19 '19 at 18:51
  • OT: regarding: `#include ` It is a very poor programming practice to include header files those contents are not used. Suggest removing that statement. – user3629249 Oct 19 '19 at 18:59

1 Answers1

1

You can call ferror() to determine if an error occurred.

You should be able to call perror() with the value you got from ferror() to get a human-readable error message.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501