Reputation: 602
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char file_name[100];
char insert[100];
printf("Enter the file name:");
scanf("%s", file_name);
FILE *f = fopen((strcat(file_name, ".txt")), "a");
printf("Insert:");
scanf ("%[^\n]%*s", insert);
fprintf(f, "%s", insert);
}
The above stated code is supposed to write/insert data to the file, however, the program is terminating right after printing 'Insert:'. I cant seem to find the problem here.
Upvotes: 0
Views: 84
Reputation: 20244
The scanf
:
scanf("%s", file_name);
will not consume the newline which you press after entering the file name. It stays in the standard input stream(stdin
). The scanf
:
scanf ("%[^\n]%*s", insert);
scans everything until a newline character, and then scans and discards a string. %[^\n]
will fail if the next character is \n
. So, scanf
, in your case fails and returns as the next character is \n
. insert
remains uninitialized and contains garbage.
fprintf(f, "%s", insert);
writes the garbage into f
.
getchar();
just after the first scanf
to get rid of the newline character left over by the first scanf
.Use
scanf (" %[^\n]%*s", insert);
instead of
scanf ("%[^\n]%*s", insert);
The space before %[^\n]
scans and discards all whitespace characters(like \n
, space etc),if any, until the first non-whitespace character as seen in the quote of the C11 standard below:
7.21.6.2 The fscanf function
[...]
- A directive composed of white-space character(s) is executed by reading input up to the first non-white-space character (which remains unread), or until no more characters can be read. The directive never fails
I prefer the second solution as it takes care of any number of whitespace characters.
scanf
! Fixing this is easy. Just remove the %*s
from the second scanf
.
Wondering why? Quoting the C11 standard,
7.21.6.2 The fscanf function
[...]
- The conversion specifiers and their meanings are:
[...]
s Matches a sequence of non-white-space characters. 286
[...]
So, %s
will skip leading whitespace characters and will stop scanning when it encounters a whitespace character or, if the length field is present, until the specified length or until a whitespace character, whichever occurs first. The bolded part explains it.
scanf
reads for insert
and file_name
so that you can avoid buffer overflows. Also, check the return values of both the scanf
s and fopen
to see if they were successful. Both the scanf
s, in your case, returns 1 if successful. If not 1, an error occured. fopen
, returns NULL
on failure. If not NULL
, fopen
is successful.
Final program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char file_name[100];
char insert[100];
printf("Enter the file name:");
if(scanf("%94s", file_name) != 1) //Scans a maximum of 94 chars,+1 for \0 at the end,+4 for ".txt"
{
printf("scanf failed\n");
exit(-1); //Exit the program with a negative return value
}
strcat(file_name, ".txt"); //Improves readability,do one thing in one line
FILE *f = fopen(filename, "a");
if(f == NULL) //if fopen failed to open the filename,
{
printf("fopen failed\n");
exit(-1);
}
printf("Insert:");
if(scanf (" %99[^\n]", insert) != 1) // Note the space before %[^\n],99 scans a maximum of 99 chars,+1 for the \0 at the end
{
printf("scanf failed\n");
fclose(f); //Free resources before exiting
exit(-1);
}
fprintf(f, "%s", insert);
fclose(f); //Close the file after use
}
scanf
, use
scanf (" %99[^\n]%*c", insert)
instead of
scanf (" %99[^\n]", insert)
It doesn't make a difference in this program, though.
fscanf
is exactly the same as scanf
when the first argument of it is stdin
. Quoting once again from the C11 standard,
7.21.6.4 The scanf function
[...]
- The
scanf
function is equivalent tofscanf
with the argumentstdin
interposed before the arguments toscanf
.
Upvotes: 3
Reputation: 16379
The trouble is in your first scanf
. The carriage return is not being dealt with, which means that the next scanf
deals with it immediately upon being called since it's still in the buffer.
Perhaps try, scanf("%s\n", filename);
Upvotes: 0