views:

159

answers:

5

The Problem was to find and replace a string in a C File.

I am new to C Files. I have tried the following code but I didnt get any output:

    #include<stdio.h>
    #include<string.h>
    int main()
    {
        FILE *f1,*f2;
        char *src,*dest,*s1,ch,ch1,ch2,ch3;
        int i;
        f1=fopen("input.txt","rw");
        f2=fopen("dummy.txt","rw");
        src="mor";
        dest="even";
        while(ch!=EOF)
        {
         ch=fgetc(f1);
         if(ch==src[0])                      //Finding 1st char of src
         {
         fgets(s1,strlen(src),f1);
         if(strcmp(src+1,s1)==0)         //Finding occurance of "src" in file
         {
          fseek(f1,strlen(src)-1,SEEK_CUR);
          while(ch1!=EOF)             //Copying remaining data into another file
          {
          ch1=fgetc(f1);
          fputc(ch1,f2);
          }
      fseek(f1,-strlen(src),SEEK_CUR);
      for(i=0;i<strlen(dest);i++)  //replacing "src" with "dest"
      {
          ch2=dest[i];
          fputc(ch2,f1);
      }
      fclose(f1);
      f1=fopen("input.txt","a");
      while(ch3!=EOF)      //Appending previosly copied data into 1st file
      {
          ch3=fgetc(f2);
          fputc(ch3,f1);
      }
     }
   }
 }
     fclose(f1);
     fclose(f2);
}

The Contents of input.txt is "morning".

Kindly point the ERROR in the logic and also give an efficient code for the same.

Thanks in Advance.

+1  A: 

You are printing the wrong thing in your output. Print, "ch", not the file pointer.

 while(ch!=EOF) 
 { 
     ch=getc(f1); 
     printf("%c",ch); 
 } 
 while(ch!=EOF) 
 { 
     ch=getc(f2); 
     printf("%c",ch); 
 }

Also, f2 is closed at the end during your output. You'll have to reopen it (just like you do with f1.)

Starkey
@Starsky, I have got ur point sir. I have changed it in the code. I have removed the printing part.Kindly check for any errors in the replacement logic sir. The input.txt file is not getting changed on running and the original contents are retained.... Thanks for ur help Sir...
Shyam
+2  A: 

One simple way to do the replace would be to first read in the whole file into a buffer

e.g.

FILE* fpIn = fopen("file.txt","rb");
fseek(fpIn, 0L, SEEK_END);
size_t s = ftell(fpIn);
fseek(fpIn, 0L, SEEK_SET);
void* buf = malloc(s);
fread(buf,s,1,fpIn);

now while writing the file, check for your string

char src[] = "mor";
char dest[] = "even";
int lenSrc = strlen(src);
int lenDest = strlen(dest);
for (char* ch = buf; ch < buf + s; ++ch)
{
   if ( !memcmp( ch, src, lenSrc ) )
   {
     fwrite( dest, 1,lenDest, fpOut );
     ch += lenSrc;
   }
   else 
   {
     fputc( *ch, fp );
   }
}

disclaimer: haven't compiled this

Anders K.
@Andres K, Thanks a lot sir... I ll try the method u gave sir, I think it ll be more easier than searching and replacing with files!
Shyam
+1  A: 

At first glance, I see that your code to call fgets is wrong. You have not allocated any memory and you are reading a string into an uninitialized pointer. Read into an array or dynamically allocated memory.

Tanuj
@Tanuj, there seems to be no problem wit fgets as u pointed out. It compiles fine and executes correctly.. I am reading it into a string which is previosly declared.....
Shyam
@Shyam Your of `fgets` is incorrect. `s1` is not a string, it is a pointer to an array of characters, and it is uninitalized. You are writing to unallocated memory. This is not a compilation error; it is a far more serious logic error that will lead to undefined behaviour.
meagar
@meager.... s1 is uninitialised and logically it s incorrect.. i know tat. But since I am not getting any errors, I am leaving it as it is. Can U pls check for any errors in the logic that i used in the program. Thnaks
Shyam
@Shyam: That is a logical error. You don't know what the uninitialized pointer is doing. If you're lucky, it will just crash the program when used, rather than causing hard-to-trace problems. At the very least, declare it as something like `char s1[500];`, or whatever size you like.
David Thornley
+3  A: 

Reading files in C is usually a bit messy. The first problem that I see is the way ch is used in the main loop. The first time

while (ch != EOF)

is executed, ch is uninitialized, and if it happens to hold EOF, the main loop will not execute at all. I usually use the following structure for reading from files:

FILE *fInput = fopen("input.txt", "r");
int ch; /* need an int to hold EOF */

for (;;)
{
    ch = fgetc(fInput);
    if (ch == EOF) break;

    ...
}

In addition, you may need to read up on file pointer concept. For example, after reading the remainder of src, you fseek() forward, and skip some more characters before you copy data to f2. Essentially, you read m, read or (with fgets() - and into an unallocated buffer s1 that would go ka-boom on you some time in the near future), skip 2 more characters (now your pointer is at last n of "morning"), copy "ng" into f2, try to write EOF to f2 in this loop (hence the above pattern for reading until EOF), seek two characters back (which may fail once you reach EOF, my C file functions are a bit rusty these days), write "even" to f1 (which should, if I am wrong about seek after EOF, set input file to "mornieven", and not change it if I am correct). In summary, I don't think the code does what you intend it to do.

I would recommend building up your function. Each one of the following can be written as a program that you should test and finish before going to next step:

  1. read the file safely, and print it out
  2. detect the contents of src, and print the rest of input
  3. save the rest of the input to second file instead of printing
  4. replace src with dest in first file, and ignore the rest (since you open input file with 'rw', this will truncate the rest of input). You may need to do an fseek() to clear the EOF status. Also look at ftell() to record a position that you can jump back to using fseek()
  5. finally, copy in everything you have saved to second file after replacing src with dest (no need to close f1 here. But it is better to open f2 as write, close after copy from first file, and reopen as read to perform the copy back to f1).

In addition, when you need a buffer (such as s1), just use a large enough array for now, but look into malloc() and free() functions to perform dynamic memory allocations for situations like these.

Dysaster
@Dysaster, Thanks a lot for ue effort in analyzing the whole thing. I cant thank U enough. I used a fseek after finding the occurance of "src" bcos i didnt know that fgets moves the file pointer. I should have read the concepts better. So if that thing is taken care of, the program does what i intend to do right?I ll also try the method U gave... Thanks again!!!!
Shyam
+1  A: 

Another problem is that you are declaring ch as char. fgetc() returns an int, and for good reason. It is good to be able to return any possible character or EOF, so EOF shouldn't be a character, so ideally fgetc() returns a bigger type than char.

The upshot is that the loop may well never end, since ch can't possibly hold EOF on some standard implementation. Declare it (and ch1 and ch3) as int.

David Thornley