Замена строк в файлах - C - PullRequest
       7

Замена строк в файлах - C

1 голос
/ 22 апреля 2011

Я пытаюсь создать программу, которая заменяет строки в файлах.

Я получил нижеприведенную программу, которая заменяет все вхождения одной строки в файле, но теперь мне нужно расширить, чтобызамените несколько строк.

Тривиальный способ - запустить программу несколько раз, каждый раз с разными строками ввода, но я ищу более эффективный способ сделать это.

Мой вводможет быть:

  1. Набор строк для замены (каждая строка появляется один раз).
  2. Список строк для замены в порядке появления (строка может быть в списке несколько раз), ноне зная их смещения.

Спасибо за помощь.

#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;
}

Ответы [ 4 ]

1 голос
/ 22 апреля 2011

Иногда вещи могут усложниться. Скажем, если у вас есть строки для замены как {ab, ba}, и они будут заменены на {xy, yx} соответственно. Скажем, у вас есть входной файл, который должен содержать «aba». Теперь вывод становится зависимым от заказа.

Аналогичная путаница может возникнуть, если замена одной строки приводит к формированию другой строки, которая принадлежит списку заменяемых строк.

ИМО, вы должны определить, что вы хотите сделать в этих ситуациях, а затем использовать подход, аналогичный тому, что вы уже сделали.

Кстати, вы можете улучшить соответствие строк, используя подход на основе конечных автоматов, или использовать какой-либо существующий современный алгоритм, такой как KMP или Boyer-Moore . Это позволит вам искать несколько строк одновременно.

0 голосов
/ 20 декабря 2013

Я думаю, это поможет вам. Пожалуйста, используйте следующий код для поиска и замены строки.

Вызовите эту функцию из функции Top lavel следующим образом:

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);

}

0 голосов
/ 25 февраля 2013
//
// 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 голосов
/ 22 апреля 2011

Я не уверен, что то, что вы хотите, возможно, но вы, возможно, захотите изучить алгоритмы поиска строк , чтобы сделать поисковую часть вашего алгоритма более оптимизированной.Наивный алгоритм поиска имеет, согласно Википедии, сложность Θ((n-m+1) m), с n длиной вашего текста и m длиной вашей строки поиска.Посмотрите на ссылку, вы можете сделать это значительно лучше.

Как только у вас есть все смещения строк для замены, фактическая замена кажется довольно простой.

ИзвинитеЯ не могу полностью ответить на ваш вопрос, но я подумал, что это может дать вам некоторые идеи по оптимизации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...