Why is rewind() not working as expected in this simple program? - c

Why is the below program not printing the first character of the newly created text file ("E") as expected? It's a simple program and I tried to look at the issue from all aspects but couldn't find the reason. The text file is being created on my D drive with the content "EFGHI", but for some reason "E" is not being read even if I rewind and read using getc() and the output is -1.
#include<stdio.h>
#include<stdlib.h>
int main()
{
int x;
FILE *fp;
fp=fopen("F:\\demo.txt","w");
if(fp==NULL)
puts("Write error");
fputs("EFGHI",fp);
rewind(fp);
x=getc(fp);
printf("%d",x);
fclose(fp);
}
UPDATED:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int x;
FILE *fp;
fp=fopen("F:\\demo.txt","w+");
if(fp==NULL)
{
puts("Write error");
exit(EXIT_SUCCESS);
}
fputs("EFGHI",fp);
rewind(fp);
while(!feof(fp))
{
x=getc(fp);
printf("%d\n",x);
}
fclose(fp);
}

File mode "w" opens the file for writing only.
Use "w+" to open a file for writing and reading.
(Please see man fopen for more file modes.)
Regarding getc() returning -1, verbatim from man getc:
[...] getc() [...] return[s] the character read as an unsigned char cast to an int or EOF on end of file or error.
EOF typically equals -1. To test this do a printf("EOF=%d\n", EOF);

fp=fopen("F:\\demo.txt","w");
Opens the file for writing, then you try to read from it. That's not going to work.
I'll also note that your program keeps trying to use fp even if it fails to be created since your if checking fp only prints an error, it doesn't stop the program.

Related

C program not writing to a file

I was reading "C: How to program" on chapter 11 (File handling) and came with this algorithm, to append a string to a file named info.txt but it isn't working at all. What am I doing wrong?
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main(void)
{
FILE *fp = fopen("info.txt","w");
char buff[100];
if(fp == NULL){
fprintf(stdout,"Error opening file\n");
exit(1);
}
while(!feof(stdin)){
fprintf(stdout,"Type a string/\nEOF ends input\n");
if(!fgets(buff,sizeof buff,stdin)){
fprintf(stderr,"Error reading string");
exit(2);
}
buff[strcspn(buff,"\n")] = 0;
fprintf(fp,"%s",buff);
}
fclose(fp);
}
I guess you are inserting EOF wrongly. As it is answered here, EOF is inserted using CTRL+D in Unix systems and using CTRL+Z in Windows.
Using exactly your code it works for me, so I guess you are trying to insert EOF using CTRL+C, or another command, which closes the application and leaves the file empty.
Also, if you want it to append always, even if you close the program and open it again, you should use the mode append "a" instead of write "w" [reference]
FILE *fp = fopen("info.txt","a");

How to read a file that was fseeked?

I have no idea why this does not work:
#include <stdio.h>
int main(){
FILE* fp = fopen("txt2","wr");
if(!fp) return 1;
fprintf(fp,"20");
fseek(fp,0,SEEK_SET);
fprintf(fp,"19");
rewind(fp);
char c;
while((c=fgetc(fp))!=EOF)
printf("%c",c);
}
Here should be write 20, then rewrite to 19, set the position to start of file, and the read the char till EOF (so should print 19). But prints nothing. Why is that?
I have tried to make better check for return poitner to fp (because of wr):
EDIT:
#include <stdio.h>
int main(){
FILE *fp = fopen("txt","wr");
if(!fp){
printf("nada\n");
return 1;
}
}
But it compiles without problem. Why is that? The wr should be UB (and thus cause segfault or another err) or?
The mode "wr" is not valid string for POSIX fopen() or Microsoft fopen(). You probably want to use "w+". Using "r+" would be an alternative, but then the file must exist before you open it.
The implementation of fopen() that you're using probably treats "wr" as equivalent to "w" (unless it reports an error and your program exits — it is a good idea to report why you are exiting). You can't read from a write-only file stream.
Strictly, you should also use int and not char for the variable c because fgetc() returns an int.

can't access a place in memory

I'm trying to read a binary file of 32 bytes in C, however I'm keep getting "segmentation fault (code dumped)" when I run my program,
it would be great if somebody can help me out by pointing where did I go wrong?.
my code is here below:
int main()
{
char *binary = "/path/to/myfiles/program1.ijvm";
FILE *fp;
char buffer[32];
// Open read-only
fp = fopen(binary, "rb");
// Read 128 bytes into buffer
fread (buffer, sizeof(char), 32, fp);
return 0;
}
It's because of the path. Make sure that "/path/to/myfiles/program1.ijvm" points to an existing file.
You should always check the return value of fopen.
\\Open read-only
fp = fopen(binary, "rb");
if(fp==NULL){
perror("problem opening the file");
exit(EXIT_FAILURE);
}
Notice also that you are reading 32 bytes in your buffer and not 128 as your comment says.
You must check the return result from fopen().
I'm assuming you are getting the segfault in the fread() call because your data file doesn't exist, or couldn't be opened, and you are trying to work on a NULL FILE structure.
See the following safe code:
#include <stdio.h>
#include <stdint.h>
#define SIZE_BUFFER 32
int main()
{
char *binary = "data.txt";
FILE *fp = NULL;
char buffer[SIZE_BUFFER];
// Open read-only
fp = fopen(binary, "rb");
// Read SIZE_BUFFER bytes into buffer
if( fp )
{
printf("Elements read %ld\n", fread (buffer, sizeof(char), SIZE_BUFFER, fp));
fclose(fp);
}
else
{
// Use perror() here to show a text description of what failed and why
perror("Unable to open file: ");
}
return 0;
}
When I execute this code it doesn't crash and will print the number of elements read if the file is opened or it will print "Unable to open file" if the file could not be opened.
As mentioned in the comments you should also close the file being exiting. Another thing you can do is the following:
FILE *fp = fopen(.....);
Instead of declaring and assigning in two separate steps.
There are two possible reasons
The fopen(3) function failed due to some reason, which means fp is NULL, and then you are trying to use the null-pointer in fread(3). This can crash. #OznOg has already given a subtle hint to look into this direction.
If the fopen call is a success (i.e. fp is non-NULL after calling fopen), the code can still crash because you are reading 32 chars into the variable binary, while binary has been initialized with only 30 chars.

read operation without fseek in a+ mode causes extra white spaces in the file

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);
}

program crashes due to file format

i was trying this problem from usaco. when i use txt file while using file the program is working fine. but when for the submission requirement i change the format to beads.in and beads.out the program crashes. what;s the problem?
here's my code:
#include <stdio.h>
#include<string.h>
main () {
FILE *fin = fopen ("beads.in", "r");
FILE *fout = fopen ("beads.out", "w");
int n;
char str[400];
char now,rev_now;
int pos,forward,reverse,sum,max=0,i,j,k;
fscanf(fin,"%d\n%s",&n,str);
n--;
for(pos=0;pos<=n;pos++){
now=str[pos];
if(pos==0)k=n;
else k=pos-1;
rev_now=str[k];
forward=2;
int flag1=0,flag2=0,reverse=2;
for(i=pos,j=k;;){
if(i==n)i=-1;
if((str[i+1]==now||str[i+1]=='w')&&flag1==0){
i++;
forward++;
}
else{
flag1=1;
}
if(j==0)j=n+1;
if((str[j-1]==rev_now||str[j-1]=='w')&&flag2==0){
j++;
reverse++;
}
else{
flag2=1;
}
if(flag1==1 && flag2==1)break;
}
sum=forward+reverse;
if(max<sum){max=sum;}
}
fprintf(fout,"%d\n",max);
return 0;
}
are you sure beads.in and beads.out are created already..
According to man page
r Open text file for reading. The stream is positioned at the
beginning of the file.
w Truncate file to zero length or create text file for writing.
The stream is positioned at the beginning of the file.
May be beads.in is not created in prior to fopen. It's better if you check the status of the fopen, use perror.
You mention that it works with a text file. I'm guessing that beads.in is not a text file, but rather a binary file. If that is the case, then #KVD's suggestion above to use: fopen ("beads.in", "rb"); and fopen ("beads.out", "wb"); should work. The reason the program would crash with binary input data is because you are asking fscanf to copy data into your str buffer until it encounters a newline character. More than likely, the beads.in file has more than 400 characters which will cause a buffer overflow and start overwriting the program stack.

Resources