Usage of fseek and feof - c

I this code is used for reading the text file in reverse order. And it successful does, displaying the original content of file and the reversed content of file.
#include <stdio.h>
#include <stdlib.h>
int main() {
int count = 0, ch = 0;
FILE *fp;
if( (fp = fopen("file.txt", "r")) == NULL ) {
perror("fopen");
exit(EXIT_FAILURE);
}
printf("\tINPUT FILE\n");
printf("\n");
while(!feof(fp)) {
if((ch = getc(fp)) != EOF) {
printf("%c", ch);
count ++;
}
}
feof(fp);
printf("\n");
printf("\tREVERSED INPUT FILE\n");
printf("\n");
while(count) {
fseek(fp, -2, SEEK_CUR);
printf("%c", getc(fp));
count--;
}
printf("\n");
fclose(fp);
}
But when i replaced, this piece of code
while(!feof(fp)) {
if((ch = getc(fp)) != EOF) {
printf("%c", ch);
count ++;
}
}
by
fseek (fp, 0, SEEK_END); or feof(fp);
Basically i just went till end of file and directly without printing the original contents of file and tried printing the reversed content of file.
But for it does not print the reversed content filed either !!! it just display blank. Why is this happening ??
NOTE: fseek(fp, -2, SEEK_CUR); Have done this (in another while loop) as getc(fp) moves fp forward by one so need to rewind it back by two, also initially it will be pointing to EOF
What is happening here? Can any one please explain?

It breaks because the second loop is while (count), and count is zero if you haven't read through the file first while incrementing it. You can use ftell to obtain the equivalent of count in this case.
P. S. feof(fp) only tests whether fp is at end-of-file, it does not make it seek to EOF, so the line feof(fp) basically does nothing since you aren't using the return value.

As #Arkku already showed, when you replace the while loop with fseek(SEEK_END), count will not be incremented.
To fix this, you can use ftell after fseek, which returns the file length
fseek(fp, 0, SEEK_END);
count = ftell(fp);
Now the file will be printed backwards.

Related

there is some text in a file and I have to put '\n' after every ending of a sentence. I am stuck

char text[1024];
fgets(text, 1024, stdin); //Foydanaluvchi kiritadi matn
FILE * file = fopen("my.txt", "w"); //yozish uchun file degan fayl ochiladi
for(int i=0; i<strlen(text); i++){
if(text[i] == 46){
fseek(file, 0, SEEK_CUR);
fputc(text[i]='\n', file);
}else{
fputc(text[i+1], file);
}
}
fclose(file);
Your logic does not make sense. Work it out on paper with a simple example to see that
here:
fputc(text[i]='\n', file);
you are writing a newline instead of the period, not after it; and
here:
fputc(text[i+1], file);
you are writing a different character than the one you just tested. Moreover,
this:
fseek(file, 0, SEEK_CUR);
asks to adjust the file position to its own current value. There may be circumstances where that's actually useful, but yours are not among them.
I think you're making it harder than it should be. All you really need to do to implement the behavior described is loop through the data, write each character, and if that character was a period ('.') then additionally write a newline.
Although the question does not say so, possibly you are expected to avoid adding extra newlines where there already is one after a sentence. That would require looking ahead at least one character, but it is doable.
You might also consider reading the file one character at a time (with getchar(), say). That would actually make your logic a little simpler, and it might smooth out some technical details if you have to avoid adding duplicate newlines, or if you need some other extra behavior such as eliminating space characters between sentences.
It is difficult to modify the file in place as you are trying to do, because there is no standard function or system call to insert bytes in the middle of a file.
The recommended approach it to write a simple filter that reads the text from stdin and writes the modified contents to stdout:
#include <stdio.h>
int main() {
int c;
while ((c = getchar()) != EOF) {
putchar(c);
if (c == '.')
putchar('\n');
}
return 0;
}
Note however that the above code will add a newline after each ., some of which might not end a sentence, eg: I paid $3.49 for each bug and some of which may already be followed by a newline, thereby doubling them.
To avoid both of the above pitfalls, you might only output the newline if the . is followed by a space. In this case, you can replace the space after each . with a newline, so you could operate in place on systems where newline is a single byte:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
FILE *fp;
int c, last = 0, count = 0;
if (argc < 2) {
fprintf(stderr, "missing file name\n");
return 1;
}
if ((fp = fopen(argv[1], "rb+")) == NULL) {
fprintf(stderr, "cannot open file %s: %s\n", argv[1], strerror(errno));
return 1;
}
while ((c = getc(fp)) != EOF) {
if (c == ' ' && last == '.') {
// call fseek to move back one byte
fseek(fp, -1L, SEEK_CUR);
// overwrite the space with a newline
putc('\n', fp);
// call fseek to allow switching back to read mode
fseek(fp, 0L, SEEK_CUR);
count++;
}
last = c;
}
fclose(fp);
printf("%d changes\n", count);
return 0;
}

C remove() function doesn't delete target file in windows environment

I'm writing a program that asks the user for a file name, and creates it if it doesn't exist. At the end of the program, I want to check if the created program is empty, and if it is, delete it. Not deleting it and then running the program with that same file name messes up the way the input is detected.
I've tried using rewind() to go back to the beginning and then checking feof() to see if the beginning of the file was the EOF character, but that didn't work.
Then, I did some searching online, and found a method that used fseek() to go to the end of the file, and then checked with ftell() whether the end of the file was at position 0, but again this did not work.
I went back and did more poking around, and found that the problem might be because I hadn't used fclose() first, so I tried the previous two attempted solutions again, this time being sure to close the file before trying to delete it. Still no dice.
I tried checking what errno was set to, and got 2: No such file or directory. This is patently false, since if that was the case, it would mean that I had accomplished my goal, and when I check the working directory, the file is still there.
I have absolutely no idea what to try next. Can anyone point me in the right direction?
Here are the ways I've tried to delete the file (fp is the file pointer, and file is a char pointer with the name of the file that fp points to.) :
Attempt 1:
rewind(fp);
if(feof(fp)){
remove(file);
}
Attempt 2:
fseek(fp, 1, SEEK_END);
long size = ftell(fp);
if(size == 0){
remove(file);
}
Attempt 3:
fseek(fp, 1, SEEK_END);
long size = ftell(fp);
fclose(fp);
if(size == 0){
remove(file);
}
Attempt 4:
rewind(fp);
int empty = 0;
if(feof(fp)){
empty = 1;
}
fclose(fp);
if(empty == 1){
remove(file);
}
UPDATE: Here's a couple MCVEs, one for each method.
#include <stdio.h>
#include <errno.h>
int main() {
FILE *fp;
char file[40];
scanf(" %[^\n]s", file);
fp = fopen(file, "r");
if(fp == NULL){
fp = fopen(file, "w");
int result;
rewind(fp);
int empty = 0;
if(feof(fp)){
empty = 1;
}
fclose(fp);
if(empty == 1){
result = remove(file);
}
printf("%d\n", result);
printf("%d\n", errno);
return 0;
}
Version 2:
#include <stdio.h>
#include <errno.h>
int main() {
FILE *fp;
char file[40];
scanf(" %[^\n]s", file);
fp = fopen(file, "r");
if(fp == NULL){
fp = fopen(file, "w");
int result;
fseek(fp, 1, SEEK_END);
long size = ftell(fp);
fclose(fp);
if(size == 0){
result = remove(file);
}
printf("%d\n", result);
printf("%d\n", errno);
return 0;
}
UPDATE 2:
I just realized that when I was making the MCVEs, when I ran them, result was returning 0, which should have meant that it was successful, but the file was still there in the directory. I'm at a loss for words.
The code wasn't reaching the remove statement.

C - FILE IO Read and Write Error

I am trying to swap the existing characters from the file with new characters one by one. The new characters are obtained by manipulating the existing characters by subtracting one from the ASCII code. The file already exists with text, but I ended up getting an infinite loop for some reason. What am I doing wrong?
#include <stdio.h>
int main()
{
FILE *fp = fopen("myfile.txt", "r+");
if (fp == NULL)
printf("File cannot be opened.");
else
{
// Used for retrieving a character from file
int c;
// Pointer will automatically be incremented by one after executing fgetc function
while ((c = fgetc(fp)) != EOF)
{
// Decrement pointer by one to overwrite existing character
fseek(fp, ftell(fp)-1, SEEK_SET);
// Pointer should automatically increment by one after executing fputc function
fputc(c-1, fp);
printf("%c\n", c);
}
fclose(fp);
}
return 0;
}
-EDIT-
I changed datatype of c from char to int, but problem still persisted. However, my problem has been resolved by adding fseek(fp, 0, SEEK_CUR) after fputc() call. I believe Jonathan Leffler's comment should become an answer since this kind of problem was not answered from the other question.
try this
#include <stdio.h>
int main(void){
FILE *fp = fopen("myfile.txt", "r+");
if (fp == NULL) {
printf("File cannot be opened.");
return -1;
}
int c;
long pos = ftell(fp);
while ((c = fgetc(fp)) != EOF){
fseek(fp, pos, SEEK_SET);//In the case of text file Do not operate the offset.
fputc(c-1, fp);
fflush(fp);//To save the output.
pos = ftell(fp);
printf("%c\n", c);
}
fclose(fp);
return 0;
}

File read write mode "r+" unexpected behavior in C

In the following code, I am searching for a '.' in my template to paste a string after it. For some reason, although the string is pasted as expected, it deletes some text from my template. I do not have an idea where the problem could be. Tried fflush() with no good effect.
#include <stdio.h>
#include <string.h>
int main() {
FILE * fp;
int tmp_char, tmp_offset;
char file_name[50] = "FileIoTest_template.txt";
char tmp_string1[50] = "Generic String 1";
char tmp_string2[50] = "Generic String 2";
long tmp_long;
fp = fopen(file_name, "r+");
//fseek(fp, 0, SEEK_SET);
do {
tmp_char = fgetc(fp);
printf("%c ", tmp_char);
if (tmp_char == '.')
break;
} while (tmp_char != EOF);
tmp_long = ftell(fp);
fseek(fp, tmp_long, SEEK_SET);
tmp_offset = strlen(tmp_string1);
fputs(tmp_string1, fp);
fputs("\n", fp);
//fflush(fp);
fseek(fp, tmp_long+tmp_offset, SEEK_SET);
do {
tmp_char = fgetc(fp);
printf("%c ", tmp_char);
if (tmp_char == '.')
break;
} while (tmp_char != EOF);
tmp_long = ftell(fp);
fseek(fp, tmp_long, SEEK_SET);
fputs(tmp_string2, fp);
fputs("\n", fp);
//fflush(fp);
fclose(fp);
return 0;
}
Here is my template, "FileIoTest_template.txt":
Sample list:
1.
2.
3.
random text
4.
5.
6.
bunch of random text
The output of my code is:
Sample list:
1.Generic String 1
ext
4.Generic String 2
of random text
You cannot easily modify a file by inserting data into the middle of it without replacing anything that's already there. You would need to overwrite the whole file, from the insertion point to the end (past the original end to whatever point the new end needs to be). It is tricky to do so correctly, and it is unsafe to try, for if the process is interrupted in the middle then your file is trashed.
Usually, one instead creates a new version of the file contents in a temporary file, and once that is completed successfully, one replaces the original file with the new one.

counting file characters with fseek

i want to count file chars like this :
#include <stdio.h>
#include <stdlib.h>
int main(){
int d=0;
char filename[25];
FILE *file;
printf("Enter file name to be read (Text File!) : ");
gets(filename);
file = fopen(filename, "rt");
if(file == NULL){
printf("Failed to open file...");
exit(1);
}
fseek(file, 0L, SEEK_SET);
while( !feof(file) ){
fseek(file, 1L, SEEK_CUR);
d++;
}
printf("%d", d);
}
after that im printing d and it value is 0..
and the file dose have chars. about 150 chars..
fseek() allows you to seek beyond the mark of EOF.
To get the file size, you could fseek(file, 0, SEEK_END) and then call ftell(file).
To read character by character, you could use for (i = 0; fgetc(file) != EOF; i++);.
I'm wondering if the program ever returns, as per fseek()'s documentation feof() shall never return anything <>0:
A successful call to the
fseek() function clears the end-of-file indicator for the stream
To determine the file size using fseek() do:
FILE * pf = ...;
fseek(pf, 0, SEEK_END);
long size = ftell(pf);
i did it like this at the end and it work.
fseek(file, 0, SEEK_END);
and then call
ftell(file);
befor i tryed to do it like that :
for (i = 0; fgetc(file) != EOF; i++);
and it didnt worked...but now it is 0.0
Thank you all..!

Resources