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!
Related
When I executed below code, m2.txt created correctly as expected with the specified data.
#include <stdio.h>
int main()
{
FILE *fp1;
char ch;
fp1=fopen("m2.txt", "a+");
fputs("Hello, data is appended\0", fp1);
fseek(fp1,0,SEEK_SET);
while((ch=getc(fp1))!=EOF)
{
putc(ch,stdout);
}
fclose(fp1);
return 0;
}
Now I commented fseek and executed the below code. (I deleted this m2.txt file before executing)
#include <stdio.h>
int main()
{
FILE *fp1;
char ch;
fp1=fopen("m2.txt", "a+");
fputs("Hello, data is appended\0", fp1);
//fseek(fp1,0,SEEK_SET);
while((ch=getc(fp1))!=EOF)
{
putc(ch,stdout);
}
fclose(fp1);
return 0;
}
To my surprise, displayed data on the screen had just whitespaces. Even "Hello, data is appended"was missing. Also the m2.txt file had many white spaces.
Why this problem? If fseek is not done before read, it should affect only read operation I thought. Why extra spaces are getting written to the file?
In a+ mode, read pointer is pointing to the beginning if no write operation is done. But in case write operation is done, pointer will be at the end I suppose. In such case, read should not be displaying anything without fseek right? In anycase, issues could be there with read. But why write is having issues even though write is done before read.
I am using Codeblock 15.12 and default mingw came with codeblock.
Edited:
I further thought if it could be some compiler related issue. Grabbed old Visual Studio 6 and compiled. Several lines of unreadable characters are printed at the end. So it is not compiler issue. Somewhere some silly issue is there it looks.
After some search, I found that fflush() or fclose() or fseek() is needed before reading the file. Otherwise the entire write buffer may be filled/affected. Tried with fflush() and write operation did not write any junk at the end even if fseek() is not called. Here is the code (Of course fseek() will be there inplace of fflush() in actual code. I just commented fseek and added fflush() for testing purpose).
int main()
{
FILE *fp1;
char ch;
fp1=fopen("m2.txt", "a+");
fputs("Hello, data is appended", fp1);
fflush(fp1);
// fseek(fp1,0,SEEK_SET);
while((ch=getc(fp1))!=EOF)
{
putchar(ch);
}
fclose(fp1);
return (0);
}
I have been trying out some file io and have written the following:
#include <stdio.h>
int main(){
char stuff [80];
FILE *file;
file=fopen("hello.cheese", "w+");
fprintf(file, "%s", "cheese");
fscanf(file, "%s", stuff);
printf("%s", stuff);
fprintf(file, "\n%s", stuff);
fclose(file);
return 0;
}
All this does is put ^A in the file (next line underneath cheese) and print nothing.
You might want to read closely fopen description, especially
When a file is opened with update mode ( '+' as the second or third character in the mode argument), both input and output may be performed on the associated stream. However, the application shall ensure that output is not directly followed by input without an intervening call to fflush() or to a file positioning function ( fseek(), fsetpos(), or rewind()), and input is not directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end-of-file.
You used 'w+' mode, which allows reading and writing, but did not flush, nor rewind file pointer after write.
As a side note, Your code could use some error checking (NULL != file).
So here is the problem:
I want to write some text to a text file, but I got across some weird situations:
SAMPLE 1:
int main()
{
FILE *file = fopen("structures.txt", "a+"); // open the file for reading & writing
int choice = 0;
if(file == NULL)
puts("Unable to open text file");
else {
do {
scanf("%d", &choice);
fprintf(file, "This is testing for fprintf...\n");
}while(choice > 0);
}
fclose(file);
return 0;
}
In this version of the program, nothing ever gets written to the text file & I can't understand why. But the strangest thing for me is next:
SAMPLE 2:
int main()
{
FILE *file = fopen("structures.txt", "a+"); // open the file for reading & writing
int choice = 0;
if(file == NULL)
puts("Unable to open text file");
else {
do {
scanf("%d", &choice);
fprintf(file, "This is testing for fprintf...\n");
fclose(file); // Added this line, the writing works
}while(choice > 0);
}
fclose(file);
return 0;
}
After adding fclose(file); directly after the fprintf call, the program successfully writes :
This is testing for fprintf...
to the text file.
My questions are:
Does that mean that I have to open my text file whenever I want to
write some text to it & close it directly afterwards ?
Does fclose() has anything to do with the writing process ?
What are the factors that prevent fprintf() from working ?
(1st sample)
How can I open & close the text file just ONCE, at the start of the program & at the end of it (respectively) guaranteeing at the same time that my program will work flawlessly ?
Does that mean that I have to open my text file whenever I want to write some text to it & close it directly afterwards ?
No, but it may mean you need to close the file before the contents you've written will actually be flushed and written out to the file.
Does fclose() has anything to do with the writing process ?
Most file streams are buffered. Meaning that each write goes to memory. It is not written to disk until the buffer is full or you call close.
What are the factors that prevent fprintf() from working ? (1st sample)
Anything you get significantly wrong.
How can I open & close the text file just ONCE, at the start of the program & at the end of it (respectively) guaranteeing at the same time that my program will work flawlessly ?
You could call something like fflush(). But are you sure you tried this and the file contained nothing even after you finally closed the file at the end?
I solved the problem using int fflush (FILE *stream) (which #Jonathan hinted at).
Flushing output on a buffered stream means transmitting all
accumulated characters to the file. There are many circumstances when
buffered output on a stream is flushed automatically:
When you try to do output and the output buffer is full.
When the stream is closed.
When the program terminates by calling exit.
When a newline is written, if the stream is line buffered.
Whenever an input operation on any stream actually reads data from its file.
So basically, I just had to call fflush() after the call to fprintf() :
fprintf(file, "This is testing for fprintf...\n");
fflush(file);
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.
I am trying to get a basic understanding on how to use fputc in C. I have read some documentation that is out there and believed I had it right. But every time I try to use the script I wrote by executing ./fputc > test.txt where text.txt is a text file with one line of text.
This is my script:
int
main(int argc, char **argv){
int ch;
FILE *input;
input = fopen("text.txt", "w+");
while ((ch = getchar()) != EOF){
fputc(ch, input);
}
fclose(input);
return 0;
}
I get no errors on compilation and for some reason the script does not reach EOF at the end of the text file. Shouldn't the getchar return EOF when it reached the end of the text file?
The text (text.txt) file does not appear to be edited, although it is created. So somewhere in my while loop something is going wrong.
I am new to C programming (if you couldn't tell) and this little script has me befuddled.
Any help would be appreciated, or any links to sites with further detail would also be great.
Cheers,
S.
What you in essence say is:
Console: Run my_program and write anything it outputs to test.txt.
Program: Open text.txt and write any input to stdin to that file.
Your console normally have three standard streams stdin, stdout and stderr. These streams you can redirect. If you are on Windows also look at i.e. redirection.
When you say ./my_prog > test.txt, what you tell your console, (not my_prog), is to write anything my_prog writes to stdout to the file test.txt.
If you in your code say i.e. printf("Hello");, then Hello would be written to the file test.txt.
If you had turned your redirection around by saying ./my_prog < test.txt instead, would be; stream the file test.txt to my_prog. Which, in turn, if there was any text in test.txt would result in a copy of test.txt to text.txt.
Now in your code you say:
int main(void)
{
int ch;
FILE *input;
/* Here you open a handle to the file text.txt for reading and writing */
input = fopen("text.txt", "w+");
while ((ch = getchar()) != EOF) { /* get next char from stdin */
fputc(ch, input); /* write that char to the handle input */
}
fclose(input); /* close the handle */
return 0;
}
So what happens, the way you run it, is:
In your code:
Open text.txt
Wait for input (data entered to stdin) - typically user entering text to console, passed to program when Enter is pressed.
In console:
Redirect anything from my_prog to test.txt.
You say:
the script does not reach EOF
Well, as it reads from stdin it will only (not without exception) get EOF under two conditions.
If you redirect a file to your program. I.e. ./my_prog < foo.txt (notice <, not >).
- What would happen then is that my_prog would read the data from the file foo.txt and when that file ends your program would receive a EOF. And, hence quit.
If you manually enter EOF to stdin.
- On Linux and OSX Ctrl-D, on Windows Ctrl-Z
Now, if you test this by typing text to console remember that write actions like fputc()is buffered. What this mean is that the data is not written to the file right away, but only when a given amount of data is in buffer, fflush() is called, stream is closed, you turn off buffering, etc.
Also; if you run your program. Enter text, enter some more text, and then hit Ctrl-C to abort the program it is a big chance you end with no data in your text.txt.
The reason for this is that the program is killed and thereby fclose() never called, and hence no flush to file.
On your further endeavors in programming it would be a very good idea to make a habit of not presuming anything. I.e. do not presume fopen() is OK.
FILE *fh;
char *outfile = "foo.txt";
if ((fh = fopen(outfile, "w")) == NULL) {
fprintf(stderr,
"Unable to open file %s\n --",
outfile);
perror(" fopen() ");
return 1;
}
Most functions has a way to check if operation was a success. I.e:
if (fputc(ch, fh) != ch) { err ...
This will make your code a lot safer, give you hints on where it fails etc.
Some links:
Look at redirection links at top of post.
Look at the functions in stdio.h (good overview), stdio.h (examples etc.). I.e.:
stdin
stdout
stderr
fopen()
fflush()
setvbuf()
setbuf()
...
getchar returns the next character from the standard input (stdin).
It is equivalent to getc with stdin as its argument.
Hence, your code reads from standard input instead of FILE* input.
Use fgetc here.
fgetc returns the character currently pointed by the internal file position indicator of the specified stream. The internal file position indicator is then advanced by one character to point to the next character.
So, Use fgetc to read from a file:
while ((ch = fgetc(input)) != EOF)
your program and the shell are both writing the same file. you should remove the output redirection > test.txt from your command line