3

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?

Anas Ayubi
  • 227
  • 1
  • 3
  • 9
  • Try reading some documentation – moffeltje Apr 16 '15 at 14:33
  • 1
    This probably isn't your underlying problem, but you can't assume you can do arithmetic with `num`. The [POSIX spec](http://pubs.opengroup.org/onlinepubs/009695399/functions/fsetpos.html) doesn't say you can do that, and (for example) the OS X manpage for this warns explicitly that ‘Although fpos_t has traditionally been an integral type, applications cannot assume that it is; in particular, they must not perform arithmetic on objects of this type.’ – Norman Gray Apr 16 '15 at 14:36
  • Are you sure you can decrement `fpos_t num`? Isn't it supposed to be a structure? If so, you should read the documentation :) – Amina Apr 16 '15 at 14:36

4 Answers4

8

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.

This variation on your code works for me:

#include <stdio.h>

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);
       }
   }
   fclose(filePtr);
   return 0;
}
John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • @AnasAyubi, I'm glad you found a solution. However, if indeed *the code I posted* does not correctly do *the job you described* for you, then you have a serious problem in your C implementation. – John Bollinger Apr 18 '15 at 15:38
2

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.

Community
  • 1
  • 1
utarid
  • 1,642
  • 4
  • 24
  • 38
1

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;
}
Anas Ayubi
  • 227
  • 1
  • 3
  • 9
0

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

Amina
  • 404
  • 4
  • 14