-1

I am a learning file handling in C. I tried implementing a program but no matter what I do the file pointer is still null.

I checked the spelling, the directory, even tried adding and removing .txt extension but I still don't get what is wrong with this program.

#include <stdio.h>

int main()
{
    FILE *fptr1;
    char filename[100], c;

    printf("Enter the filename to open for reading: ");
    scanf("%s", filename);

    fptr1 = fopen(filename, "r");
    if (fptr1 == NULL)
    {
        printf("Cannot open file %s \n", filename);
    }
    do {
        c = fgetc(fptr1);
        printf("%c", c);
    } while (c != EOF);
    fclose(fptr1);
    return 0;
    }
Rupa TS
  • 19
  • 2
  • 2
    Welcome to StackOverflow. Please share what you've tried so far. – M. Yousfi Jun 19 '23 at 14:47
  • I checked if I misspelled the file name, checked if the it is in the same directory. I don't know what else to do. – Rupa TS Jun 19 '23 at 14:49
  • did you check global variable errno is set to indicate the error? – OldProgrammer Jun 19 '23 at 15:06
  • It is a mistake in pasting the code. It compiled and ran with no problem. Only that it is a null pointer each time. – Rupa TS Jun 19 '23 at 15:06
  • I am just learning C. So, I have no idea about errno – Rupa TS Jun 19 '23 at 15:08
  • 3
    Change the line `printf("Cannot open file %s \n", filename);` to `perror(filename);` to get a hint of _why_ it can't be opened. – Ted Lyngmo Jun 19 '23 at 15:08
  • OK I will try and say – Rupa TS Jun 19 '23 at 15:09
  • 2
    Btw, `scanf("%s", filename);` looks like the wrong tool since it will only read a _word_. If your filename contains whitespaces, it will be cut short. Use `fgets(filename, sizeof filename, stdin)` instead - and **always** check the return values from functions that can fail, like `scanf` and `fgets` can. – Ted Lyngmo Jun 19 '23 at 15:09
  • Note that `scanf("%s", filename);` will only read a single word. Therefore, if your file name contains spaces, only the characters before the first space will be stored in `filename`. If you want to read an entire line of input, I recommend that you use the function [`fgets`](https://en.cppreference.com/w/c/io/fgets) instead and then [remove the newline character from the input](https://stackoverflow.com/q/2693776/12149471), like this: `fgets( filename, sizeof filename, stdin ); filename[strcspn(filename,"\n")] = '\0';` Note that the function `strcspn` requires you to `#include `. – Andreas Wenzel Jun 19 '23 at 15:14
  • @TedLyngmo: If OP uses `fgets` without removing the newline character, then `fopen` will likely fail due to not finding the file name. – Andreas Wenzel Jun 19 '23 at 15:21
  • Okay... Thanks to perror(filename); I discovered that you have to add .txt extension and the problem with my code is not that the pointer is null but rather the first character is EOF so the file can't be read. As for why it is EOF I have no idea. – Rupa TS Jun 19 '23 at 15:22
  • @AndreasWenzel Yes, true. – Ted Lyngmo Jun 19 '23 at 15:23
  • 1
    @RupaTS We can't say anything about that because you haven't shown how you read from the file. – Ted Lyngmo Jun 19 '23 at 15:23
  • 1
    I guess that you are using Microsoft Windows which hides the extensions of file names by default. If that is the case, then I suggest that you change this setting in Windows, so that it shows the extensions. – Andreas Wenzel Jun 19 '23 at 15:28
  • To those who have pointed out the problem with scanf, I don't have any space in my filename. In fact as this is for learning purpose I just named it ftest1.txt. But considering the fact that people use space when naming files, I must really keep this point in mind. – Rupa TS Jun 19 '23 at 15:29
  • Note that generally, you should not change the question in such a way that it invalidates existing answers. Your new problem with `fgetc` is a different problem. However, because you question does not have any existing answers, in my opinion, it is acceptable for you to change the question. Otherwise, it would be appropriate to post a second question instead. – Andreas Wenzel Jun 19 '23 at 15:36
  • _... the pointer is null but rather the first character is EOF so the file can't be read._ I'm quite dubious of this claim. Can you add your text file to the question? Are you sure it's just a simple text file,, no weird encoding? – yano Jun 19 '23 at 15:37
  • Should I close this question and create a new one? – Rupa TS Jun 19 '23 at 15:38
  • @RupaTS: In this case, I believe it is ok for you to reuse the existing question, because it has no answers, only comments. – Andreas Wenzel Jun 19 '23 at 15:39
  • Yeah. The text file just contains a sentence, "File Handling in C test trial." – Rupa TS Jun 19 '23 at 15:39
  • Note: `c` should be an `int`, not a `char`. Your loop is also wrong in that it will try to print the character even when EOF is returned – Ted Lyngmo Jun 19 '23 at 15:39
  • Yeah I tried changing char to int. It still stays the same. – Rupa TS Jun 19 '23 at 15:41
  • Wait a min. I am typing in my phone. I will compare and see if I made any mistakes – Rupa TS Jun 19 '23 at 15:43
  • 2
    you'll also need to add the code that reads and closes the file in an `else` block. If `fptr1 == NULL` you print out an error, but then go on and try to read the file anyway. What if you hardcode the file name rather than getting it from user input, same problem? – yano Jun 19 '23 at 15:45
  • Yeah I changed the ch to c ‍♀️ – Rupa TS Jun 19 '23 at 15:47
  • And no change if I directly give the filename instead of user input – Rupa TS Jun 19 '23 at 15:47
  • Depending on which platform you are using, a `char` is not guaranteed to be able to store the value `EOF`. For this reason, and also at least one other reason, you should make `c` an `int`, which is guaranteed to be able to store the value `EOF`. Note that the function `fgetc` returns a value of type `int`, not `char`. Once you have determined that `c` does not hold the value `EOF`, you can treat it as a normal `char` value. – Andreas Wenzel Jun 19 '23 at 15:48
  • Yeah I tried changing that, it went from EOF to -1, which I discovered still means EOF. So I changed it back to char. – Rupa TS Jun 19 '23 at 15:53
  • 1
    @RupaTS: Even if the value `EOF` is representable on your platform as a `char`, I still recommend that you make `c` an `int`, because otherwise, you will not be able to distinguish the special value `EOF` from an actual value of a character code. Therefore, that value will be ambiguous in certain situations. – Andreas Wenzel Jun 19 '23 at 15:55
  • Ok I am giving up on this for today. I will look at it tomorrow. Maybe after waking up I will grow a brain and be able to solve whatever this thing's problem is. Thank you guys for your help. Thanks to you I learnt quite a bit. – Rupa TS Jun 19 '23 at 15:56
  • 1
    @yano: Instead of enclosing the remainder of the function `main` in an `else` block, I think it would be easier to simply add the line `exit( EXIT_FAILURE );` after `printf("Cannot open file %s \n", filename);`. This will terminate the program immediately. Note that the function `exit` and the macro constant `EXIT_FAILURE` both require `#include `. – Andreas Wenzel Jun 19 '23 at 16:00
  • @AndreasWenzel sure, that works too – yano Jun 19 '23 at 16:01
  • @RupaTS Some of the things mentioned here could make it into [this](https://godbolt.org/z/qe3bYYWr9) for reading text files. – Ted Lyngmo Jun 19 '23 at 16:51
  • If `c` gets the value `EOF`, then you will attempt to print that value with `printf("%c", c);`. This may print a garbage character, because the special value `EOF` is not an actual character code. For this reason, I suggest that you change your `do`...`while` loop to a `while` loop, like this: `while ( (c=fgetc(fptr1)) != EOF ) { printf( "%c", c ); }` – Andreas Wenzel Jun 20 '23 at 01:13

1 Answers1

0

I tried your code it works fine , you just have to add (filename.txt) as your input like (myfile.txt)

well i changed some in your code to make it more simpler ,so here is the changed sections

First from this

 if (fptr1 == NULL)
    {
        printf("Cannot open file %s \n", filename);
    }

to this

 if (fptr1 == NULL)
        printf("Cannot open file %s \n", filename);

Because when you have only one line that execute after the condition is true , you can get ride of the { }

also i changed the ( do while ) to ( while ) Second from this

 do {
        c = fgetc(fptr1);
        printf("%c", c);
    } while (c != EOF);

to this

    while(!feof(fptr1)){
        c = fgetc(fptr1);
        printf("%c",c);
    }

Here the line feof is a function that means the end of file

We are checking if its NOT the end of file ( !feof ) , if thats true then we can read from the file and print the result . the loop ends when c = EOF .

and thats it.

NOTE : your file name should be without spaces ( myfile.txt ) and not (my file.txt) because we are using scanf() function , it stoppes when countering a space ( blank space ) , so keep that in mind.

  • The function `feof` specifies whether a function call to `fgetc` **has already failed** due to end-of-file. It does not necessarily specify whether the next call to `fgetc` **will fail**. Therefore, your use of `feof` is wrong, because you will attempt to print one `EOF` character returned by `fgetc`. I suggest that you read this for further information: [Why is “while( !feof(file) )” always wrong?](https://stackoverflow.com/q/5431941/12149471) – Andreas Wenzel Jun 20 '23 at 01:56
  • For the reason stated in my previous comment, I think the best solution would be `while ( (c=fgetc(fptr1)) != EOF ) { printf( "%c", c ); }`. – Andreas Wenzel Jun 20 '23 at 01:57