0

I am trying to code a simple program that does the following:

  • Selects a file
  • Selects what to do with the file (fopen modes: r, w, a, r+...)
  • Writes to the file

this is my code so far:

//Gets future file content
printf("Write content:\n");
char content[100];
fgets(content, 100, stdin);

//Selects file
printf("Select output file: ");
char file[30];
fgets(file, 30, stdin);

//Selects mode
printf("Select mode: ");
char mode[3];
fgets(mode, 3, stdin);

    FILE *fp;
    fp = fopen(file, mode);

    if (fp == 0) {
       printf("File NOT opened\n");
    }

I want the variable "file" to be used as the string/path to the file, and same goes for the "mode" variable. When I run the program I get that the file is not opened, meaning that fp is a null pointer.

PS: It is not the whole code, but that's what's breaking it

Thanks in advance

Daniel Hernandez
  • 635
  • 1
  • 11
  • 22
  • If the file does not exist or you do not have permission then you would likely receive some type of notification via an other than NULL result I would think. Try checking if file is NULL? – Jay May 21 '14 at 16:50
  • Using the mode w or w+ would create a file. I checked and it still returns the same error. But thanks anyway – Daniel Hernandez May 21 '14 at 16:52
  • 2
    `fgets()` most propably reads in a trailing new-line to `file`. – alk May 21 '14 at 16:53
  • Do you think that, as I initialize file to be char file[30]. The unused elements would hold garbage values? (Because I may not use 29 digits) – Daniel Hernandez May 21 '14 at 16:59
  • No, unused elements after short strings are not the problem. `fgets` writes the necessary terminating NUL - anything after that will not be seen by `fopen`. The issue is the newline in the input. – nobody May 21 '14 at 17:26

2 Answers2

2

Add this line

fprintf(stderr, "file='%s'\n", file);

after you read file and learn that a newline is read if the input was terminated by hitting Enter.

From man fgets() (italics by me):

fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A terminating null byte ('\0') is stored after the last character in the buffer.


As per Chris Dodd's comment below: The same applies to the string read into mode.

alk
  • 69,737
  • 10
  • 105
  • 255
  • Actually, the problem is the `mode` argument -- including a newline will cause `fopen` to fail. But the newline in the name is probably not wanted either. – Chris Dodd May 21 '14 at 17:08
  • @ChrisDodd: A newline as a suffix to a file name would make `fopen` choke also, wouldn't it? – alk May 21 '14 at 17:09
  • Depends on the system -- on unix-like systems, any character other than `/` is fine in the file name. – Chris Dodd May 21 '14 at 17:13
  • Wow, that's useful. How could I get rid of the '\n'? I could traverse the string looking for it and turning it into a '\0', using a simple loop and a comparison, but it looks like there could be a simpler solution – Daniel Hernandez May 21 '14 at 17:15
  • @ChrisDodd: Fair enough. However, I'm 100% sure the user doesn't use file names ending with a newline. – alk May 21 '14 at 17:17
  • @user2850788: Have a look at this answer: http://stackoverflow.com/a/16000784/694576 – alk May 21 '14 at 17:19
  • Not conciously. But i am hitting enter in order to finish with fgets, because I don't use all the length of the array, so I am adding a a new line. I am going to see if there is any kind of command to stop the stream of incoming input. – Daniel Hernandez May 21 '14 at 17:21
  • @user2850788: Try `Ctrl-Z` on Windows or `Ctrl-D` (twice) on Linux. – alk May 21 '14 at 17:23
1

You need to check what the problem is with the filename and mode. First of all, fgets() will store the newline into the buffer, which can prevent fopen() from doing what you expect. Print out what you're trying to open:

printf("opening: '%s' with mode '%s'\n", file, mode);

Secondly, you should check the error code that fopen sets:

perror("File NOT Opened");

That way you will at least see what the error was opening the file.