【问题标题】:C - Counting words, characters and lines in file. Character countC - 计算文件中的单词、字符和行数。字符数
【发布时间】:2018-06-02 18:50:09
【问题描述】:

我必须用 C 语言编写代码,输出给定文件中的字符数、行数和单词数。任务看起来很简单,但我真的不确定现在出了什么问题。

所以,这里是代码:

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

int main()
{
    FILE *file;
    char filename[256];
    char ch;
    char prevch;

    int lines=0;
    int words=0;
    int characters=0;

    printf("Enter your filename (don't forget about extension!):\n");
    scanf("%s", filename);

    file=fopen(filename, "r");
    if(file == NULL)
    {
        printf("Cannot open file %s \n", filename);
        exit(0);
    }
    else
    {

        while((ch=fgetc(file))!=EOF)
        {
            if(ch==' ' || ch=='\n' || ch=='\t')
            {
                if(isspace(prevch)==0)
                {
                    words++;
                }
            }
            if(ch=='\n')
            {
                lines++;
            }

            prevch=ch;
            characters++;
        }
    }

    fclose(file);

    if(isspace(prevch)==0)
    {
        words++;
    } 

    printf("Number of characters: %d\n", characters);
    printf("Number of words: %d\n", words);
    printf("Number of lines: %d\n", lines);

    return 0;
}

任务的想法是输出应该与Linux中命令wc的输出相同。但我完全不知道,为什么我的循环跳过了一些字符。我编写代码的方式应该适合计算每个字符,即使是那些空格。为什么我的程序显示示例文件包含 65 个字符,而 wc 显示 68?我一直认为可能有一些字符被 fgetc 跳过了,但这是不可能的,因为我之前在编写程序将一个文本文件的内容复制到另一个文本文件的内容并且一切正常时使用了该功能。

顺便问一下,我的字数统计解决方案是否正确?循环后的条件应确保计算 EOF 之前的最后一个单词。我使用 isspace 来确保结尾不只是一些空格。

谢谢!

【问题讨论】:

  • if(ch==' ' || ch=='\n' || ch=='\t') 你为什么不也使用isspace(ch)
  • 你还没有初始化 prevch - 你应该初始化它以包含一个空格,否则如果文件中的第一个字符 is 是一个空格,那么你有一个错误的计数......
  • 记住:fgetc() 返回一个int,而不是char。如果您使用 char,则无法可靠地检测 EOF,尽管问题的性质取决于普通的 char 是有符号还是无符号以及使用的代码集。
  • “我的程序显示示例文件包含 65 个字符,而 wc 显示 68”:您是否在 Windows 上工作,您的文件是否只有三行?如果是这样,问题是 Windows 将 CRLF 行结尾映射到换行符,因此 3 个 CRLF 对映射到 3 个 NL-only(LF-only)结尾,解释了差异。以二进制模式打开文件。
  • @Coolerini Windows 上的 CRLF 行尾与 Linux/Unix 上的 LF 行尾等是一个非常常见的问题。

标签: c file character lines words


【解决方案1】:

"我的程序显示示例文件包含 65 个字符,而 wc 显示为 68"

您是否在 Windows 上工作,您的文件是否只有三行?如果是这样,问题在于 Windows 将 CRLF 行结尾映射到换行符,因此 3 个 CRLF 对映射到 3 个换行符(仅限 LF)结尾,从而解释了差异。要解决此问题,请以二进制模式打开文件。

在没有运行您的代码的情况下,我认为您计算单词的代码是可以的。您可以改为使用最初设置为 0 (false) 的“in-word”标志并切换到 true 并在您检测到不在单词中的非空白内容时计算一个新单词。两者都有效;它们略有不同。

另外,请记住 fgetc() 和亲戚返回 int,而不是 char。如果将返回值保存在 char 中,则无法可靠地检测 EOF,尽管问题的性质取决于普通的 char 是有符号还是无符号以及使用的代码集。

如果plain char 是无符号类型,则永远无法检测到 EOF(因为 EOF 映射到 0xFF,并且当将其转换为 int 以与 EOF 进行比较时,它是正数)。如果对普通的char 进行了签名,如果输入包含代码 0xFF(在 ISO 8859-1 和相关代码集中,即 ÿ — Unicode 术语中带分音符号的拉丁小写字母 Y),您会及早检测到 EOF。但是,有效的 UTF-8 永远不能包含字节 0xFF(也不包含 0xC0、0xC1 或 0xF5..0xFF),因此您不应该遇到这种误解问题 - 但是您的代码也是字节计数而不是字符计数。

【讨论】:

    【解决方案2】:

    你可以这样做

    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    
    int main()
    {
        FILE *file;
        char filename[256];
        char ch;
        char prevch = '\0';
    
        int lines = 0;
        int words = 0;
        int characters = 0;
    
        printf("Enter your filename (don't forget about extension!):\n");
        scanf("%s", filename);
    
        file = fopen(filename, "r");
        if(file == NULL)
        {
            fprintf(stderr, "Cannot open file %s \n", filename);
            exit(-1);
        }
    
        while((ch = fgetc(file)) != EOF)
        {
            if(isspace(ch))
            {
                if (ch == '\n')
                    lines++;
            }else {
                if (prevch == '\0' || isspace(prevch)) 
                    words++;
            }
    
            characters++;
            prevch = ch;  
        }
    
        fclose(file);
    
        printf("Number of characters: %d\n", characters);
        printf("Number of words: %d\n", words);
        printf("Number of lines: %d\n", lines);
    
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-02-20
      • 2023-03-12
      • 2014-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多