Thread: Change character in file?

  1. #1
    1ST » R. vd Kooij
    Join Date
    Mar 2006
    Location
    Netherlands
    Posts
    154

    Change character in file?

    Hi, been searching but can't find anything... no idea what search parameters to use, so excuse me if this has already been discussed somewhere!

    I've got the following problem: I have a file that contains the following (example) data:

    Manufacturer;Model;2007;Signal_Name;640;2;0;Tester ;0
    Another_Manufacturer;Some_Model;2007;Signal2_Name; 756;4;0;Some_Tester;0
    etc.
    As you can see it's a ;-seperated file that contains signal information. Every new line in the file represents a new signal.
    The final '0' on the line indicates the signal isn't processed yet (i.e. added to our signal database).

    Now, what I need to do is, when the signal has been processed, replace that '0' with a '1'. I think this should be doable with pointers, but apparently I have too little knowledge about pointers to make this work.

    Here's an example of what I thought is a solution - please note I know this example is 90% bollocks, it's a "road plan" rather than a code example:

    Code:
       
       FILE *fpin;
       int signals_cnt=0;
    
        if((fpin = fopen(signal_file,"r+"))!=NULL)
        {
           while(fpin!=EOF)
           {
              fpin++;
              puts(fpin);
              if(fpin=='\n')
              {
                 signals_cnt++;
                 if(signals_cnt==processed_signal_number)
                 {
                     fpin--;
                     fpin='1';
                 }
    
              }
    
           } //  while(fpin!=EOF)
    
        }
    So the idea is to check for a new line character to count the signal number, and when the desired signal number was found, change the 0 into 1.
    Apparantly fpin (declared as a FILE type) doesn't like being played with (the fpin++ results in blabla on-screen).

    Hope it's clear :S Any help would be greatly appreciated!

    Thanks in advance, René
    Last edited by rkooij; 05-09-2007 at 08:29 AM.
    http://www.f1rstracing.nl/
    OS: Windows XP
    Compiler: Dev-C++

  2. #2
    1ST » R. vd Kooij
    Join Date
    Mar 2006
    Location
    Netherlands
    Posts
    154
    Just to add, I have a solution for this, which involves:
    - copy the file to a temp file
    - add every line from the temp file into the original file until the line with the desired signal is reached (using fgets(buf, BUFSIZ, fpin) and fprintf(fpout,buf) )
    - replace the final 0 by using p = strrchr(buf,";") and *p=1
    - add the altered line to the original file
    - add the rest of the temp file to the original file
    although it works, it seems a bit too far fetched to me...

    And if I could somehow get the idea from the first post working, I'm sure I could use that more often in the future!

    So any help would still be more than welcome!

    Thanks!
    Last edited by rkooij; 05-09-2007 at 08:45 AM.
    http://www.f1rstracing.nl/
    OS: Windows XP
    Compiler: Dev-C++

  3. #3
    1ST » R. vd Kooij
    Join Date
    Mar 2006
    Location
    Netherlands
    Posts
    154
    I'll just keep on trying until someone stops me

    This doesn't work either:

    Code:
        if((fpin = fopen(signals,"r+"))!=NULL)
        {
           while((ih=fgetc(fpin))!=EOF)
           {
              putch(ih);
              if(ih=='\n')
              {
                 if(signals_cnt==counter)
                 {
                    fpin--;
                    fpin=1;
                 }
                 signals_cnt++;
              }
           }
       }
    Application hangs on the line fpin=1; EDIT: hmmmm it doesn't actually... it runs until it reaches the end of the file, then hangs?! The 0 doesnt seem to change to 1 though
    How can I make this work?
    Last edited by rkooij; 05-09-2007 at 09:09 AM.
    http://www.f1rstracing.nl/
    OS: Windows XP
    Compiler: Dev-C++

  4. #4
    .
    Join Date
    Nov 2003
    Posts
    307
    Your long solution is one that will work. I don't know what OS you're using, but essentially
    that is what you would do in UNIX. Can you not save all of this until some point late in the day, and change maybe 40 of them with one pass? Instead of one line per pass?

    Since you can copy the file, mess with the copy, and copy it back it suggests that it is not a file that is held open by a logger. You could consider memory-mapping the file, updating it, then closing it. This bypasses the copy to temp and copy back from temp steps.

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    You can do it, but using a temp file is much more preferable.

    This probably makes some unwarranted assumptions.
    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main ( ) {
        long    pos, oldpos = 0;
        char    buff[BUFSIZ];
        FILE    *fp = fopen("foo.txt", "r+" );
    
        while ( fgets( buff, sizeof buff, fp ) != NULL ) {
            char *p = strrchr( buff, ';' );
            int   offset = p - buff + 1;    /* the 0 or 1 */
            pos = ftell(fp);                /* the start of the next line */
    
            /* From the start of the current line, to the last ';' + 1 */
            fseek( fp, oldpos + offset, SEEK_SET );
            fputc( '1', fp );
            fflush( fp );
    
            fseek( fp, pos, SEEK_SET );
            oldpos = pos;
        }
        fclose( fp );
        return 0;
    }
    
    
    $ gcc -W -Wall -ansi -pedantic -O2 foo.c
    $
    $ cat foo.txt && ./a.exe && cat foo.txt
    Manufacturer;Model;2007;Signal_Name;640;2;0;Tester ;0
    Another_Manufacturer;Some_Model;2007;Signal2_Name; 756;4;0;Some_Tester;0
    Manufacturer;Model;2007;Signal_Name;640;2;0;Tester ;1
    Another_Manufacturer;Some_Model;2007;Signal2_Name; 756;4;0;Some_Tester;1
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    1ST » R. vd Kooij
    Join Date
    Mar 2006
    Location
    Netherlands
    Posts
    154
    Wow, didn't expect my temp-file-solution would be the one to go for... Thanks for the help guys!
    And Salem, thanks very much for your example; learned another couple of new terms, functions and strategies from that... interesting, interesting... Much appreciated!

    René
    http://www.f1rstracing.nl/
    OS: Windows XP
    Compiler: Dev-C++

  7. #7
    1ST » R. vd Kooij
    Join Date
    Mar 2006
    Location
    Netherlands
    Posts
    154
    EDIT3 Arghhh...! sometimes I can make it much more difficult than it actually is....!! Nevermind the stuff below... strcat ftw.

    Hmm I just came up with another idea that needs a slight change of plans... I'd like to change the 0 into an integer bigger than 1 (representing the number the signal gets in our database).

    What I do is, I get the last entry number from the database and store that into an integer called "lastkey". What I would like the *p to become is the value (lastkey+1).

    Now the problem that occurs is the following:

    Code:
       char *p;
       char buf[BUFSIZ];
    
                 if((p = strrchr(buf,';')) != NULL)
                 {
                    *p++;
                    *p='23'; // 23 is example value
    
                 }
    In the example above, only '3' is written to the signal line;
    Another_Manufacturer;Some_Model;2007;Signal2_Name; 756;4;0;Some_Tester;3
    And when I try:

    Code:
       char *p;
       char buf[BUFSIZ];
       int lastkey=23; // 23 is example value here
    
                 if((p = strrchr(buf,';')) != NULL)
                 {
                    *p++;
                    *p=(lastkey+1);
    
                 }
    It puts a 'T' (or another character, depending on the lastkey value) in the line:
    Another_Manufacturer;Some_Model;2007;Signal2_Name; 756;4;0;Some_Tester;T
    EDIT: 'T' was with lastkey value 83, thus it stored 84... 84 is ASCII value for T, so that part's explained then...

    So basically my question is, what do I do to write multiple characters to the signal line? As *p = doesn't seem to work in that case.

    Thanks again!

    Ren&#233;



    EDIT2:

    Code:
    sprintf(temp,"&#37;d",(lastkey+1));
    for(i=0;strlen(temp);i++)
    {
       *p=temp[i];
       p++;
    }
    Bit cheap maybe? And needs a lot of checks and tricks to avoid it overwriting the next line... surely an easier solution is possible?
    Last edited by rkooij; 05-10-2007 at 07:35 AM.
    http://www.f1rstracing.nl/
    OS: Windows XP
    Compiler: Dev-C++

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    *p++ = '2';
    *p++ = '3';
    One character at a time.

    Be very careful about having enough room in your buffer.
    As written so far, there is only one character, followed by a newline.
    So this little trick will overwrite the newline.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. A development process
    By Noir in forum C Programming
    Replies: 37
    Last Post: 07-10-2011, 10:39 PM
  2. Newbie homework help
    By fossage in forum C Programming
    Replies: 3
    Last Post: 04-30-2009, 04:27 PM
  3. C++ std routines
    By siavoshkc in forum C++ Programming
    Replies: 33
    Last Post: 07-28-2006, 12:13 AM
  4. Unknown Memory Leak in Init() Function
    By CodeHacker in forum Windows Programming
    Replies: 3
    Last Post: 07-09-2004, 09:54 AM
  5. Hmm....help me take a look at this: File Encryptor
    By heljy in forum C Programming
    Replies: 3
    Last Post: 03-23-2002, 10:57 AM