Anas Ayubi
Anas Ayubi

Reputation: 257

Writing and Reading from a file at the same time

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

Answers (4)

John Bollinger
John Bollinger

Reputation: 181459

There are three main problems with your code:

  1. 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.

  2. 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.

  3. You do not close the file when you're done.

and at least two secondary problems:

  1. 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.

  2. 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

Anas Ayubi
Anas Ayubi

Reputation: 257

There are two main problems with the code here:

  1. "r+" mode must be used here instead of "w+".

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.

  1. A position setting function must be used when switching from either reading to writing or from writing to reading data.

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

utarid
utarid

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.

You should use "r+".

"r+" read/update: Open a file for update (both for input and output). The file must exist.

Upvotes: 2

Amina
Amina

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

Related Questions