查找和替换功能

时间:2011-11-29 16:10:11

标签: c file-io

我希望创建一个C函数,在该函数中,它将根据用户输入的条目搜索文件,并能够替换那里的内容。我见过类似的c ++示例,但我不太了解c ++。任何建议或示例代码,以帮助我开始将是惊人的。我的理解是我需要打开原始文件进行读取,打开一个新文件进行写入,一次读取一行orig文件,将该行写入新文件,完成后删除原始文件,并重命名新文件文件的原始文件名。

任何带有解释的建议或示例代码都是最有帮助的

编辑经过进一步的研究,我在想是否可以找到一种方法来查找文件,搜索文件,进行更改,然后将其转换回文件就可以了更容易。

3 个答案:

答案 0 :(得分:1)

尝试这样的事情: -

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

答案 1 :(得分:1)

使用面向行的函数进行读写很容易,通常会使用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",..)这是一些可以用来改进和学习的想法和概念。希望你有很多乐趣

答案 2 :(得分:0)

使用仅识别文字的愚蠢语法创建lex-scanner的一个很好的解决方法。在下面的例子中,“aaaa”被“AAAA”等替代。输出未重新扫描。

%%

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

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

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

. { ECHO; }

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

%%

这个的makefile片段:

#Makefile

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

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

replace.o: replace.c

replace.c: replace.l

(但是使用sed可能会更容易) 这种方法的一个很好的特性是(f)lex完成所有缓冲,并且只需要最少量的缓冲。由于lex创建了DFA,因此该方法也很快:有效地,所有字符串并行匹配