c 结束程序_C语言写一个统计单词的程序

a58969d5cdef0b8a285658be2f2f9f44.png

施工图

现在,我们可以编写一个统计单词数量的程序(即,该程序读取并报告单词的数量)。

伪码实现分析

该程序还可以计算字符数和行数。先来看看编写这样的程序要涉及那些内容。首先,该程序要逐个字符读取输入,知道何时停止读取。然后,该程序能识别并计算这些内容:字符、行数和单词。据此我们编写的伪代码如下:

read a characterwhile there is more input     increment character count     if a line has been read, increment line count     if a word has been read, increment word count     read next characterYou already have a model for the input loop:

输入循环的模型为:

while ((ch = getchar()) != STOP){  ...}

这里,STOP表示能标识输入末尾的某个值。以前我们用过换行符和句点标记输入的末尾,但是对于一个通用的统计单词程序,它们都不合适。我们暂时选用一个文本中不常用的字符(如,|)作为输入的末尾标记。第8章中会介绍更好的方法,以便程序既能处理文本文件,又能处理键盘输入。

现在,我们考虑循环体。因为该程序使用getchar()进行输入,所以每次迭代都要通过递增计数器来计数。为了统计行数,程序要能检查换行字符。如果输入的字符是一个换行符,该程序应该递增行数计数器。这里要注意STOP字符位于一行的中间的情况。是否递增行数计数?我们可以作为特殊行计数,即没有换行符的一行字符。可以通过记录之前读取的字符识别这种情况,即如果读取时发现STOP字符的上一个字符不是换行符,那么这行就是特殊行。

识别单词

最棘手的部分是识别单词。首先,必须定义什么是该程序识别的单词。我们用一个相对简单的方法,把一个单词定义为一个不含空白(即,没有空格、制表符或换行符)的字符序列。因此,“glymxck”和“r2d2”都算是一个单词。程序读取的第1个非空白字符即是一个单词的开始,当读到空白字符时结束。判断非空白字符最直接的测试表达式是:

最棘手的部分是识别单词。首先,必须定义什么是该程序识别的单词。我们用一个相对简单的方法,把一个单词定义为一个不含空白(即,没有空格、制表符或换行符)的字符序列。因此,“glymxck”和“r2d2”都算是一个单词。程序读取的第1个非空白字符即是一个单词的开始,当读到空白字符时结束。判断非空白字符最直接的测试表达式是:

c != ' ' && c != '' && c != 't'   /* true if c is not whitespace */

检测空白字符最直接的测试表达式是:

c == ' ' || c == '' || c == 't'   /* true if c is whitespace */

然而,使用ctype.h头文件中的函数isspace()更简单,如果该函数的参数是空白字符,则返回真。所以,如果c是空白字符,isspace(c)为真;如果c不是空白字符,!isspace(c)为真。要查找一个单词里是否有某个字符,可以在程序读入单词的首字符时把一个标记(名为inword)设置为1。也可以在此时递增单词计数。然后,只要inword为1(或true),后续的非空白字符都不记为单词的开始。下一个空白字符,必须重置标记为0(或false),然后程序就准备好读取下一个单词。我们把以上分析写成伪代码:

if c is not whitespace and inword is false     set inword to true and count the wordif c is whitespace and inword is true     set inword to false

这种方法在读到每个单词的开头时把inword设置为1(真),在读到每个单词的末尾时把inword设置为0(假)。只有在标记从0设置为1时,递增单词计数。如果能使用_Bool类型,可以在程序中包含stdbool.h头文件,把inword的类型设置为bool,其值用true和false表示。如果编译器不支持这种用法,就把inword的类型设置为int,其值用1和0表示。如果使用布尔类型的变量,通常习惯把变量自身作为测试条件。如下所示:

用if (inword)代替if (inword == true)用if (!inword)代替if (inword == false)

可以这样做的原因是,如果inword为true,则表达式inword ==true 为true;如果inword为false,则表达式inword == true为false。

所以,还不如直接用inword作为测试条件。类似地,!inword的值与表达式inword == false的值相同(非真即false,非假即true)。

代码实现:

上述思路(识别行、识别不完整的行和识别单词)翻译了成C代码。

// wordcnt.c -- counts characters, words, lines#include #include          // for isspace()#include        // for bool, true, false#define STOP '|'int main(void){    char c;                 // read in character    char prev;              // previous character read    long n_chars = 0L;      // number of characters    int n_lines = 0;        // number of lines    int n_words = 0;        // number of words    int p_lines = 0;        // number of partial lines    bool inword = false;    // == true if c is in a word    printf("Enter text to be analyzed (| to terminate):");    prev = '';            // used to identify complete lines    while ((c = getchar()) != STOP)    {        n_chars++;          // count characters        if (c == '')            n_lines++;      // count lines        if (!isspace(c) && !inword)        {            inword = true;  // starting a new word            n_words++;      // count word        }        if (isspace(c) && inword)            inword = false; // reached end of word        prev = c;           // save character value    }    if (prev != '')        p_lines = 1;    printf("characters = %ld, words = %d, lines = %d, ",          n_chars, n_words, n_lines);    printf("partial lines = %d", p_lines);    return 0;}

下面是运行该程序后的一个输出示例:

Enter text to be analyzed (| to terminate):Reason is apowerful servant butan inadequate master.|characters = 55, words = 9, lines = 3, partial lines = 0

该程序使用逻辑运算符把伪代码翻译成C代码。例如,把下面的伪代码:

if (!isspace(c) && !inword)

再次提醒读者注意,!inword与inword == false等价。上面的整个测试条件比单独判断每个空白字符的可读性高:

if (c != ' ' && c != '' && c != 't' && !inword)

上面的两种形式都表示“如果c不是空白字符,且如果c不在单词里”。如果两个条件都满足,则一定是一个新单词的开头,所以要递增n_words。如果位于单词中,满足第1个条件,但是inword为true,就不递增n_word。当读到下一个空白字符时,inword被再次设置为false。检查代码,查看一下如果单词之间有多个空格时,程序是否能正常运行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值