Code:
struct subscriber
{
char phonenumber[20];
char name[50];
float amount;
}s;
void addrecords()
{
FILE *f;
char test;
f=fopen("file.txt","ab+");
//if(f==0)
//{ f=fopen("file.txt","wb+");
//system("clear");
//printf("please wait while we configure your computer");
//printf("/npress any key to continue");
//getchar();
//getch();
//}
while(1)
{
//system("clear");
printf("\n Enter phone number:");
scanf("%s",s.phonenumber);
printf("\n Enter name:");
fflush(stdin);
//scanf("%[^\n]",s.name);
scanf("%s",s.name);
printf("\n Enter amount:");
scanf("%f",&s.amount);
printf("check 1");
fwrite(&s,sizeof(s),1,f);
fflush(stdin);
printf("check 2");
//system("clear");
printf("1 record successfully added");
printf("\n Press esc key to exit, any other key to add other record:");
test=getchar();
//test=getche();
if(test==27)
break;
}
fclose(f);
}
I am facing two problems here:
Nothing is getting written to file although file is being created.
After I enter the amount it outputs all the print statements and goes to the initial of the while loop that is it does not wait at getchar.
The last scanf() doesn't read the newline at the end of the input, that's why getchar() returns immediately and doesn't wait and that's also the cause of the first problem, why the file isn't written, because you have to terminate the program to exit and the file isn't flushed. so you need to consume the newline char at the end of the last input you can do that with scanf()
scanf("%f%*[^\n]%*c",&s.amount);
Or using fgets() to read the whole line and using scanf() on that. Finally, note that you shouldn't use fflush() to clear an input stream, it's undefined:
7.19.5.2.2 If stream points to an output stream or an update stream in which the most recent operation was not input, the fflush function
causes any unwritten data for that stream to be delivered to the host
environment to be written to the file; otherwise, the behavior is
undefined.
fflush is never necessary if you have fclose.
But in your case, you have while(1) and fclose outside, that means fclose never get called so the file content never gets updated by fclose function.
You might want to use fflush inside the loop, e.g. right after fwrite, then it will flush the buffer to actual file.
You have named your file file.txt, so I assume you intend the file to be a text file? But then you open it with the b flag, which indicates binary format, and you write to it using fwrite, which doesn't convert the data to text, but just dumps the internal format to the file.
If you look at the created file in some sort of binary editor, you will see that it contains the data.
Related
I am trying to write user input to a txt file using a while loop.
But for some reason that I don't know, the while loop doesn't stop by clicking 'enter'.
when I click 'enter', I see "while loop executed" so I know the while loop iterated again even though I wanted to stop the while loop.
How to do it in a right way?
P.S: I use Microsoft Visual Studio recommended by my professor.
#include <stdio.h>
#include <string.h>
void main()
{
//writing to file
char write[100];
char fileName[100];
printf("give a name for file: ");
gets_s(fileName,99);
strcat(fileName,".txt");
FILE* pF = fopen(fileName, "w");
printf("what needs to be written?\n: ");
while(gets_s(write,99) != NULL)
{
printf("whileloop executed\n");
fprintf(pF,"%s\n", write);
}
fclose(pF);
}
Per Microsoft's gets_s() documentation, gets_s() returns NULL on end-of-file and error conditions:
Return Value
Returns buffer if successful. A NULL pointer indicates an error or
end-of-file condition. Use ferror or feof to determine which one
has occurred.
Hitting the enter key does not close the input stream and cause an end-of-file condition. It just places a zero-length line terminated with a newline in the input stream.
To do that on Windows from a terminal, one usually has to enter the CTRL-Z key combination.
You need to do some handling there as gets_s() will return and empty string when enter is hit. You can write an extra function to handle that:
size_t my_gets(char *buf,size_t len)
{
size_t ret=0;
if(gets_s(buf,len))
ret = strlen(buf);
return ret;
}
Then change your loop to:
while(my_gets(write,99))
{
...
P.S.- You should avoid calling variables with the same name of system functions (i.e. write).
I am trying to make a program which will store the data entered by the user in a text file whose name is provided by the user. Program will terminate when the user enters exit. strcmp function of string.h is used for string comparison and fgets() is used to read data from stdin.
Here is my code.
#include<stdio.h>
#include<string.h>
void main()
{
char file[60]; // will store file name
printf("Enter file name: ");
fgets(file, 59, stdin);
FILE *fp = fopen(file, "a+"); // open file in append mode
if(fp == NULL){
printf("File not found !");
return;
}
char data[100];
printf("Enter some data to add to file(exit to terminate): ");
fgets(data, 99, stdin);
int flag = strcmp(data, "exit");
while(flag != 0){
fputs(data, fp);
fgets(data, 59, stdin);
flag = strcmp(data, "exit");
printf("%d\n", flag); // for checking whether string are correctly comapred or not
}
printf("Bye");
}
Program does not terminate even if i enter exit. I have also tried concatenating "\n" at the end of string input by user but that also doesn't help. Although, gets() function works fine, but i know it is not preferred to use to I shifted to fgets() but it doesn't work for me.
Check the man page for fgets(), it reads and stores the newline (caused by pressing ENTER) after the entered input. Thus, the strcmp() fails.
You have to manually strip the input buffer off the newline, before you can compare the input. A simple yet elegant way of doing that would be
data[strcspn(data, "\n")] = 0;
fgets reads in a complete "line", i.e. a sequence of characters until (and including!) a new line character. Hence, when a user presses "Enter", the new line will be part of the string read in and a strcmp(data,"exit") will evaluate to "not equal".
So either strip off the new line before comparison, or compare with a string literal including a new line. Since you write the data as is(i.e. including the new lines) to a file, it seems cumbersome to first strip the new line off and add it then in the output manually. So I'd actually suggest the second approach:
fgets(data, 100, stdin);
flag = strcmp(data, "exit\n");
An alternative would be to use strstr if excess characters do not matter (i.e. your program would exit if the user types "exit" or "asdfexitasdf". - both of which contain "exit".)
So
int flag = strstr(data, "exit");
if(flag != NULL)
//exit the program
else
//stay in the program
In the code below, extra spcaes (may be around 300 space) are getting appended if I write data after seeking the file pointer to the start position after the line
fseek(fp1,0,SEEK_SET);
If I comment second fputs() function call, there is no issue.
Also the inputted data is not getting appended at the end, instead only spaces are getting appended.
I am unable to identify the problem.
I am using TDM-GCC-64 compiler.
For testing purpose, file1.txt had contents "Welcome to You All" at the beginning.
Inputted data: "Today"
Output after execution of the program: "Todayme to You All" followed by many spaces.
int main()
{
FILE *fp1;
char ch;
char data[50];
fp1=fopen("file1.txt", "r+");
if(fp1==NULL)
{
printf("Error in Opening the file\n");
return(0);
}
printf("Read and Write Mode. The data in the file is\n");
while((ch=getc(fp1))!=EOF)
{
putc(ch,stdout);
}
// Write some data at the end of the file
printf("\nEnter some data to be written to the file\n");
gets(data);
fseek(fp1,0,SEEK_END);
fputs(data,fp1);
fseek(fp1,0,SEEK_SET);
fputs(data,fp1);
printf("data in file after write operation is\n");
while((ch=getc(fp1))!=EOF)
{
putc(ch,stdout);
}
fclose(fp1);
return 0;
}
You should check the fine print in the fopen documentation:
In update mode ('+'), both input and output may be performed, but output cannot be followed by input without an intervening call to fflush, fseek, fsetpos or rewind, and input cannot be followed by output without an intervening call to fseek, fsetpos or rewind, unless the input operation encountered end of file.
Reading and writing might be buffered, but still share a single file position. Switching modes without alerting the runtime (fseek) could mess up the buffering. Like you have noticed!
Below is a small program which takes information from user and write it into a file teacher.txt.
I am using only one array q2[30] for taking input and writing into a file using fprintf().
But when i want to enter more teacher then again loop will execute but at this time fclose() will not appear
so data will not be write/save(don't know) into file also previous value of q2 get erased/overwrite with new input.
So in this case where data is stored/write by fprintf().Because when i manually open teacher.txt before fclose() there is no any new data.
#include <conio.h>
#include <iostream.h>
int main()
{
system("cls");
int yoe;
char cond[]="yes";char q2[30];
FILE *p;
p = fopen("teacher.txt","a+"); //opening file in reading + appending mode
printf("\nDo you want to add more Teacher ? (yes/no)\n");
gets(q2);
fflush(stdin);
if(!strcmp(q2,cond))
{
do
{
printf("\nEnter Teacher's Name\n");
gets(q2);
fprintf(p,"\n!%s!",q2);
printf("Enter Teacher's Qualifications\n");
fflush(stdin);
gets(q2);
fprintf(p,"%s!",q2);
printf("Enter Teacher's year of experience (0-30)\n");
fflush(stdin);
scanf("%d",&yoe);
fprintf(p,"%d!",yoe);
printf("Enter Teacher's Mobile number(id) [Should be of 10 digits]\n");
fflush(stdin);
gets(q2);
fprintf(p,"%s!",q2);
printf("\nDo you want to add more Teacher ? (yes/no)\n");
fflush(stdin);
gets(q2);
}while(!strcmp(q2,cond)); // condition to check , if user want to add more Teacher , if yes then loop will execute again.
fclose(p); // when user enter 'no' then only fclose will appear.
}
fclose(p);printf("\nPress any key to return to Admin menu\n");
getch();
system("pause");
}
When you open a file with fopen, the output you write is buffered, meaning it's not actually send to the lower layers until the buffer is either full or you explicitly flush it with fflush.
Also note that the layers under fopen/fprintf/fclose, all the way down to the actual hardware, may also have some buffering that can delay the actual update of the on-disk data.
I made a following program.The program shows no compiler error. There exist a file alive.txt in the directory. I want to use gets to write string to the file alive.txt but its not working properly.
#include<stdio.h>
#include<conio.h>
#include<ctype.h>
int main()
{
FILE *myfile;
char c,d;
char e[100];
myfile=fopen("alive.txt","r");
if(!myfile)
{
puts("Disk Error");
return(1);
}
while((c=fgetc(myfile))!=EOF)
{
putchar(c);
}
puts("\n");
puts("Do ya want to overwrite this file:{Y/N}");//
d=toupper(getchar());
if(d!='Y')
{
puts("Ok.. See ya Later");
return(1);
}
myfile=fopen("alive.txt","w");
puts("Type The Character to overwrite");
gets(e); // scanf works
fprintf(myfile,"%s",e);
fclose(myfile);
getch();
return(0);
}
The file is already open for reading from when you open it for writing to. Add
fclose(myfile);
before the second fopen.
The problem is that gets() reads the newline after the Y and realizes 'end of line', and returns an empty string (because it removes the newline), so there's nothing written to the file. If you use scanf("%s", e); instead of gets(), the %s format skips leading white space (such as the newline after the Y) and reads the next word.
Other problems include:
You're also leaking file descriptors (file streams) because you don't fclose() the myFile from the first fopen().
You're using gets() which is, as stated in a comment, a very bad idea. (Teachers who suggest using gets() should be forcibly restrained from teaching; students who use gets() should be given 0 marks automatically.) Don't use gets(); use fgets() or
getline() instead. Note that fgets() includes the newline in the data if there's space for it.
You're using char c; and then trying to detect EOF with it — which is unreliable.
You don't check that your fopen() calls succeed; you use the file pointer anyway, which will cause your program to crash if the file isn't there for any reason.
#include<stdio.h>
//#include<conio.h> Non-portable
#include<ctype.h>
int main()
{
FILE *myfile;
char c,d;
char e[100];
myfile=fopen("alive.txt","r");
if(!myfile)
{
puts("Disk Error");
return(1);
}
/* Show the current file content. */
while((c=fgetc(myfile))!=EOF)
{
putchar(c);
}
fclose(myFile); // Close the read-only file mode.
puts("\n");
puts("Do ya want to overwrite this file:{Y/N}");
d=toupper(getchar());
if(d!='Y')
{
puts("Ok.. See ya Later");
return(1);
}
/*Flush '\n' character from stdin */
getchar();
puts("Type The Characters used to overwrite");
gets(e); // scanf works
myfile=fopen("alive.txt","w"); Re-open in write mode, deleting old file content.
fprintf(myfile,"%s",e);
fclose(myfile);
// getch(); Non-portable
/* Be nice and close the file when finished with it. */
fclose(myfile);
return(0);
}