Reputation: 19
So I'm trying to open a file based on a users input but I just keep getting what I typed in back.
This is what I have.
#include <stdio.h>
#include <string.h>
int main(void)
{
FILE* data;
char a[144];
printf("Enter a filename:\n");
fscanf(stdin, "%143[^\t]", a);
data = fopen(a, "r");
printf("%s", a);
fclose(data);
return 0;
}
This is my text file.
larry snedden 123 mocking bird lane
sponge bob 321 bikini bottom beach
mary fleece 978 pasture road
hairy whodunit 456 get out of here now lane
Upvotes: 0
Views: 6554
Reputation: 25
fscanf(stdin, "%143[^\t]", a)
read input end with tab. You can try another method. And you didn't read from the file stream data
.
#include <stdio.h>
#include <string.h>
int main(void)
{
FILE* data;
char a[144];
printf("Enter a filename:\n");
fscanf(stdin, "%s", a); //use %s not 143[^t]
data = fopen(a, "r");
//read from the file
char read_from_file[100];
while (!feof(data)) {
fgets(read_from_file, 1024, data);
printf("%s", read_from_file);
}
print("\n")
printf("%s", a);
fclose(data);
return 0;
}
text file named file.txt:
larry snedden 123 mocking bird lane
sponge bob 321 bikini bottom beach
mary fleece 978 pasture road
hairy whodunit 456 get out of here now lane
input:
file.txt
output:
larry snedden 123 mocking bird lane
sponge bob 321 bikini bottom beach
mary fleece 978 pasture road
hairy whodunit 456 get out of here now lane
file.txt
Upvotes: 1
Reputation: 13134
Use fgets()
to read a whole line of input:
#include <stddef.h> // size_t
#include <stdlib.h> // EXIT_FAILURE
#include <stdio.h> // FILE, fprintf(), fputs(), fgets(), fopen(), fclose()
#include <string.h> // strlen()
enum { MAX_FILENAME_LENGTH = 120 };
int main(void)
{
char filename[MAX_FILENAME_LENGTH + 2]; // + '\n' + '\0'
if (!fgets(filename, sizeof(filename), stdin)) {
fputs("Input error :(\n\n", stderr);
return EXIT_FAILURE;
}
size_t length = strlen(filename); // get rid of the newline at the end:
if (length && filename[length - 1] == '\n')
filename[--length] = '\0';
// When the length of the string is not needed, the above if-statement
// can be replaced as suggested by Jonathan Leffler:
filename[strcspn(filename, "\n")] = '\0'
FILE *input = fopen(filename, "r");
if(!input) {
fprintf(stderr, "Couldn't open \"%s\" for reading :(\n\n", filename);
return EXIT_FAILURE;
}
// do stuff with input
fclose(input);
}
See this answer on how to read a whole file into memory line by line.
Upvotes: 2
Reputation: 84551
You face three primary issues: (1) you take a filename from the user with fscanf(stdin, "%143[^\t]", a);
which will read all characters not a tab
(including the trailing '\n'
generated by pressing Enter), (2) after opening the file input by the user and assigning the return from fopen
to data
, you have no way to know whether the file is actually open (given the trailing '\n'
included in the filename, I suspect it fails); and (3) you never actually read from the file-stream data
(which is probably a good thing given you failed to VALIDATE it was actually open.
The key is to validate every critical step in your program especially every bit of user input. Each function provides a return -- use them to validate whether the function succeeded or failed.
A short example adding validation (and declaring a constant where needed -- don't use magic numbers in your code except where absolutely required -- like with the scanf
field-width modifier), e.g.
#include <stdio.h>
#define MAXC 1024 /* if you need a constant, define one (or more)
( don't SKIMP on buffer size ) */
int main (void)
{
FILE* data = NULL; /* initialize all variables */
size_t nlines = 0;
char a[MAXC] = "";
printf("Enter a filename: ");
/* VALIDATE EVERY SINGLE BIT OF INPUT */
if (fscanf (stdin, " %1023[^\n]", a) != 1) {
fputs ("user canceled input.\n", stderr);
return 1;
}
/* open/VALIDATE file open for reading */
if ((data = fopen (a, "r")) == NULL) {
perror ("fopen-a");
return 1;
}
printf ("file opened: %s\n\n", a);
/* reuse buffer to read each line */
while (fgets (a, MAXC, data) != NULL)
/* fgets include '\n' in buffer if buffer of sufficient size */
printf ("line[%3zu]: %s", nlines++ + 1, a);
fclose(data);
return 0;
}
Example Input File
$ cat dat/file.txt
larry snedden 123 mocking bird lane
sponge bob 321 bikini bottom beach
mary fleece 978 pasture road
hairy whodunit 456 get out of here now lane
Example Use/Output
$ ./bin/fopen_file_from_user
Enter a filename: dat/file.txt
file opened: dat/file.txt
line[ 1]: larry snedden 123 mocking bird lane
line[ 2]: sponge bob 321 bikini bottom beach
line[ 3]: mary fleece 978 pasture road
line[ 4]: hairy whodunit 456 get out of here now lane
Upvotes: 4