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
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");
I am trying to write a few lines to a file. After the line are written, when I try to read those lines from file using fscanf it is going into infinite loop. fprintf is working but fscanf is going to an infinite loop.
#include<stdio.h>
#include<stdlib.h>
void main()
{
FILE *fp;
int roll;
char name[25];
float marks;
char ch;
fp = fopen("file.txt","w");
if(fp == NULL)
{
printf("\nCan't open file or file doesn't exist.");
exit(0);
}
do
{
printf("\nEnter Roll : ");
scanf("%d",&roll);
printf("\nEnter Name : ");
scanf("%s",name);
printf("\nEnter Marks : ");
scanf("%f",&marks);
fprintf(fp,"%d%s%f",roll,name,marks);
printf("\nDo you want to add another data (y/n) : ");
ch = getche();
}while(ch=='y' || ch=='Y');
printf("\nData written successfully...");
printf("\nData in file...\n");
while((fscanf(fp,"%d%s%f",&roll,name,&marks))!=EOF)
printf("\n%d\t%s\t%f",roll,name,marks);
fclose(fp);
}
You have opened the file for writing (mode "w"), so your scanf calls are almost certainly failing. Even if you fix the mode, it is not at all surprising that:
while((fscanf(fp,"%d%s%f",&roll,name,&marks))!=EOF)
goes into an infinite loop. If the next character in the stream is not a valid character in an integer, then scanf will return zero and not consume it. It will repeatedly attempt to read that character as an integer and repeatedly fail. The correct approach here is probably to stop using scanf entirely, but a quick work-around may be something like:
int rv;
while( (rv = fscanf(fp,"%d%s%f",&roll,name,&marks)) != EOF ){
if( rv == 3 ){
printf(...);
} else {
/* probably the right thing to do is break out of
the loop and emit an error message, but maybe
you just want to consume one character to progress
in the stream. */
if( fgetc(fp) == EOF ){
break;
}
}
}
it would be more common to write while( 3 == fscanf(...)) and just emit an error message on bad input, but something like the above kludge might be useful (depending on your use case).
But you need to fix the open mode. Probably you just want to close the file after the write loop (you certainly need to flush it before you can expect to read from the file) and re-open in with mode "r".
I am writing a menu system in C, the code works correctly but for some reason the first first time the while loop is entered for the menu it skips the getchar() command and runs through the while loop again, but the second time round it works?
Any ideas as to why it does this?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "structs.h"
int main(void)
{
FILE *fp = NULL;
char fileName[25], line[200], userInput = ' ';
int len;
while (fp == NULL)
{
printf("Enter The File To Load In: \n");
scanf("%s", fileName); // Ask User For File Name
fp = fopen(fileName, "r"); // Open File To Read
if (fp == NULL)
{
perror("Error While Loading File\n");
}
}
while (userInput != 'g')
{
printf(" |User System|\n");
printf("A) Save Current Data To A File\n");
printf("B) Enter Details\n");
printf("C) View Details\n");
printf("D) Amend Details\n");
printf("E) Search by Award Title\n");
printf("F) Search by Surname\n");
printf("G) Shut Down\n");
userInput = getchar();
if (userInput == 'c')
{
fgets(line, 200, fp);
len = strlen(line);
printf("%s", line);
userInput = getchar();
}
}
}
After 'scanf' use
getchar();
to consume extra newline. As 'scanf' can not discard newline, first iteration of 'getchar();' take the newline.
So you shold place getchar() after scanf as to consume extra newline('\n')
scanf("%s", fileName);
getchar();
It's better to use 'fgets' instead of scanf as file name may have space.
You can use 'fgets()' as
fgets(fileName, sizeof(fileName), stdin);
fileName[strlen(fileName)-1] = 0; //Replace newline with '\0' character
I'm starting to learn file processing in C. The point of this specific program is to make a file called "clients.dat" where I store the account number, name, and balance of clients at a bank, lets say. I've worked and refined the code so that its a perfect replica of what the textbook provides as an example, yet for some reason mine loops endlessly after the first "scanf" and reprints question marks unto oblivion, without ever making it to the scanf statement inside the while loop. Would anyone have any suggestions as to why this is happening? My compiler is Netbeans and I'm running it on Linux-Ubuntu.
#include <stdio.h>
#include <stdlib.h>
/*
*
*/
int main() {
unsigned int actNumber;
char actName[30];
long double actBalance;
FILE *fPtr;
if((fPtr = fopen("clients.dat", "w")) == NULL) {
printf("File could not be found.\n");
}
else {
printf("Enter the Account Number, Name, and Balance.\n Hit the EoF to exit.\n");
printf("%s","?");
scanf("%d%29s%lf", &actNumber, actName, &actBalance);
while (!feof(stdin)) {
fprintf(fPtr, "%d, %29s, %.2lf\n", actNumber, actName, actBalance);
printf("%s", "?");
scanf("%d%29s%lf", &actNumber, actName, &actBalance);
}
fclose(fPtr);
}
return;
}
The end of file marker is set on stdin only when you press a special key combination on the console.
You can make your loop work correctly by using the return value of scanf(), like this
while (scanf("%d%29s%lf", &actNumber, actName, &actBalance) == 3)
{
fprintf(fPtr, "%d, %29s, %.2lf\n", actNumber, actName, actBalance);
printf("%s", "?");
}
After the first scanf() a '\n' character is left in the input stream, when you call scanf() again inside the loop, the character is consumed then ignored, and scanf() fails returning a value that is less than 3, the process is repeated over and over causing the infinite loop.
The following solution, however, is better. Using fgets() allows a better handiling of the '\n' character left unread in the stdin,
char line[100];
while (fgets(line, sizeof(line), stdin) != NULL)
{
if (sscanf(line, "%d%29s%lf", &actNumber, actName, &actBalance) != 3)
continue;
fprintf(fPtr, "%d;%29s;%.2lf\n", actNumber, actName, actBalance);
fprintf(stdout, "?");
}
note that I remove the white spaces in the printf() format, and replaced the , with ; because in some locales the , is the decimal separator, it's just instintictive not to use it, you can use it if you ensure that . is the decimal separator.
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.