【问题标题】:Counting number of words inside a text file and printing results in a different text file in c/c++计算文本文件中的字数并在 c/c++ 中打印出不同的文本文件
【发布时间】:2021-08-11 03:37:11
【问题描述】:

代码:

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

char filename[] = "11.txt";
char filename1[] = "2.txt";
FILE *ptr, *resultptr;
char string[100];
char words[100][100];
int len = sizeof(filename) / sizeof(char);
int i = 0, j = 0, k, length, count;

int main()
{
    fopen_s(&ptr, filename, "r");
    fopen_s(&resultptr, filename1, "w");

    if ((ptr == nullptr) || (resultptr == nullptr)) {
        printf("Files were not opened!");
        return -1;
    }
    while (fgets(string, sizeof string, ptr)) {
        for (k = 0; string[k] != '\0'; k++) {
            if (string[k] != ' ' && string[k] != '\n') {
                words[i][j++] = tolower(string[k]);
            } else {
                words[i][j] = '\0';
                i++;
                j = 0;
            }
        }
        length = i + !!j;
        fputs("Occurrences of each word:\n", resultptr); //prints this sentence into file
        for (i = 0; i < length; i++) {
            if (strcmp(words[i], "0") == 0)
                continue;
            count = 1; 
            char *ch = words[i];
            for (j = i + 1; j < length; j++) {
                if (strcmp(words[i], words[j]) == 0 && (strcmp(words[j], "0") != 0))         {
                    count++;
                    strcpy_s(words[j], "0");
                }   
            }
            fputs("The word ", resultptr);
            if (string[i] != ' ' && string[i] != '\n') {
                fprintf(resultptr, "%s", ch);
            }
            fputs(" occurred ", resultptr);
            fprintf(resultptr, "%d", count);
            fputs(" times\n", resultptr);
        }
        fclose(ptr);
        fclose(resultptr);
        return 0;
     }
 } 

计数部分工作得非常好,但问题是当我尝试打印结果时,对于句子“to be or not: to be that is the question ...”它会打印:

Occurrences of each word:
The word to occurred 2 times
The word be occurred 2 times
The word  occurred 1 times
The word not: occurred 1 times
The word that occurred 1 times
The word is occurred 1 times
The word  occurred 1 times
Occurrences of each word:
The word to occurred 1 times
The word be occurred 1 times
The word or occurred 1 times
The word  occurred 1 times
The word that occurred 1 times
The word is occurred 1 times
The word  occurred 2 times
The word question occurred 1 times
The word ... occurred 1 times

怎么了?就像我不专业,但有人可以指导我这里有什么问题吗?和原来的有点变化,但还是有很多错误

【问题讨论】:

  • 评论不用于扩展讨论;这个对话是moved to chat
  • 请不要以使现有答案无效的方式更改问题。我已回滚您最近的编辑。如果您想使用后续问题更新您的问题,则可以将其添加到问题的底部。只要原始问题保持不变,这不会使现有答案无效。
  • @Youngwildandfree:您可以通过单击分数下方的灰色复选标记来接受其中一个答案。

标签: c file count


【解决方案1】:

代码中存在多个问题:

  • 应将全局变量移至 main() 函数的主体内。
  • fopen_s() 不可移植,请改用 fopen()
  • strcpy_s() 不可移植,请改用 strcpy() 或仅将字符串的第一个字节设置为 '\0' 以使其为空字符串。
  • ij 应在每个 fgets() 之后重置为 0
  • 您应该使用isalpha() 测试字母,而不是只测试空格和换行符。
  • 您应该通过将重复的单词设置为空字符串来清除它们。
  • 您应该对输出行使用简单的fprintf() 调用。
  • 您不应关闭 while(fgets(...)) 循环内的文件。

如果您想计算文件中的所有单词,这种方法仅限于相当少量的单词。更通用的解决方案是构建一个在您阅读文件内容时找到的单词字典,并为找到的每个单词增加计数。

这是修改后的版本:

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

#ifdef _MSC_VER
#pragma warning(disable:4996)  // disable Microsoft obnoxious warning
#endif

#define WORDS 2000
#define CHARS 40

int main() {
    char filename[] = "11.txt";
    char filename1[] = "2.txt";
    FILE *ptr, *resultptr;
    char string[100];
    char words[WORDS][CHARS];
    int i, j, k, length, count;

    ptr = fopen(filename, "r");
    if (ptr == NULL) {
        fprintf(stderr, "cannot open %s: %s\n", filename, strerror(errno));
        return 1;
    }
    resultptr = fopen(filename1, "w");
    if (resultptr == NULL) {
        fprintf(stderr, "cannot open %s: %s\n", filename1, strerror(errno));
        return 1;
    }

    i = j = 0;

    while (i < WORDS && fgets(string, sizeof string, ptr)) {
        for (k = 0; string[k] != '\0'; k++) {
            unsigned char c = string[k];
            if (isalpha(c)) {
                if (j < CHARS - 1)
                    words[i][j++] = tolower(c);
            } else {
                words[i][j] = '\0';
                if (j > 0) {
                    j = 0;
                    i++;
                    if (i == WORDS)
                        break;
                }
            }
        }
        if (j > 0) {
            // include the last word if the file does not end with a newline
            words[i][j] = '\0';
            i++;
        }
    }
    length = i;
    fprintf(resultptr, "Occurrences of each word:\n");
    for (i = 0; i < length; i++) {
        if (words[i][0] == '\0')
            continue;
        count = 1; 
        for (j = i + 1; j < length; j++) {
            if (strcmp(words[i], words[j]) == 0)         {
                count++;
                words[j][0] = '\0';
            }   
        }
        fprintf(resultptr, "The word %s occurred %d times\n", words[i], count);
    }
    fclose(ptr);
    fclose(resultptr);
    return 0;
}

【讨论】:

    【解决方案2】:

    注意:同时,OP 已对问题应用了上述修复,从而使该答案无效。此答案适用于revision 4 of the question

    怎么了?

    1. The word 0 occurred 1 times - 您选择用字符串 "0" 替换重复的单词。为了不将这些替换视为单词,请插入

                  if (strcmp(words[i], "0") == 0) continue;
      

      在打印for 循环体的最开始。您似乎打算 if (string[i] != ' ' &amp;&amp; string[i] != '\0' &amp;&amp; string[i]!='0' ) 执行此操作,但这不起作用 - 删除此代码。
      此外,空字符串是更好的选择,允许使用单词0

    2. The word
      occurred 1 times - 末尾的'\n' 被计为一个单词。为了不计算这个,另外跳过标点符号以及避免由于连续的非单词字符导致空词,替换

                  if (string[k] != ' ' && string[k] != '\0') {
                      words[i][j++] = tolower(string[k]);
                  }
                  else
      

                  if (isalnum(string[k]))
                      words[i][j++] = tolower(string[k]);
                  else if (j)
      
    3. The word occurred 1 times - 计算文件末尾的空字。为了不计算在内,只有在 EOF 处的单词 i 内时,才将 1 添加到 i。 e.改变

              length = i + 1;
      

              length = i + !!j;
      

    【讨论】:

    • 那是因为您只调用了一次fgets。要更改此设置,请将 fgets(string, 100, ptr); //reads a line while (!feof(ptr)) { 替换为 while (fgets(string, sizeof string, ptr)) 并在末尾删除多余的 }
    • 如果它打印出单词0,那么你似乎没有对上面的1.进行更改。
    • 而且由于无法正确格式化cmets中的数据,您最好将输入文件的真实内容插入问题帖子中的行之间```。
    • 放在for (i = 0; i &lt; length; i++) {之后。 - 我现在下班,两小时后回来,负责处理其他问题 - 如果那时你还没有自己解决的话。 ;-)
    • 比如built-in应该算多少字?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多