开发者

Replacing strings in files - C

I'm trying to make a program that replacing strings in files.

I got the program below that replacing all the occurrences of one string in the file, but now I need to extend so it'll replace multiple strings.

The trivial way is to run the program several times, each time w开发者_如何学JAVAith different string as input, but I'm looking for more efficient way to do it.

My input can be:

  1. Set of strings to replace (each string appears once).
  2. List of strings to replace by order of appearance (string can be at the list several times) but without knowing their offset.

Thanks for the help.

#include <stdio.h>
#include <string.h>
#define LINE_LEN     128

int main(){
char fileOrig[32] = "orig.txt";
char fileRepl[32] = "new.txt";
char text2find[80];
char text2repl[80];
printf("enter text to replace in the file:");
scanf ("%s",text2find);
sprintf(text2repl,"%s%s%s","<b><font color=\"#FF0000\">",text2find,"</font></b>");
char buffer[LINE_LEN+2];
char *buff_ptr, *find_ptr;
FILE *fp1, *fp2;
int buff_int;
size_t find_len = strlen(text2find);

fp1 = fopen(fileOrig,"r");
fp2 = fopen(fileRepl,"w");
buff_int=(int)buffer;
while(fgets(buffer,LINE_LEN+2,fp1)){
    buff_ptr = buffer;
    while ((find_ptr = strstr(buff_ptr,text2find))){
        while(buff_ptr < find_ptr)
            fputc((int)*buff_ptr++,fp2);
        fputs(text2repl,fp2);
        buff_ptr += find_len;
    }
    fputs(buff_ptr,fp2);
}
fclose(fp2);
fclose(fp1);
return 0;
}


Sometimes things can get complicated. Say if you have strings to replace as {ab,ba} and they would be replaced to {xy,yx} respectively. Say you have the input file to contain "aba". Now the output becomes order dependant.

Similar confusion can occur if the replacement of one string causes another string to be formed which belongs to the strings-to-replace list.

IMO, you should define what you want to do in this situations and then use an approach similar to what you have already done.

BTW, you can better your string matching by using an finite automata based approach or use some existing state of the art algorithm like KMP or Boyer-Moore. This will let you search multiple strings at once.


I'm not sure if what you want is possible, but you might want to look into string search algorithms to make the search part of your algorithm more optimized. A naive search algorithm has, according to Wikipedia, complexity Θ((n-m+1) m), with n the length of your text and m the length of your search string. Take a look at the link, you can do significantly better.

Once you have all the offsets of the strings to replace, the actual replacing seems to be fairly straightforward.

I'm sorry I can't completely answer your question, but I thought this might give you some optimization ideas.


I think this will help you. Please use following Code to Search & Replace string .

Call this function from Top lavel function like this:

replaceIPAddress( "System.cfg", "172.16.116.157", "127.0.0.1");


void replaceIPAddress( char * confFileName, char *text_to_find , char *text_to_replace ) {

FILE *input = fopen(confFileName, "r");

FILE *output = fopen("temp.txt", "w");

char buffer[512];


while (fgets(buffer, sizeof(buffer), input) != NULL)
{
    char *pos = strstr(buffer, text_to_find);
    if (pos != NULL)
    {
        /* Allocate memory for temporary buffer */
        char *temp = calloc(
                strlen(buffer) - strlen(text_to_find) + strlen(text_to_replace) + 1, 1);

        /* Copy the text before the text to replace */
        memcpy(temp, buffer, pos - buffer);

        /* Copy in the replacement text */
        memcpy(temp + (pos - buffer), text_to_replace, strlen(text_to_replace));

        /* Copy the remaining text from after the replace text */
        memcpy(temp + (pos - buffer) + strlen(text_to_replace),
                pos + strlen(text_to_find),
                1 + strlen(buffer) - ((pos - buffer) + strlen(text_to_find)));

        fputs(temp, output);

        free(temp);
    }
    else
        fputs(buffer, output);
}

fclose(output);
fclose(input);

/* Rename the temporary file to the original file */
rename("temp.txt", confFileName);

}


//
// Find and replace data in a file
//
// This is not as straightforward a problem as it initially appears,
// because if you have the text
//
// "Jack is a pirate"
//
// And you wish to replace "is" with "was", the string needs to be longer,
// or else you end up with the following:
//
// "Jack wasapirate"
//
// This becomes more of a problem for larger text.  For example, if we wanted
// to replace "Jack" with "Rumpelstiltskin", we'd end up with:
//
// "Rumpelstiltskin"
//
// Which completely overwrites our original text!!!
//
// In order to do this correctly, we wither need to:
// 
// 1. Read the entire file into a in-memory buffer
// 2. Write to a temporary file, then replace the original file
//
// Option #2 is easier to implement, and should work for your coursework.
// 


#include <stdio.h>


int main(int argc, char** argv)
{
    // We need a buffer to read in data
    const int BufferSize = 0x1000;
    char      Buffer[BufferSize];
    char     *InputFileName     = "input.txt";
    char     *TemporaryFileName = "temp.txt";


    // Open the file for reading.  'rt' means that it must already exist, for reading.
    FILE     *Input = fopen(InputFileName, "rt");

    // Our output file.  'w+' means to create the file if it doesnt exist, for writing.
    FILE     *Output = fopen(TemporaryFileName, "w+");

    // Our find and replace arguments
    char     *Find = "is";
    char     *Replace = "was";

    if(NULL == Input)
    {
        printf("Could not open file");
        return 1;
    }

    printf("Find:    %s\n", Find);
    printf("Replace: %s\n", Replace);

    // For each line...
    while(NULL != fgets(Buffer, BufferSize, Input))
    {
        // For each incidence of "is"
        char *Stop = NULL;    // Where to stop copying (at 'is')
        char *Start = Buffer; // Start at the beginning of the line, and after each match

        printf("Line: %s\n", Buffer);

        while(1)
        {
            // Find next match
            Stop = strstr(Start, Find);

            if(NULL == Stop)
            {
                // Print the remaining text in the line
                fwrite(Start, 1, strlen(Start), Output);
                break;
            }

            // Write out everything between the end of the previous match, and the 
            // beginning of the current match.
            //
            // For example:
            //
            // "Jack is a pirate who is cool"
            //
            // Has two instances to replace.  In order, we'd find them as such:
            //
            // "Jack is a pirate who is cool"
            //       ^
            //                        ^
            // What we want to do is write:
            // - "Jack "
            // - "was"
            // - "a pirate who "
            // - "was"
            // - "cool"
            printf("Match starts at: %s\n", Stop);

            // We have found a match!  Copy everything from [Start, Stop)
            fwrite(Start, 1, Stop - Start, Output);

            // Write our replacement text
            fwrite(Replace, 1, strlen(Replace), Output);

            // Next time, we want to start searching after our 'match'        
            Start = Stop + strlen(Find);

            printf("Search resumes at: %s\n", Start);
        };
    }

    // Close our files
    fclose(Input);
    fclose(Output);

    // If desired, rename the Output file to the Input file
    rename(TemporaryFileName, InputFileName);

    return 0;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜