【问题标题】:Check duplicates words in a file检查文件中的重复单词
【发布时间】:2016-02-03 19:20:35
【问题描述】:

我想检查 .txt 文件中是否有任何重复项。我写了一个代码,但它没有运行。我不确定在"a+" 模式下打开norep.txt 文件。想法是将我的文本的第一个单词放在norep.txt 文件中,然后将text.txt 中的每个单词与norep.txt 中的单词进行比较,然后只复制文件中我需要的单词。

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

int main() {
    FILE *fd;
    FILE *ft;
    char aux[30];
    char aux1[30];    
    int len;    

    fd = fopen("c:\\text.txt", "r");
    if (fd == NULL) {
        puts("Error");
    }

    ft = fopen("c:\\norep.txt", "a+");
    if (ft == NULL) {
        puts("Error");
    }

    fscanf(fd, "%s", aux);
    fprintf(ft, "%s", aux);
    rewind(fd);
    rewind(ft);
    while (!feof(fd)) {
        fscanf(fd, "%s", aux);

        while (!feof(ft)) {
            fscanf(ft, "%s", aux1);
            len = strcmp(aux, aux1);

            if (len != 0) {
                fprintf(ft, "%s", aux);
            }
        }
        rewind(ft);
    }
    return 0;
}

【问题讨论】:

  • it's not running. 为什么不呢?进一步描述您的问题。
  • 程序立即结束
  • 程序结束和程序未运行是很不一样的东西。
  • 另外,如果遇到致命错误,请退出,不要只是打印并继续。

标签: c file printf scanf words


【解决方案1】:

您应该在倒带之前刷新输出文件。

fflush - flush a streamfflush

当然,这不会解决您的问题,因为:

请注意下面的手册说重新定位操作被忽略,因此您的阅读尝试总是会找到文件的结尾。

追加:在文件末尾打开文件以进行输出。输出操作 总是在文件末尾写入数据,扩展它。重新定位 操作(fseek、fsetpos、rewind)被忽略。文件已创建 如果它不存在。

您可能应该做的是创建一个内部内存表来保存所有唯一条目,并在所有处理完成后将其写入一个新文件。当您阅读 fd 文件时,检查列表并添加一个新条目(如果它不在列表中)。然后在你完成处理 fd 之后,然后才写出你的列表。当然,根据数据文件的大小,这可能会太大。

您可以随时将每个唯一条目附加到输出文件中。但是您需要有一些方法来检查以前的条目而不尝试读取输出文件。

【讨论】:

  • 如何刷新输出?我想程序在尝试在 norep.txt 中写入新单词时关闭
  • @Marco 我在两本手册中添加了指向 fflush() 条目的指针。
  • @Marco 手册似乎说,因为它被标记为“附加”,所以写入磁盘的数据必须始终位于文件末尾。这似乎是 Unix 的要求。
  • @Marco 我为答案添加了更新,但除此之外我没有什么可以说的。
【解决方案2】:

解决这个问题的通常方法是逐字读取输入文件,以某种方式存储必要的信息,然后在读取文件中的所有信息后,将所需的输出写入输出文件。

该方法的粗略框架可能如下所示:

int main()
{
    const char *infile = "text.txt";
    const char *outfile = "norep.txt";

    FILE *in;
    FILE *out;

    char word[30];

    // (1) Read all words

    in = fopen(infile, "r");      // .. and enforce success

    while (fscanf(in, "%29s", word) == 1) {
        // store word somewhere
    }        
    fclose(in);

    // (2) Determine unique words somehow

    // (3) Write out unique words

    out = fopen(outfile, "w");    // .. and enforce success

    for (i = 0; i < nunique; i++) {
        fprintf(out, "%s\n", unique[i]);
    }        
    fclose(out);

    return 0;
}

这个不完整的骨架代码中缺少查找唯一词的实际算法。

如果您真的想测试文件中单词的唯一性而不使用当前单词之外的额外内存,您可以使用独立的文件指针打开输入文件两次。然后你可以像这样写一个循环:

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

int main()
{
    const char *infile = "text.txt";
    const char *outfile = "norep.txt";

    FILE *in1;
    FILE *in2;
    FILE *out;

    char word1[30];
    char word2[30];

    in1 = fopen(infile, "r");
    in2 = fopen(infile, "r");
    out = fopen(outfile, "w");

    if (in1 == NULL || in2 == NULL || out == NULL) {
        fprintf(stderr, "Could not open all required files.\n");
        exit(1);
    }

    while (fscanf(in1, "%29s", word1) == 1) {
        int count = 0;

        while (fscanf(in2, "%29s", word2) == 1) {
            if (strcmp(word1, word2) == 0) count++;
            if (count > 1) break;
        }

        if (count == 1) fprintf(out, "%s\n", word1);
        rewind(in2);
    }

    fclose(in1);
    fclose(in2);
    fclose(out);

    return 0;
}

这当然会像文件中的单词一样频繁地重新读取文件。不是在 Moby-Dick 中找到独特单词的好方法。我建议您研究基于内存的方法。

【讨论】:

  • 如果我需要在文件中添加一次非唯一词,我该如何修改循环?
  • 这很明显,不是吗?一个独特的词只出现一次,重复的词出现得更频繁。所以你只需要将写入out的条件改为if (count &gt; 1) ...即可。
  • 不,因为我只想复制非唯一的单词一次,这样程序只会复制多次出现的非唯一单词
  • 好吧,你是对的,该解决方案仅适用于独特的单词。您可能可以解决这个问题,但它会产生一个已经非常丑陋甚至更丑陋的解决方案。不要使用文件的方法,想出一个将单词存储在内存中的解决方案。在 cmets 中,user3386109 列出了一些可能性;我认为他的“简单方法”适用于小文件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-17
  • 1970-01-01
  • 2021-07-25
  • 2020-02-17
  • 2012-12-14
相关资源
最近更新 更多