Thread: Help! Inserting a character into file

  1. #1
    Registered User
    Join Date
    Aug 2003
    Posts
    34

    Help! Inserting a character into file

    Could you guys look at the following code?

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main() {
    
    	FILE *f;
    	char c=0, temp[512]={0};
    	int br=0;
    
    	if ((f=fopen("fajl.htm", "r+"))==NULL) {;
    		exit(1);
    	}
    
    
    	while ((c=fgetc(f))!=EOF) {
    		
    		if (c=='&') {
    				fseek(f, 0, SEEK_CUR);
    				printf("%d", fputc('q', f));
    
    		}
    	}
    	
    	fclose(f);
    	
    	return 0;
    
    }
    I'm trying to add 'q' after each ampersand (replacing the character that is already there). However, after running this program on a file that has "&AAAAA", I get the following output:

    Code:
    &qAAAAA
    
    様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様
    Any idea what's wrong?

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    You can't edit a file like that. That only works if you're only changing the file, not adding or removing data.

    You have to read the file in, make your changes and write out a new copy of the file.

  3. #3
    Registered User
    Join Date
    Aug 2003
    Posts
    34
    Quote Originally Posted by Salem
    That only works if you're only changing the file
    What do you mean? Could you give an example?

    Also, is this line necessary before fputc:


    Code:
    fseek(f, 0, SEEK_CUR);
    I think I read somewhere that I need to use fseek before fputc.

  4. #4
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Well, since the program doesn't work the way you think it should, and since you can't do what you think you can, I'd have to say the line is unneeded. Because you simply cannot do what you want.
    Code:
    loop
        read a byte
        if not EOF
            write byte to new file
            if byte is an amp
                write a q to the new file
        else
            stop loop
    Quzah.
    Hope is the first step on the road to disappointment.

  5. #5
    Registered User
    Join Date
    Mar 2004
    Posts
    536
    Quote Originally Posted by Ariod
    What do you mean? Could you give an example?

    Also, is this line necessary before fputc:


    Code:
    fseek(f, 0, SEEK_CUR);
    I think I read somewhere that I need to use fseek before fputc.

    From http://msdn.microsoft.com/library/de..._constants.asp
    When the "r+", "w+", or "a+" type is specified, both reading and
    writing are allowed (the file is said to be open for "update").
    However, when you switch between reading and writing, there must
    be an intervening fflush, fsetpos, fseek, or rewind operation. The
    current position can be specified for the fsetpos or fseek
    operation.
    (Some compilers seem to work OK without the intervening positioning command, some--- not so good.)

    For example visual c++ requires some positioning command, like fseek(), after the getc and also after the putc. (This may not be your problem here, but there is good reason to do what is suggested.)

    I'm thinking that your problem is caused by

    Code:
    char c;
    In order to test the value c against EOF, c needs to be an int, not a char.

    Try this, and tell me if it helps (it works for me).


    [edit]
    Note that the file should be opened with mode "rb+" to make sure that fseek() works properly.
    [/edit]
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main() {
    
      FILE *f;
      int c; /* Must be int so that it can hold EOF */
    
      if ((f=fopen("fajl.htm", "rb+")) == NULL) {;
        exit(1);
      }
    
      while ((c = fgetc(f)) != EOF) {
    
        printf("0x%02x\n", c); /* added for debugging purposes */
        
        if (c == '&') {
          fseek(f, 0, SEEK_CUR);
          fputc('q', f);
          fseek(f, 0, SEEK_CUR);
        }
      }
      fclose(f);
      
      return 0;
    }
    Regards,

    Dave
    Last edited by Dave Evans; 11-21-2004 at 01:58 PM.

  6. #6
    Registered User
    Join Date
    Mar 2004
    Posts
    536
    Quote Originally Posted by Salem
    You can't edit a file like that. That only works if you're only changing the file, not adding or removing data.
    But he is replacing a character with another character in its place. That's precisely what mode "r+" allows.

    Regards,

    Dave

  7. #7
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by Dave Evans
    But he is replacing a character with another character in its place. That's precisely what mode "r+" allows.

    Regards,

    Dave
    Ah. I, and probably Salem, was under the impression they were inserting a character. (Probably from the thread title, eh?)

    Quzah.
    Hope is the first step on the road to disappointment.

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Heh, yeah, mis-read

    Try this
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        FILE *f;
        int c = 0;
    
        if ((f = fopen("fajl.htm", "r+")) == NULL) {
            exit(1);
        }
    
        while ((c = fgetc(f)) != EOF) {
            if (c == '&') {
                fputc('q', f);
                fflush(f);
            }
        }
        fclose(f);
    
        return 0;
    }

  9. #9
    Registered User
    Join Date
    Mar 2004
    Posts
    536
    Quote Originally Posted by Salem
    Heh, yeah, mis-read

    Try this

    Works on my Linux box, but none of the three Windows XP compilers give the required result (Borland bcc32, Microsoft VC++, GNU gcc). The only thing that works for all that I have tried is given in my previous post. (That is with fseek() between read and write and fseek() between write and read.)

    Regards,

    Dave

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    What about "rb+" mode ?

  11. #11
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >Try this
    Your code chains an output right after an input without an intervening seek. There would have to be a seek before fputc and either an fflush or a seek after fputc for the code to be correct. Also, since the idea is to replace the '&' character, the first seek needs to go backward by one character to account for the fact that the '&' character has already been read by fgetc. Because this is an arbitrary seek, the stream needs to be opened as binary:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
      FILE *f;
      int c = 0;
    
      if ((f = fopen("file.txt", "r+b")) == NULL) {
        exit(1);
      }
    
      while ((c = fgetc(f)) != EOF) {
        if (c == '&') {
          fseek(f, -1, SEEK_CUR); /* Required between input and output */
          fputc('q', f);
          fflush(f); /* Required between output and input. fseek would work too */
        }
      }
      fclose(f);
    
      return 0;
    }
    Last edited by Prelude; 11-21-2004 at 01:43 PM.
    My best code is written with the delete key.

  12. #12
    Registered User
    Join Date
    Mar 2004
    Posts
    536
    Quote Originally Posted by Salem
    What about "rb+" mode ?
    It still doesn't work on any of my Windows compilers (not even GNU gcc).
    [edit]
    Of course, as hinted at by you and pointed out by Prelude, anything using fseek() should open the file in binary mode. I just forgot, and my simple test case only had one line. Oh, well... the code you posted still didn't work with my Windows compilers.
    [/edit]

    Here's a quote from K&R (2nd ed.), similar to, but not exactly the same as my previous MSDN reference:

    FILE *fopen(const char *filename, const char *mode)

    fopen opens the named file, and returns a stream, or Null if the
    attempt fails.

    Legal values for mode include:
    .
    .
    "r+" open text file for update (i.e. reading and writing)
    "w+" create file for update (i.e. reading and writing)
    .
    .
    Update mode permits reading and writing the same file: fflush or a
    file-positioning function must be called between a read and a write or vice
    versa.
    I have found that the magical, (or, at least mystical) incantation with fseek() before and after writing seems to make things work as advertised.


    Regards,

    Dave
    Last edited by Dave Evans; 11-21-2004 at 01:51 PM.

  13. #13
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >anything using fseek() should open the file in binary mode
    Not anything. Text files do support incredibly restricted seeking from SEEK_SET to either 0 or a value returned by a previous call to ftell. Anything else isn't supported though.
    My best code is written with the delete key.

  14. #14
    Registered User
    Join Date
    Mar 2004
    Posts
    536
    Quote Originally Posted by Prelude
    >anything using fseek() should open the file in binary mode
    Not anything. Text files do support incredibly restricted seeking from SEEK_SET to either 0 or a value returned by a previous call to ftell. Anything else isn't supported though.
    Well, what I should have said (how many times have I said, "what I should have said?") is something like

    "I always try to remember to open files in binary mode if I expect to use fseek(). It's not always absolutely necessary, but it can't hurt."

    Oh, yeah, one more thing: I didn't go back to the previous character with the fseek() because the Original Post said

    I'm trying to add 'q' after each ampersand (replacing the character that is already there)

    Regards,

    Dave

  15. #15
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >I didn't go back to the previous character with the fseek() because the Original Post said
    My mistake, I thought that the original question was to replace the ampersand with something else, not the character after the ampersand.
    My best code is written with the delete key.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Newbie homework help
    By fossage in forum C Programming
    Replies: 3
    Last Post: 04-30-2009, 04:27 PM
  2. opening empty file causes access violation
    By trevordunstan in forum C Programming
    Replies: 10
    Last Post: 10-21-2008, 11:19 PM
  3. gcc link external library
    By spank in forum C Programming
    Replies: 6
    Last Post: 08-08-2007, 03:44 PM
  4. Inventory records
    By jsbeckton in forum C Programming
    Replies: 23
    Last Post: 06-28-2007, 04:14 AM
  5. Possible circular definition with singleton objects
    By techrolla in forum C++ Programming
    Replies: 3
    Last Post: 12-26-2004, 10:46 AM