Reputation:
I am trying to read in user input and open the file that the user inputs. My program seems to be exiting right after the print statement. Any help would be appreciated!
printf("What is the name of the file? \n");
scanf("%s", "fileName");
FILE* inFile = NULL;
inFile = fopen("fileName", "r");
if(inFile == NULL) {
printf("Could not open this file");
}
Upvotes: 0
Views: 927
Reputation: 84521
Continuing from my comment, until you thoroughly understand the pitfalls of scanf()
, it is recommended you use fgets()
for all user and file input so that you consume a complete line of input with each read. That way what remains in the input stream does not depend on the conversion specifier used and whether a matching-failure occurs. If you then need to extract information from the line read by fgets()
you can use sscanf()
and regardless of whether sscanf()
succeeds or fails, it does not impact what is left in your input stream unread.
All line-oriented input functions, fgets()
and POSIX getline()
read and include the '\n'
as part of the buffer they fill. You simply trim the '\n'
from the end of the stored line after your call to fgets()
using strcspn()
to determine the number of characters before the '\n'
and then overwrite the '\n'
with the nul-terminating character '\0'
(which is simply ASCII 0
).
You handle user-input or lines read from a file the exact same way. For example, you can prompt the user for a filename, read the input, open the file, and then read all lines in the file as follows:
#include <stdio.h>
#include <string.h>
#define MAXC 1024 /* if you need a constant, #define on (or more) */
int main (void) {
char fname[MAXC], line[MAXC]; /* storage for filename & line */
FILE *fp = NULL; /* FILE pointer */
fputs ("enter filename: ", stdout); /* prompt */
if (!fgets (fname, MAXC, stdin) || *fname == '\n') { /* check EOF or empty line */
puts ("(user canceled input)");
return 1;
}
fname[strcspn (fname, "\n")] = 0; /* trim \n from end */
if (!(fp = fopen (fname, "r"))) { /* validate file open succeeds */
perror ("fopen-fname"); /* fopen sets errno on failure */
return 1;
}
putchar ('\n'); /* provide space before output */
while (fgets (line, MAXC, fp)) { /* read each line from file */
line[strcspn (line, "\n")] = 0; /* trim \n from end */
puts (line); /* output line */
}
fclose (fp); /* close file when done */
}
Note, when taking any type of input, every single step must be validated. Otherwise, if you fail to validate, and an input fails, you will invoke undefined behavior if you blindly use the variable containing an indeterminate value.
Example Use/Output
$ ./bin/readfile
enter filename: dat/fleas.txt
My dog has fleas
My cat has none
Lucky cat
fgets()
provides one of the most robust ways to handle input. You can use scanf()
as well -- so long as you understand each pitfall associated with its use and you protect against it. Let me know if you have further questions.
Upvotes: 1
Reputation: 212168
The root of you problem (is using scanf
, but that's a different issue completely) is:
scanf("%s", "fileName");
That should be:
char fileName[128];
if( 1 == scanf("%127s", fileName)) ...
You cannot write to a string literal, so passing the address of a string literal to scanf is a disaster waiting to happen. You really should use PATH_MAX instead of the hard coded 128, but then you need to use sprintf to construct the format string, and that seems to detract from this example. For completeness:
#include <limits.h>
...
char fileName[PATH_MAX];
char fmt[64];
snprintf(fmt, sizeof fmt, "%%%ds", PATH_MAX - 1);
if( 1 == scanf(fmt, fileName) ){
FILE* inFile = fopen(fileName, "r");
if( inFile == NULL ){
perror(fileName);
exit(EXIT_FAILURE);
}
...
}
But note that you almost certainly do not want to read the input file from the input stream using scanf
. It would be better to take it as a command line argument and have it available in argv
.
Upvotes: 2