0

So I have a project I am doing and I have created a program that allows the user to write to a file, as shown below:

 #include <stdio.h>
 #include <stdlib.h>

 FILE *fd;
 FILE *fw;

     struct store
     {
          char Word[512];
          char NWord[512];
     }
     stock;

     struct store2
     {
          char Definition[512];
     }
     stock2;

char done='y';
int count=1;
int c=0;
int d=0;

int main(void)
{
    fw=fopen("Test Z W.txt","w");
    fd=fopen("Test Z D.txt","w");

    do
    {    
         printf("Word %d: ",count);
         gets(stock.Word);
         while((c= getchar()) != '\n' && c != EOF);

         printf("Definition %d: ",count);
         gets(stock2.Definition);
         while((c= getchar()) != '\n' && c != EOF);  

         fprintf(fw,"%s\n", stock.Word);         
         fprintf(fd,"%s\n", stock2.Definition);        
         count=count+1;  
         system("cls");                
    }
    while (count<11);

fclose(fd);
fclose(fw);

return 0;

}

this code is fine, however, I would like to expand it so that there is an option to edit just one chosen line, rather than wiping the entire file and writing all of the contents again.

All I have to work on is using How do you write to a specific line of a txt file in C?

Which wasn't very helpful since I couldn't take an answer and import it to my code, either way all I need is something where an error such as the one below, can be fixed easily.

 1
 2
 Three
 4
 5
 6
 7
 8
 9
 10

Where the user will automatically be asked which line they want to edit.

Community
  • 1
  • 1
  • 2
    Files are not lists of strings, they are lists of characters. You cannot easily "replace" a single string with a shorter or longer one. If you do not want to rewrite the entire file, you need a fail-safe system to read/re-write everything after your modification. Which is much harder (and error prone) than simply **rewrite** the entire file. – Jongware Apr 06 '14 at 15:06
  • The previous answer was unhelpful because what you want to do is basically as impossible today as it was then. – Duck Apr 06 '14 at 15:09
  • The problem is that I can't request a word and have that changed, it has to be a line. –  Apr 06 '14 at 15:12
  • Well then, why is the *obvious* answer (rewrite the file) also a problem? – Jongware Apr 06 '14 at 15:14
  • ???, I can re-write the file, I just want to re-write one line, unless of course I scan the lines of the file, and paste them back until I get to the specific line, where I just input the new word and then paste the rest after? –  Apr 06 '14 at 15:16
  • If you just want to change one line in the text file why don't you use fseek()? – MrSykkox Apr 06 '14 at 15:19
  • 4
    Yes, that *is* pretty much what you have to do. There is no magic in the filesystem that allows you to say "i want to stuff this line in the middle, would you mind expanding the file and shoving everything after it down for me?" You have to do that yourself. @MrSykkox, even after he seeks, if the new line is not the same length as what he is replacing he will be overwriting the old or leaving some strange gap. – Duck Apr 06 '14 at 15:21
  • Here's an example of deleting a line in a text file : http://www.sanfoundry.com/c-program-delete-line-text-file/ – MrSykkox Apr 06 '14 at 15:28
  • @MrSkykox How is fseek() used?, is it just a function like getch();? or is there some code?, also DUCK I could always find a function that deletes all spaces in a file, even though I don't mind the spaces for the definition part. –  Apr 06 '14 at 15:37
  • @user3503792, you can explore all kinds of dead ends and add as much complexity to a common problem every developer since the beginning of time has faced. This is where you will end up. – Duck Apr 06 '14 at 15:56
  • @user3503792 as Duck pointed out fseek will not work because you may overwrite other file data. You might look at a solution where you store all the file data in the memory and do your editing there. Since your file size isn't bigger it's the best solution. – MrSykkox Apr 06 '14 at 16:19

1 Answers1

0
#include <stdio.h>
int main()
{
    FILE *fp,*fc;
    int lineNum;  //stores line number which should be edited.
    int count=0;  //count number lines in source file.
    int ch;   //temporary place to store character of source file(one at a time).
    int edited=0;  //0=false and 1=true
    int t;   //temporary place to store input which you want to be replaced with error in text file.


    fp=fopen("source.txt","r");
    fc=fopen("target.txt","w");

    if(fp==NULL||fc==NULL)
    {
        printf("\nError...cannot open/create files");
        return 1;
    }

    printf("\nEnter Line Number Which You Want 2 edit: ");
    scanf("%d",&lineNum);

    while((ch=fgetc(fp))!=EOF)
    {
        if(ch=='\n')  //counts number of lines
            count++;
        if(count==lineNum-1 && edited==0)  //if specific line(error line) is found and that line is still not edited. More Explanation:- If we want to edit 3rd line than we should start writing at the end of 2nd line(hence count==lineNum-1) and edited==0 means that error line is still not edited. 
        {
            printf("\nEnter input to store at line %d:",lineNum);

            scanf(" %c",&t);  //You can replace this statement with any input operation which you want to replace it with the error line.

            if(count==0)  //if its the first line to edit..
                fprintf(fc,"%s\n",t)   //watch closely,no '\n' before %s,This will copy without creating a extra newline in beginning of new file.
            else 
                fprintf(fc,"\n%s\n",t);  //stores input at error line in file fc(target.txt) from variable t.

            edited=1;  //this prevents loop to execute more than once(as error is already edited),so there will be no need to execute this loop till the end of program

            while( (ch=fgetc(fp))!=EOF )  //Actually this loop will skips the existing line in source.txt(see below)
            {                           //we want to skip this line because this is error line.
                if(ch=='\n')//this will break when next new line(after error line is skipped) is found.
                    break;
            }
       }
       else
          fprintf(fc,"%c",ch);
    }
    fclose(fp);
    fclose(fc);

    if(edited==1)
        printf("\nCongrates...Error Edited Successfully.");
    else
        printf("\nLine Not Found");

return 0;
}

This program will open a source file (which may have error,i called it source.txt*) and keeps reading it character by character and write to new file (target.txt) untill (EOF) is found.But it will stop at the specific line and will ask user to input some data which will be written in place of error(error line from source file) in new text file( target.txt).

so at the end you will get target.txt file free from errors. Open and check it.

In this program i have assumed that we want to replace only single character at line 3.but you can change this operation to replace it with string,float or integers etc.

Here is the output:-

Enter Line Number Which You Want 2 edit: 3

Enter input to store at line 3: 3

Congrates...Errors Edited Successfully.

contents of target.txt:-

1

2

3

4

5

6

7

Mysterious Jack
  • 621
  • 6
  • 18
  • Thanks, I am guessing i have to use another function to copy the contents of target back to source? –  Apr 07 '14 at 08:52
  • I Already told you,you can replace those lines with any input operation you want.If you want to change 3 to "three" you have to add `scanf(" %s[^\n]",t);`(here t should be a string array),and you should also add this `fprintf(fc,"\n%s\n",t);` – Mysterious Jack Apr 07 '14 at 08:57
  • No Don't copy back to source, After everything is done, just delete orginal file(srouce.txt) and rename target.txt to source.txt....:) – Mysterious Jack Apr 07 '14 at 09:01
  • I think i will go in detail, After running the above program you will already have a error free copy of source.txt(target.txt). So why would you copy all the contents of target.txt to source.txt.what you can do is Delete the source.txt file and rename target.txt to source.txt. Thats it, now you will have a single file(error free) called source.txt. – Mysterious Jack Apr 07 '14 at 09:16
  • I fixed the character input, Realised that i had to change an int to a char. Anyway I should be more specific: I need to be able to use this in a loop, So pasting the new version back onto the old version makes this work no problem. I'm just using the "Target file" as a temporary subsitute. –  Apr 07 '14 at 10:25
  • Renaming is also impossible, there is going to be 2 files of the same name in the documents which the computer will have a fit over, even if i rename both files back and forth. –  Apr 07 '14 at 10:27
  • No atcually you can rename it. This code `fc=fopen("target.txt","w");` will always create a new file named target.txt. To delete source.txt all you have to add is this code at the end of loop `remove("source.txt")` and (to rename target.txt) you have to add `rename("target.txt","source.txt");` .So the program will automatically do it.There will be no same filenames at any point during the execution in document – Mysterious Jack Apr 07 '14 at 10:36
  • On the second comment from the top, where does this go exactly? –  Apr 08 '14 at 08:41
  • hahahaaa..you should really learn a lot first dude. Don't just copy paste code man, make effort to understand it too. Anyways it goes in the `while` block, in that 2nd `if` block from there lines 2 and 3 where i commented ` //You can replace this statement.... ` and ` //stores input at error line... ` – Mysterious Jack Apr 08 '14 at 10:12
  • Sigh, Half the stuff you're telling be isn't worth commenting –  Apr 08 '14 at 19:58
  • really??. i was trying to be funny..:) .sorry,Am here to help you, don't worry, comment again if you need help with the program – Mysterious Jack Apr 09 '14 at 05:59