I'm having a little trouble with the code below and I can not for the life of me figure out what went wrong and why it is displaying what it does, any help or assistance would be most appreciated. It is supposed to allow 5 lines of text to be entered and display those 5 lines onscreen, however it only allows 4 lines to be entered, and 4 are displayed. Please help!
#include <stdio.h>
int main()
{
char string[100];
char filename[20];
int n=0;
FILE *fp;
printf(" Enter the name of file to open ");
scanf("%s",filename);
fp =fopen(filename,"wr");
if(fp==NULL)
{
printf("unable to open File");
}
for(n=1;n<6;n++)
{
printf("\nEnter line %d:",n+1);
gets(string);
fputs(string,fp);
fputs("\n",fp);
}
fclose(fp); /*close the file*/
fp =fopen(filename,"r");
if(fp==NULL)
{
printf("unable to open File");
}
for(n=1;n<6;n++)
{
fgets(string,100,fp);
printf("%s",string);
}
fclose(fp); // close after reading.
return 0;
}
The problem is that scanf("%s", filename); doesn't consume the newline after the filename. So your first call to gets() reads this newline as an empty line.
Add:
gets(string);
after that line to use up the rest of the line before you start reading input lines.
Here is the modified code. Added gets instead of scanf and added return 0; if file is not opened.
#include <stdio.h>
int main()
{
char string[100];
char filename[20];
int n=0;
FILE *fp;
printf(" Enter the name of file to open ");
gets(filename);
fp =fopen(filename,"wr");
if(fp==NULL)
{
printf("unable to open File");
return 0; // do not proceed
}
for(n=1;n<6;n++)
{
printf("\nEnter line %d:",n);
gets(string);
fputs(string,fp);
fputs("\n",fp);
}
fclose(fp); /*close the file*/
fp =fopen(filename,"r");
if(fp==NULL)
{
printf("unable to open File");
return 0; // do not proceed
}
for(n=1;n<6;n++)
{
fgets(string,100,fp);
printf("%s",string);
}
fclose(fp); // close after reading.
return 0;
}
replace scanf("%s",filename) with gets(filename)
To get rid of the newline in the buffer right after your call to scanf, you can simply add getchar();:
scanf("%s", filename);
getchar();
But do adjust your for loops to start at 0, since you add 1 to n i.e:
for(n=0;n<6;n++)
^
After making those changes I was able to input 6 lines and then print all of them out.
As you've noticed, buffered input can be pesky if you don't deal with it properly as it can be inserted in your subsequent input calls. Don't be tempted to flush the stdin.
Here are some recommended alternatives on how to deal with this.
Related
I a trying to take file name as argument and write strings using loop until user enter "-1".
problem 1: writing is not happening in text file and always shows empty
problem 2: cannot compare input -1 and "-1" . Always runs the else statements.
Note: I also tried fputs but it did not work that time either.
FILE *fp = fopen(argv[1], "a");
//fseek(fp, 0, SEEK_END);
char str[100];
printf("enter string\n");
bool flag = true;
while (flag == true) {
//printf("\nEnter data to append: ");
fflush(stdin);
fgets(str, 100, stdin);
if (strcmp(str, "-1") == 0) {
break;
} else {
fprintf(fp, "%s", str);
printf("Text written in file: %s\n", str);
}
}
fclose(fp);
Writing don't happen because of strcmp, I'm showing you my version of this with atoi.
#include <stdio.h>
#include <stdlib.h>
#define buffer 128
int main(int argc, char *argv[])
{
char str[buffer];
int flag = 1;
FILE *fp = fopen(argv[1], "w+"); //I prefer using write mode and not append
if(fp==NULL)
{
printf("Error opening file.\n"); //here you control if the file is opening correctly
exit(EXIT_FAILURE);
}
while(flag) //you don't need to write while(flag==true) (that's not wrong)
{
printf("Insert string: ");
scanf("%s", str);
if(atoi(str)==1) //the function strcmp as you wrote it will break after the
break; //first cicle, use atoi, it returns 1 if the string is a number
fprintf(fp, "%s\n", str); //the \n is to get the next string on the next row
}
fclose(fp);
return 0;
}
If you want to make it work with strcmp your if statement should be if(strcmp(str, "-1\n")) because fgets reads also the \n character.
Because fget() reads new line character.
So once you do comparation, It looks like:
strcmp("-1\n", "-1");
or
strcmp("-1\n\r", "-1");
You will never break the loop.
To remove newline character, let try:
strtok(str, "\n");
or
strtok(str, "\r\n");
When I execute my code below. It waits for my input for entering a file name. But it doesn't wait for me to enter a filename, but rather just skips it to the _getch() part of it. I'm unable to add a sentence.
Code not working:
#include <stdio.h>
main() {
FILE *fp;
char fnamer[100] = ""; //Storing File Path/Name of Image to Display
printf("\n\nPlease Enter the Full Path of the Image file you want to view: \n");
scanf("%s", &fnamer);
fp = fopen(fnamer, "w");
if (fp == NULL)
{
printf("\n%s\" File NOT FOUND!", fnamer);
}
char c[1000];
printf("Enter a sentence:\n");
gets(c);
fprintf(fp, "%s", c);
fclose(fp);
_getch();
}
Code that works and waits for entering a sentence:
#include <stdio.h>
#include <stdlib.h> /* For exit() function */
int main()
{
char c[1000];
FILE *fptr;
fptr = fopen("program.txt", "w");
if (fptr == NULL){
printf("Error!");
exit(1);
}
printf("Enter a sentence:\n");
gets(c);
fprintf(fptr, "%s", c);
fclose(fptr);
return 0;
}
Both are so similar right there in the end for the prompt asking for a sentence. It doesn't make sense.
you have to flush your input after using scanf.
put a getchar() after every scanf
You are encountering a very common problem when using stdin to receive input, which is after your first scanf call there is a dangling \n character which gets stuck in the buffer from the enter key. To clear this buffer in a portable easy way, add something like
char c;
while ( (c = getchar()) != '\n' && c != EOF ) { }
This simply initializes a character, and then calls get char as many times as needed until it reaches '\n' or 'EOF', which is immediately in your case.
tl;dr :
Your buffer looks like this
hello.txt\n <-- "comes from the enter key"
and when you try to use get(c) it takes the \n as the next enter key.
The rule is never mix scanf and [f]gets. scanf stops before the next unused character, generaly a blank, and the end of line is composed of blank characters.
You could try to put a dummy fgets between the last scanf and the first real fgets. That will ensure that you are now positionned on a beginning of line before reading. Alternatively, you could read everything in lines with fgets, and parse the lines with sscanf. That is what I prefere as soon as I want my input to be line oriented. And always control return values of input functions, it will avoid a progam suddenly going mad without any indication simply because one input gave an ignored error.
And last and not least: never use gets but only fgets, the former is for decades in the hall of shame as the cause of uncountable buffer overflows
Code could become:
#include <stdio.h>
#include <string.h>
main() {
FILE *fp;
char fnamer[100] = ""; //Storing File Path/Name of Image to Display
char c[1000], *ix;
int cr;
printf("\n\nPlease Enter the Full Path of the Image file you want to view: \n");
cr = scanf("%s", &fnamer);
if (cr != 1) {
// process error or abort with message
}
fp = fopen(fnamer, "w");
if (fp == NULL)
{
printf("\n%s\" File NOT FOUND!", fnamer);
return 1; // do not proceed after a fatal error!
}
for(;;) { // read until a newline in input
ix = fgets(c, sizeof(c), stdin);
if (ix == NULL) {
// end of input: abort
}
if (strcspn(c, "\n") < strlen(c)) break;
}
printf("Enter a sentence:\n");
ix = fgets(c, sizeof(c), stdin);
c[strcspn(c, "\n")] = '\0'; // remove end of line to get same data as gets
fprintf(fp, "%s", c);
fclose(fp);
_getch();
}
main() {
FILE *fp;
char fnamer[100]=""; //Storing File Path/Name of Image to Display
printf("\n\nPlease Enter the Full Path of the Image file you want to view: \n");
fgets ( fnamer,100,stdin); //fgets(name, sizeof(name), stdin);
fp=fopen(fnamer,"w");
if(fp==NULL)
{
printf("\n%s\" File NOT FOUND!",fnamer);
getch();
exit(1);
}
}
I Think best way to do,use fgets insted of scanf,Because
fgets() can read any open file, but scanf() only reads standard input(user given).
fgets() reads a line of text from a file; scanf() can be used for that but also handles conversions
from string to built in numeric types
I have some demo code that wants the user to input a filename and the mode. The book is suggesting the dreaded gets(); function for input, which I refuse to use, so I tried to grab my input with fgets(). When I used fgets() I specified my input stream as 'stdin', however the code will not work. The code WILL work with gets(), however. I assume that the problem with my implementation of fgets() is the 'stdin' stream type. Is that why my fgets() will not work with this program? If so, what input stream type should I use? Here is the program:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *fp;
char ch, filename[40], mode[4];
while(1)
{
printf("\nEnter a filename: "); //This is where fgets/gets conflict is
//fgets(filename, 30, stdin); //I commented out the fgets()
gets(filename);
printf("\nEnter a mode (max 3 characters):");
//fgets(mode, 4, stdin); //fgets again
gets(mode);
//Try to open the file
if((fp = fopen(filename, mode)) != NULL)
{
printf("\nSuccessful opening %s in mode %s.\n",
filename, mode);
fclose(fp);
puts("Enter x to exit, any other to continue.");
if((ch = getc(stdin)) == 'x')
{
break;
}else{
continue;
}
}else
{
fprintf(stderr, "\nError opening file %s in mode %s.\n",
filename, mode);
puts("Enter x to exit, any other to try again.");
if((ch = getc(stdin)) == 'x')
{
break;
}else{
continue;
}
}
}
return 0;
}
Thanks in advance all. This program was from "Teach Yourself C in 21 Days" by B. Jones.
Well done on not wanting to use gets(); that is absolutely the correct way to go.
The error opening the file arises from the fact that fgets() keeps the newline and gets() does not. When you try to open the file name with the newline, the file is not found.
I am working on a program to write user input to a file and then search for a specific record in the file and output it to the screen.
I tried using fgets and also fputs but havent been successful
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
main ()
{
FILE *fileptr;
char id [30];
char name [47];
char amt[50];
int i;
fileptr=fopen("C:\\Users\\Andrea\\Documents\\Tester.txt","w");
if (fileptr == NULL) {
printf("File couldn't be opened\n\a\a");
fclose(fileptr);
exit(0);
}
printf("Enter name: \n");
fscanf(fileptr,"%c",name);
fputs(name,fileptr);
fclose(fileptr);
printf("File write was successful\n");
return 0;
}
There are several problems.
You are trying to read from fileptr.
You are reading only one character, but treat the name array as if it was read in correctly.
A start would be:
[...]
printf("Enter name: \n");
if (fgets(name, sizeof name, stdin)) {
fputs(name,fileptr);
fclose(fileptr);
printf("File write was successful\n");
} else {
printf("Read error.\n");
}
But that's not all: you have forgotten to put error checking. E.g., how do you know that your "File write was successful\n" if you don't check at least the return value of fputs()?
I'm creating a program that asks the user to input a word. The word is then compared with a word in a text file. If correct, I want the user to input another word which should correspond with the next word in the text file and this should loop until the end of the file. I'm having trouble with the loop to the end of the file. Could someone please review my code and give me a few pointers? thanks so much
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
//Step 1: open file and declare variables//
FILE *fp;
fp = fopen("secretwords.txt","r");
char guess[20];
char secret[20];
int i, count;
//Step 2: Check that file opened correctly, terminate if not//
if (fp == NULL)
{
printf("Error reading file\n");
exit (0);
fclose(fp);
}
//Step 3: Create loop to run for each word to run to end of file//
fscanf(fp,"%s", secret);
//Need to create a loop here that will read the text file 20 times,
// each time reading the next word//
for (i=0; i < 3; i++)
{
printf("Please guess the word: \n");
scanf("%s", guess);
if (strcmp(secret,guess)==0)
{
printf("Your guess was correct\n");
return 0; //This return will terminate the program.
// I need to restart loop from here
}
else
{
printf("Your guess was incorrect. Please try again\n");
}
}
return 0;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
FILE *fp = fopen("secretwords.txt", "r");
if (fp == NULL)
{
printf("Error reading file\n");
return 1;
}
char guess[20] = {0};
char secret[20] = {0};
while(fscanf(fp, "%s", secret) != EOF) // i would suggest you use 'fscanf_s("%s", guess);' instead if available
{
printf("Please guess the word: \n");
scanf("%s", guess); // i would suggest you use 'scanf_s("%s", guess);' instead if available
if (!strncmp(secret, guess, sizeof(guess)))
{
printf("Your guess was correct. Continue ...\n");
}
else
{
printf("Your guess was incorrect. Good bye.\n");
break;
}
}
fclose(fp);
return 0;
}
i made some suggestions about scanf_s and fscanf_s, if they are available, use them. But still, i am wondering why they are still teaching bad code in schools? I would not suggest to use *scanf* functions at all. Further reading: uncontrolled format string
Move the fscanf call that reads from the file to a function that returns the next word
loop for user input, only calling the function outlined above when you need to advance to the next word in the file (when the user inputs the correct thing)