C编程 - 如何从文件中删除包含特定单词的行?

时间:2016-01-26 22:25:44

标签: c file-handling

我为珠宝店创建了库存盘点计划。

但是,我似乎无法弄清楚如何在包含项目的文件中搜索特定单词(以表格形式),并删除单词所在的整行。

例如,我可以从列表中删除耳环,但不能删除相同行上几个空格的数量。

#include <stdio.h>

int main() {
    FILE *fp1, *fp2;

    //consider 40 character string to store filename
    char filename[40];
    char c;
    int del_line, temp = 1;

    //asks user for file name
    printf("Enter file name: ");

    //receives file name from user and stores in 'filename'
    scanf("%s", filename);

    //open file in read mode
    fp1 = fopen(filename, "r");
    c = getc(fp1);

    //until the last character of file is obtained
    while (c != EOF) {
        printf("%c", c);
        //print current character and read next character
        c = getc(fp1);
    }
    //rewind
    rewind(fp1);
    printf(" \n Enter line number of the line to be deleted:");
    //accept number from user.
    scanf("%d", &del_line);

    //open new file in write mode
    fp2 = fopen("copy.c", "w");
    c = getc(fp1);
    while (c != EOF) {
        c = getc(fp1);
        if (c == '\n')
            temp++;
        //except the line to be deleted
        if (temp != del_line) {
            //copy all lines in file copy.c
            putc(c, fp2);
        }
    }

    //close both the files.
    fclose(fp1);
    fclose(fp2);

    //remove original file
    remove(filename);

    //rename the file copy.c to original name
    rename("copy.c", filename);
    printf("\n The contents of file after being modified are as  follows:\n");

    fp1 = fopen(filename, "r");
    c = getc(fp1);

    while (c != EOF) {
        printf("%c", c);
        c = getc(fp1);
    }
    fclose(fp1);
    return 0;
}

1 个答案:

答案 0 :(得分:3)

您的代码有几个问题:

  • 您使用对scanf的不受保护的调用读取文件名,如果用户键入的名称超过39个字符,则调用未定义的行为。使缓冲区变大,因为文件名现在往往很长,并以这种方式保护格式:

    char filename[256];
    
    if (scanf("%255s", filename) != 1) {
        /* end of file reached, deal with this error */
        ...
    }
    
  • 您逐字节读取文件的方法不正确:c应定义为int,否则您无法可靠地检测EOF。标准惯用法是:

    int c;
    
    //until the last character of file is obtained
    while ((c = getc(fp1)) != EOF) {
        //print current character and read next character
        putchar(c);
    }
    
  • 在复制阶段,您删除文件的第一个字符。

  • 您可以忽略错误。您不仅要调用未定义的行为,还可能在无法复制其内容后删除该文件。

  • 您要求用户提供行号,但不显示回显阶段的行号。这样做会有所帮助。

这是一个改进版本:

#include <stdio.h>

int main(void) {
    FILE *fp1, *fp2;

    //consider 255 character string to store filename
    char filename[256];
    int c, last, del_line, lineno;

    //asks user for file name
    printf("Enter file name: ");

    //receives file name from user and stores in 'filename'
    if (scanf("%255s", filename) != 1) {
        perror("missing filename");
        return 1;
    }

    //open file in read mode
    fp1 = fopen(filename, "r");
    if (fp1 == NULL) {
        perror("cannot open file");
        return 1;
    }

    //until the last character of file is obtained
    last = '\n';
    lineno = 0;
    while ((c = getc(fp1)) != EOF) {
        if (last == '\n') {
            printf("%4d: ", ++lineno);
        }
        //print current character and read next character
        putchar(c);
        last = c;
    }

    rewind(fp1);
    printf("\nEnter line number of the line to be deleted: ");
    //accept number from user.
    if (scanf("%d", &del_line) != 1) {
        perror("missing line number");
        return 1;
    }
    if (del_line < 1 || del_line > lineno) {
        printf("no such line: %d\n", del_line);
        return 1;
    }

    //open new file in write mode
    fp2 = fopen("copy.c", "w");
    if (fp2 == NULL) {
        perror("cannot open copy.c");
        return 1;
    }

    lineno = 1;
    while ((c = getc(fp1)) != EOF) {
        //except the line to be deleted
        if (lineno != del_line) {
            //copy all lines in file copy.c
            putc(c, fp2);
        }
        if (c == '\n')
            lineno++;
    }

    //close both files.
    fclose(fp1);
    if (fclose(fp2)) {
        perror("write error to copy.c");
        return 1;
    }

    // remove original file (unsafe)
    // uncomment this if your system does not allow rename
    // to overwrite existing files
    // if (remove(filename)) {
    //     perror("cannot remove source file");
    //     return 1;
    // }

    //rename the file copy.c to original name
    if (rename("copy.c", filename)) {
        perror("cannot rename file");
        return 1;
    }

    printf("\nThe contents of file after being modified are as  follows:\n");

    fp1 = fopen(filename, "r");
    if (fp1 == NULL) {
        perror("cannot re-open modified file");
        return 1;
    }

    while ((c = getc(fp1)) != EOF) {
        putchar(c);
    }
    fclose(fp1);
    return 0;
}