Thread: Need help with altering info on a txt file

  1. #1
    Registered User
    Join Date
    Dec 2007
    Posts
    9

    Wink Need help with altering info on a txt file

    Here is the code I am writing not very good I know but I am a noob programer.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #define LINE_TO_ALTER 200
    int main(int argc, char *argv[])
    {
        int i=0,Id;
        FILE *testfile;
        int j=0;
        char alter[LINE_TO_ALTER];
        char nome[200];
        char numero[100];
    
                testfile=fopen("contactos.txt","r+");
     printf("Enter the number of the line you want to alter");
     scanf("%d",&Id);
     while (i<=Id)
      {
            printf("%d",i);
            fscanf(testfile,"%s",&alter);
          
            i++;
            }
            
    
            fseek(testfile,0L,SEEK_CUR);  
            printf("Alter line");
            scanf("%s",&nome);
            scanf("%s",&numero);
            fprintf(testfile,"\n#%s#%s# \n",&nome,&numero);
            
        
            
            fclose(testfile);
      system("PAUSE");	
      return 0;
    }
    Now using r+ overwrites the text in a file and thus what I am trying to accomplish with this program is overwrite the line of text that I wish to alter and then so that the rest of the txt file is not changed I wanted to also overwrite everything from the line that is being altered with the exact same information that is already in the file from the line that has been altered until the end (hope someone can help me.... and if possible bye using my idea). lol sorry for the redundancy, but I can't seem to find another way to explain. If anyone has doubts in my explanation just ask and I will try to explain again.


    Thanks in advance......

    Bye the way "nome" is name in portugues
    and "numero" is number

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    This:
    Code:
            fseek(testfile,0L,SEEK_CUR);
    does EXACTLY NOTHING - it tells the C run time to move forward 0 steps.

    Also, writing new data to a text file "in situ" does depend on the new text being exactly as long as the old text, otherwise you'll either overwrite the content after (when it's longer), or leave something "behind" (when it's shorter).

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Bad indentation warning!
    Each block should be indented ONCE. Indentation should be abused all around the code.

    Code:
    int main(int argc, char *argv[])
    {
    	int i=0,Id;
    	FILE *testfile;
    	int j=0;
    	char alter[LINE_TO_ALTER];
    	char nome[200];
    	char numero[100];
    
    	testfile=fopen("contactos.txt","r+");
    	printf("Enter the number of the line you want to alter");
    	scanf("%d",&Id);
    	while (i<=Id)
    	{
    		printf("%d",i);
    		fscanf(testfile,"%s",&alter);
    		i++;
            }
            
    	fseek(testfile,0L,SEEK_CUR);  
    	printf("Alter line");
    	scanf("%s",&nome);
    	scanf("%s",&numero);
    	fprintf(testfile,"\n#%s#%s# \n",&nome,&numero);
    
    	fclose(testfile);
    	system("PAUSE");	
    	return 0;
    }
    Properly indented.
    scanf/fscanf("%s", ...) is unsafe! Read my signature.
    If you want to replace a line in a text file, you need to write a string that is of equal length. A new line is just a character ('\n'); there's no magic that keeps lines apart, so you need to write out the exact amount of character the old line is to keep the rest of the contents intact.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #4
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Code:
    fscanf(testfile,"&#37;s",&alter);
    Drop the &. (When reading strings with *scanf(), you don't use &var -- with integers, numbers, characters, and everything else, you do.)

    Code:
    fprintf(testfile,"\n#%s#%s# \n",&nome,&numero);
    Ditto. You never use & with *printf().

    You also need to call
    Code:
    fflush(testfile);
    before you can switch between reading and writing. (Or fseek(), or rewind().)
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  5. #5
    Registered User
    Join Date
    Dec 2007
    Posts
    9
    Thanks a billion guys for the tips keep em coming..... as noobs like me need the info ;-)

    about the overwiting I have figuerd out what you guys are saying in relation to "must be the same amount of caracters".

    What I trying to write is code that alteres a spasific line in my txt file, a line that I choose to alter (and this line can be bigger than the one that was there before or smaller) and all the rest is untouched.... anyone can help me with this?
    Last edited by Netflyer; 12-18-2007 at 04:24 PM.

  6. #6
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Chappell Hill, Texas
    Posts
    2,332
    If you want to change the length of one line of text, and the leave the rest of the file the same, realize that you can't do that. You CAN leave the first portion of the file AS IS, IN PLACE, and then you can write the new length record, but then you'll have to write the remainder of the file also.

    Todd

  7. #7
    Registered User
    Join Date
    Dec 2007
    Posts
    9
    Thanks tod.... for the info.... I think that is what I am trying to do with my program actually but I am not managing to get it write :-( can anyone run my program and check what it does to get a better notion please..... sorry guys for the nag

  8. #8
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    A few things you'll probably want to do.
    • Use fgets() instead of fscanf() as Elysia hinted at, in case a line in the file contains a space.
    • Write to a separate file, unless you know the new line is the same length as the old line.
    • If you write the previous lines, the new line, and then the next lines to an output file, you can remove() the original file and then rename() the intermediate file to the old file name.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    --- Dangers of scanf and fscanf ---


    I'm going to elaborate a little here.
    scanf and fscanf are dangerous functions if misused, which many do. The thing is that these functions do not take an argument specifying the buffer size, so you must explicitly do so in the arguments you pass indicating what type of input you're expecting.
    This information applies when reading strings, only!
    The correct way to call scanf/fscanf is
    Code:
    scanf("%BufferSizeHere - 1s", ...);
    Doing that will pass along the size of your buffers to the function (or rather tell it how many chars to read maximum), so you won't get buffer overruns.
    And now, to my favorite topic - Buffer overruns!

    --- Buffer Overruns ---


    Why is this bad?
    Consider that you have an array of 5 characters in size. The user enter 10 characters! That means 10 characters + 1 (for the ending '\0') is written to your array. But your array is only 5 chars long! Uh-oh!
    What can happen? Well, the result is undefined. Basically that means the result is not defined. Defined as in that we know the behavior. In undefined, we cannot guarantee what will happen.
    First and foremost - it's a security risk. Lots of malware and other security threats take advantage of buffer overruns to run malicious code. Not very good, is it!?
    Second is that your app may crash because you're writing to an area in memory which you do not own. OSes locks down areas in Virtual Memory where application may write and not. Usually (but not always) you get a crash when writing to memory you haven't allocated. This is sort of an advanced topic, so let's leave it at that.
    Third is that the space beyond your array may actually be allocated for some other variable! What happens is that your call to scanf/fscanf will overwrite data in some of your other variables! This will at least cause garbage data or weird results in your applications, or in worst case, a crash.

    But you can simply avoid this by specifying the maximum characters to read. Sure, it may not get you the result you want, but it's better than undefined behavior.
    Think about that.

    MSDN has an article on scanf and how you specify the size: http://msdn2.microsoft.com/en-us/lib...x1(VS.80).aspx
    Remember that scanf also stops reading at the first blank space ( ), so if you type something like "Hello World" - it will only read "Hello". Both of these problems can be fixed using fgets.
    But you can also just use fgets, which takes an argument for buffer size. Here's documentation for fgets on MSDN: http://msdn2.microsoft.com/en-us/lib...kf(VS.71).aspx
    Remember that fgets reads an entire line and also stores the '\n' (the newline) in your buffer.

    --- Examples ---


    How to call scanf correctly with a buffer when reading a string:
    Code:
    char buffer[10];
    scanf("%9s", buffer);
    Note that the size passed to scanf must be size of buffer - 1, so since the size of the buffer is 10, 9 should be passed to scanf.

    How to call scanf correctly with a buffer when reading a string and read spaces too:
    Code:
    char buffer[10];
    scanf("%9[^\n]", buffer);
    Complicated? Try fgets!

    fgets sample to read a line into a buffer:
    Code:
    char buffer[10];
    fgets(buffer, 10, stdin);
    What's stdin, you ask? While not getting too complicated, it is a stream that points (by default) to the keyboard.
    scanf reads from stdin, as well. And note that with fgets, you should specify the entire size of your buffer, so if it's 10, pass 10!
    Last edited by Elysia; 12-18-2007 at 06:56 PM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Quote Originally Posted by Elysia View Post
    I'm going to elaborate a little here.
    So am I.
    scanf and fscanf are dangerous functions if misused, which many do. The thing is that these functions do not take an argument specifying the buffer size, so you must explicitly do so in the arguments you pass indicating what type of input you're expecting.
    This only applies to reading strings, of course. Numbers and characters and stuff are just fine.
    The correct way to call scanf/fscanf is
    Code:
    scanf("%BufferSizeHere - 1%", ...);
    Doing that will pass along the size of your buffers to the function (or rather tell it how many chars to read maximum), so you won't get buffer overruns.
    No, but you'll still get the space problem. See below.
    And now, to my favorite topic - Buffer overruns!

    Why is this bad?
    Consider that you have an array of 5 characters in size. The user enter 10 characters! That means 10 characters + 1 ...
    +1 for the NULL, of course.
    ... is written to your array. But your array is only 5 chars long! Uh-oh!
    What can happen? Well, the result is undefined. Basically that means the result is not defined. Defined as in that we know the behavior. In undefined, we cannot guarantee what will happen.
    First and foremost - it's a security risk. Lots of malware and other security threats take advantage of buffer overruns to run malicious code. Not very good, is it!?
    Second is that your app may crash because you're writing to an area in memory which you do not own. OSes locks down areas in Virtual Memory where application may write and not.
    Not only in virtual memory -- in any memory.
    Usually (but not always) you get a crash when writing to memory you haven't allocated. This is sort of an advanced topic, so let's leave it at that.
    Use Linux, get Valgrind!
    Third is that the space beyond your array may actually be allocated for some other variable! What happens is that your call to scanf/fscanf will overwrite data in some of your other variables! This will at least cause garbage data or weird results in your applications, or in worst case, a crash.

    But you can simply avoid this by specifying the maximum characters to read. Sure, it may not get you the result you want, but it's better than undefined behavior.
    Think about that.
    The space problem: *scanf()'s %s, when it sees "Joe Smith", only reads "Joe". In other words, it stops at the first whitespace it sees, be this a newline or a tab or an ordinary space. In line-based applications, this is a problem. One way to solve this is to use fgets(). You can also do it with *scanf() by passing some funky format specifier -- I think it's %[^\n].
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Updated post! More suggestions, please!
    It's important to put as much data as possible into one reply if I'm going to link it through my signature
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    scanf("&#37;BufferSizeHere - 1%", ...);
    What's that extra % for?

    I'd provide an example, e.g.
    Code:
    char buffer[10];
    scanf("%9s", buffer);
    And an example that lets you enter spaces as well:
    Code:
    char buffer[10];
    scanf("%9[^\n]", buffer);
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by dwks View Post
    What's that extra % for?
    Bug! Should be s, of course.

    I'd provide an example, e.g.
    Code:
    char buffer[10];
    scanf("%9s", buffer);
    And an example that lets you enter spaces as well:
    Code:
    char buffer[10];
    scanf("%9[^\n]", buffer);
    Examples and headers added.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #14
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Also mention sizeof().
    Code:
    char buffer[10];
    fgets(buffer, sizeof(buffer), stdin);
    or (works on variables only, not on types like int)
    Code:
    char buffer[10];
    fgets(buffer, sizeof buffer, stdin);
    and
    Code:
    char buffer[10];
    scanf("&#37;*[^\n]", sizeof(buffer)-1, buffer);
    Just a thought.

    You should also mention something about the various methods of stripping newlines from strings. Here are some examples to get you started.
    Code:
    #include <string.h>
    char buffer[] = "Hello, World!\n", *p;
    size_t len;
    
    if((p = strchr(buffer, '\n'))) *p = 0;
    if((p = strrchr(buffer, '\n'))) *p = 0;
    buffer[strcspn(buffer, "\n")] = 0;
    
    len = strlen(buffer);
    if(len && buffer[len-1] == '\n') buffer[len-1] = 0;
    
    while(*s && s != '\n') s ++;
    *s = 0;
    Might want to mention how 0 and '\0' are the same, and how NULL is different. Something about the difference between char *buffer and char buffer[] wouldn't be amiss, as well using sizeof() on pointers like arrays passed to functions.

    Just some thoughts. I might write up a post like that, too. It might be useful for sure.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    If only I could edit, of course. The edit time expired
    Also, perhaps you can elaborate on the use of * in scanf, but I don't know scanf very well and the doc says little about it other than it suppresses an argument.
    (And the following does obviously not work:
    Code:
    scanf("&#37;*s", sizeof(buffer) - 1, buffer);
    )
    Last edited by Elysia; 12-20-2007 at 12:16 PM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Formatting the contents of a text file
    By dagorsul in forum C++ Programming
    Replies: 2
    Last Post: 04-29-2008, 12:36 PM
  2. Basic text file encoder
    By Abda92 in forum C Programming
    Replies: 15
    Last Post: 05-22-2007, 01:19 PM
  3. Game Pointer Trouble?
    By Drahcir in forum C Programming
    Replies: 8
    Last Post: 02-04-2006, 02:53 AM
  4. Replies: 3
    Last Post: 03-04-2005, 02:46 PM
  5. System
    By drdroid in forum C++ Programming
    Replies: 3
    Last Post: 06-28-2002, 10:12 PM