Reputation: 257
I've been trying to read and write from a file at the same time and I'm trying to substitute all the tabs in the content of text.txt to be turned into spaces. This is my code:
int main()
{
FILE* filePtr = fopen("text.txt", "w+");
char c;
c = fgetc(filePtr);
fpos_t num;
while(c != EOF)
{
if(c == '\t')
{
fgetpos(filePtr, &num);
num--;
fsetpos(filePtr, &num);
fputc(' ', filePtr);
}
c = fgetc(filePtr);
}
}
The content of text.txt is as such:
Hi \t my \t name \t is \t jack!
When I run this code, my output in the text.txt file is just blank space. There are no characters there. What should I do so that the substitutions work out as intended?
Upvotes: 5
Views: 23714
Reputation: 181459
There are three main problems with your code:
Opening the file with mode "w+"
truncates the file (removes all contents). You can both read and write to it, but the original contents are lost. Mode "r+"
would open it for reading and writing without changing the contents, and with the file position initially at the beginning of the file.
It is not safe to perform arithmetic on a value of type fpos_t
. It's anyway needless; there's an easier way to move the file position a relative amount.
You do not close the file when you're done.
and at least two secondary problems:
fgetc()
returns int
, not char
, with values in the range of unsigned char
, plus EOF
, which is guaranteed outside that range. If you convert the result to char
then at best, there will be one real character value that you will not be able to distinguish from EOF
.
For more graceful failure behavior, you should check the return value of fopen()
to verify that it succeeded, and proceed accordingly if it did not. (Not demonstrated below.)
This variation on your code works for me:
#include <stdio.h>
int main(void)
{
FILE* filePtr = fopen("text.txt", "r+");
int c;
while((c = fgetc(filePtr)) != EOF)
{
if(c == '\t')
{
fseek(filePtr, -1, SEEK_CUR);
fputc(' ', filePtr);
}
}
fclose(filePtr);
return 0;
}
Upvotes: 10
Reputation: 257
There are two main problems with the code here:
The "w+" mode deletes all the contents of a file if it exits from before and then writes to the file, while the "r+" mode enables you to use the present data from before.
From Pelles C help file:
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, output shall not be directly followed by input without an intervening call to the fflush function or to a file positioning function (fseek, fsetpos, or rewind), and input shall not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end-of-file.
This is the code that worked for me:
int main(void)
{
FILE* filePtr = fopen("text.txt", "r+");
char c;
while( (c = fgetc(filePtr)) != EOF )
{
if(c == '\t')
{
fseek(filePtr, -1, SEEK_CUR);
fputc(' ', filePtr);
fseek(filePtr, 0, SEEK_CUR);
}
}
fclose(filePtr)
return 0;
}
Upvotes: 2
Reputation: 1715
Quoting cplusplus.com,
"w+" write/update: Create an empty file and open it for update (both for input and output). If a file with the same name already exists its contents are discarded and the file is treated as a new empty file.
"r+" read/update: Open a file for update (both for input and output). The file must exist.
Upvotes: 2
Reputation: 414
The problem is that you are using the w+
fopen flag and trying to decrement a fpos_t
variable which is a complex type. You should use r+
and then decrement num.__pos
to get it working
Upvotes: 1