在C中查找并替换

时间:2017-05-13 19:47:36

标签: c file

程序应该从stdin读取数据到文本文件,然后对文件执行查找和替换,条件是新单词比旧单词长。它编译没有任何错误或警告罚款,但问题是fread不起作用,它似乎返回0所以while循环不起作用。打印文件功能就是可以检查文件的内容,它不是最终代码的一部分。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_SIZE 1000
#define OLD_WORD_SIZE 24
#define NEW_WORD_SIZE 64

void write_to_file(const char *s);
void replace_word(const char *s, const char *old, const char *new);
void print_file(const char *s);

int main(void){
    const char file_name[] = "text.txt";
    int c;
    char old_word[OLD_WORD_SIZE];
    char new_word[NEW_WORD_SIZE];
    while((c = getchar()) != EOF){
        switch(c){
        case 'w':
            getchar();
            write_to_file(file_name);
            break;
        case 'r':
            getchar();
            puts("Enter the word you want to replace");
            fgets(old_word, sizeof(old_word), stdin);
            old_word[strlen(old_word) - 1] = '\0';
            puts("Enter the new word");
            fgets(new_word, sizeof(new_word), stdin);
            new_word[strlen(new_word) - 1]  = '\0';
            if(strlen(old_word) >= strlen(new_word)){
                printf("Error: can't replace \"%s\" with \"%s\":\n\"%s\" is too small\n", old_word, new_word, new_word);
                break;
            }
            replace_word(file_name, old_word, new_word);
            getchar();
            break;
        case 'p':
            print_file(file_name);
            getchar();
            getchar();
            break;
        default:
            printf("Invalid command:%i\n", c);
            break;
        }
    }
    return 0;
}

void write_to_file(const char *s){
    FILE *out_file;
    if((out_file = fopen(s, "w")) == NULL){
        perror(s);
        exit(EXIT_FAILURE);
    }
    int c;
    while((c = getchar()) != EOF){
        fputc(c, out_file);
    }
    fclose(out_file);
}

void print_file(const char *s){
    FILE *in_file;
    if((in_file = fopen(s, "r")) == NULL){
        perror(s);
        exit(EXIT_FAILURE);
    }
    int c;
    while((c = fgetc(in_file)) != EOF){
        printf("%c", c);
    }
    fclose(in_file);
}

void replace_word(const char *s, const char *old_word, const char *new_word){
    char *buffer = malloc(BUFFER_SIZE);
    FILE *original_file;
    FILE *copy;

    if((original_file = fopen(s, "r")) == NULL){
        perror(s);
        exit(EXIT_FAILURE);
    }

    if((copy = fopen("copy.txt", "w")) == NULL){
        perror("text");
        exit(EXIT_FAILURE);
    }

    int old_word_len = strlen(old_word);
    int new_word_len = strlen(new_word);

    char *src;
    char *dst;
    char *tmp;
    while(fread(&buffer, BUFFER_SIZE, 1, original_file) == 1){
        if((tmp = strstr(buffer, old_word))){
            buffer = realloc(buffer, BUFFER_SIZE + new_word_len - old_word_len + 1);
            src = tmp + old_word_len;
            dst = tmp + new_word_len;
            memmove(dst, src, BUFFER_SIZE - strlen(src));
            memcpy(tmp, new_word, new_word_len);
            fwrite(&buffer, BUFFER_SIZE + new_word_len - old_word_len + 1, 1, copy);
        }
        else{
            fwrite(&buffer, BUFFER_SIZE, 1, copy);
        }
        fseek(original_file, -old_word_len, SEEK_CUR);
    }
}

代码不完整,只缺少一小段,我不会将修改后的版本移回原始文件。

为什么fread返回零?代码中是否还有其他错误?

我意识到我应该在最后释放缓冲区。

2 个答案:

答案 0 :(得分:1)

您想将第二个和第三个参数交换为fread()

你拥有它的方式,如果它可以读取1个字节,它将只返回BUFFER_SIZE

 n = fread(buffer, 1, BUFFER_SIZE, original_file);
 if (n == BUFFER_SIZE) /* buffer full, needs to read more */;
 if (n > 0) /* read n bytes */;

评论中建议的更好的方法是使用fgets()

答案 1 :(得分:0)

你不应该在那里使用&buffer。由于缓冲区已经是一个char指针,因此将buffer作为fread和fwrite的第一个参数传递。