Найти и заменить функцию - PullRequest
0 голосов
/ 29 ноября 2011

Я ищу создание функции C, в которой она будет искать файл на основе введенной пользователем записи и сможет заменить то, что было там. Я видел похожие примеры с ++, но не очень хорошо знаю с ++. Любые предложения или примеры кода, которые помогут мне начать работу, будут удивительными. Насколько я понимаю, мне нужно открыть исходный файл для чтения, открыть новый файл для записи, прочитать файл orig по одной строке за раз, записать эту строку в новый файл, а когда закончите, удалить исходный файл и переименовать новый файл с именем исходного файла.

Любые предложения или примеры кода с объяснением были бы наиболее полезными

РЕДАКТИРОВАТЬ После дальнейших исследований я подумал, что если бы я мог найти способ перечитать файл, найти файл, внести изменения, и написать его обратно в файл, это было бы намного проще.

Ответы [ 3 ]

1 голос
/ 29 ноября 2011

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

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

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

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

#define BUFFER_SIZE 512

static void searchAndReplace(char* original_file,char* destination_file,char *searchString,char *replacementString){
    FILE* original = NULL;
    FILE* modified = NULL;
    char origLine[BUFFER_SIZE]; //buffer, assuming the longest line will be BUFFER_SIZE -1 characters, being the null terminator the last one
    size_t searchStringLength = strlen(searchString);//length without terminating NULL.
    memset(origLine,0,BUFFER_SIZE);// filling with nulls just in case
    original = fopen(original_file,"r");
    if(!original){
        printf("Error opening file for reading : %s \n",original_file);
        perror("Cause of Error");
        exit(2);
    }
    modified = fopen(destination_file,"w+");
    if(!modified){
        printf("Error opening file for writing: %s \n",destination_file);
        perror("Cause of Error");
        exit(2);
    }

    while(NULL != (fgets(origLine,BUFFER_SIZE,original) )){
        char* searchStringPos=NULL;
        /*it begins to concatenate at the beginning of the string, next position is strlen(searchString) from the last
          searchString pointer position*/
        char* lastConcatPos = origLine;
        if(feof(original) != 0){
            break;
        }
        while ( (searchStringPos = strstr(lastConcatPos,searchString)) != NULL ){
            /* offset between position where searchStringPos was found and the last position being concantenated */
            char tempBuffer[BUFFER_SIZE];
            size_t sizeToConcatenate = (size_t)(searchStringPos - lastConcatPos);
            /* if searchString was located at the beginning of the line or right after the last occurrence do nothing */
            if(sizeToConcatenate >0){
                strncpy(tempBuffer,lastConcatPos,sizeToConcatenate);
                tempBuffer[sizeToConcatenate]='\0';
                fputs(tempBuffer,modified);
            }
            fputs(replacementString, modified);
            lastConcatPos = searchStringPos + searchStringLength;/* continue search after current occurrence*/
        }
        fputs(lastConcatPos,modified);
    }
    fclose(original);
    fclose(modified);
}

static void askUserForInput(char* data_storage,char* text_message){
    int result = 0;
    do{
        //printf("%s, | %s\n  | result = %i",text_message,data_storage,result);
        printf("%s\n",text_message);
        fflush(stdout);
        result = scanf("%s",data_storage);
    }while(result ==0 );
}

int main(int argc,char* argv[]){
    /* Use: program <original_filename> <modified_filename> <string_to_search> <replacement_string> or
     * program for asking the user for input */

    if(argc == 5){
        searchAndReplace(argv[1],argv[2],argv[3],argv[4]);
    }else if(argc == 1){
        char origin_file[128];
        char destination_file[128];
        char search_string[128];
        char replacement_string[128];
        askUserForInput(origin_file,"Enter origin file please");
        askUserForInput(destination_file,"Enter destination file please");
        askUserForInput(search_string,"Enter search string please");
        askUserForInput(replacement_string,"Enter replacement string please");
        searchAndReplace(origin_file,destination_file,search_string,replacement_string);
    }else{
        printf("Usage:\n %s <original_filename> <modified_filename> <string_to_search> <replacement_string>\n or"
               "%s without parameter for asking for input",argv[0],argv[0]);
        exit(1);
    }
    return 0;
}

Редактировать: Есть еще много возможностей для улучшения, например, проверка на NULL-указателив каждой функции изменение searchAndReplace для возврата int = 0 в случае успеха и других в зависимости от типа ошибки и позволить вызывающей программе управлять остальным поведением программы, таким как повторная попытка вместо выхода из программы и т. д.

Также printf на деталях обработки ошибок следует заменить на fprintf(stderr,"message",..) Это некоторые идеи и концепции, которые вы можете использовать для улучшения и изучения гораздо большего.Надеюсь, вам будет весело

1 голос
/ 29 ноября 2011

Попробуйте что-то вроде этого: -

#include <stdio.h>
#include <string.h>

#define MAX_LEN_SINGLE_LINE     120   // ?

int main()
{
    const char fileOrig[32] = "myOriginalFile.txt";
    const char fileRepl[32] = "myReplacedFile.txt";
    const char text2find[80] = "lookforme";
    const char text2repl[80] = "REPLACE_WITH_THIS";

    char buffer[MAX_LEN_SINGLE_LINE+2];
    char *buff_ptr, *find_ptr;
    FILE *fp1, *fp2;
    size_t find_len = strlen(text2find);

    fp1 = fopen(fileOrig,"r");
    fp2 = fopen(fileRepl,"w");

    while(fgets(buffer,MAX_LEN_SINGLE_LINE+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;
}
0 голосов
/ 30 ноября 2011

Хороший обходной путь для создания lex-сканера с глупым синтаксисом, который распознает только литералы.В приведенном ниже примере «aaaa» заменяется на «AAAA» и так далее.Выходные данные не сканируются повторно.

%%

"aaaa" { fputs("AAAA", stdout ); }

"bbbb" { fputs("BBBB", stdout ); }

"cccc" { fputs("CCCC", stdout ); }

. { ECHO; }

[ \t\r\n]+ { ECHO; }

%%

Фрагмент make-файла для этого:

#Makefile

LDFLAGS := -lfl
###################

replace: replace.o
    $(CC) -o $@  $? $(LDFLAGS)

replace.o: replace.c

replace.c: replace.l

(но, вероятно, было бы проще просто использовать sed) Хорошим свойством этого метода является то, что (f) lex выполняет всебуферизация, и требуется только минимальное количество буферизации.Поскольку lex создает DFA, метод также быстрый: по сути, все строки совпадают параллельно .

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