mrQWERTY
mrQWERTY

Reputation: 4149

fgetc returns a strange character

I am reading input until EOF with fgetc(). I am running into a strange problem. Right before EOF, I am getting a char \337. I am not sure what that is.

Here is my code implementation:

char *get_file_paths() 
{
        char *return_str = NULL;
        int chars_read = 0;
        size_t buf_sz = 80;

        return_str = (char *) malloc(buf_sz * sizeof(char));

        while((*(return_str + chars_read) = fgetc(stdin)) != EOF) {
                chars_read++;
                if ((chars_read + 1) == buf_sz) {
                        buf_sz *= 2;
                        return_str = realloc(return_str, buf_sz);
                }
        }

        return return_str;

}

For instance, if I had a string :assignment_2/grepout.txt. I am getting the following when viewing return_str in gdb:

assignment_2/grepout.txt\n\337

I am really curious what that means. I looked online, but there is no mention of it. Could it be platform specific?

I am running the following version of gcc:

gcc version 4.8.1 20130909 [gcc-4_8-branch revision 202388] (SUSE Linux)

And I am running openSuse.

Upvotes: 0

Views: 1643

Answers (2)

Patrick Schlüter
Patrick Schlüter

Reputation: 11841

It is important to not type coerce the return of fgetc() to a char. fgetc() (and fgets()) return int and not char exactly for the reason that EOF is a value that is outside the range of characters. Your 0337 (0xFF or 255 decimal) is a valid character in most implementations (It's character ÿ in Codepage 1252, in ISO-8859-15 and in Unicode). With your loop, if you enter that character on the keyboard, you will have the same behaviour as EOF.

You should therefore change your loop to:

char *get_file_paths(void) 
{  
    int chars_read = 0;
    size_t buf_sz = 0;
    int ch;
    char *return_str = NULL;

    while((ch = fgetc(stdin)) != EOF) {
        if(chars_read == buf_sz) {
            buf_sz += 80;
            void *no_leak = realloc(return_str, buf_sz+1);
            if(!no_leak) {
              perror("No memory\n");
              abort();
            }
            return_str = no_leak;
         }
         return_string[chars_read++] = ch;
    }
    if(return_string)
        return_string[chars_read++] = 0;
    return return_str;
}

I changed several other small "issues".

  • realloc() with NULL as first parameter is the same as malloc() so by rearranging the (re-)allocation in the loop you avoid unnecessary code.
  • sizeof (char) is by definition 1 and does not need to be stated.
  • The EOF value (i.e. -1) does not enter in the loop and is not mixed up with character 0xFF.
  • The function returns NULL if EOF is already reached. It's a functional choice that can be helpful (or not). It depends on the context.
  • Use array syntax (a[x] instead of *(a+x)), it's much, much more readable.

EDIT: Added allocation check. Used a harsh method. What could we do else in that case?

Upvotes: 5

Lars Blumberg
Lars Blumberg

Reputation: 21371

You didn't mark the end of the string.

return_str[chars_read] = '\0';
return return_str;

Upvotes: 1

Related Questions