C Primer Plus学习—统计单词的程序

现在,我们可以编写一个程序来统计一段文字的单词数量,行数和字符数。

在做一个程序之前需要有一个思路。

首先该程序要逐个字符读取输入,知道何时停止读取。然后,程序能识别并计算这些内容:字符、行数和单词。根据这些,书上推荐我们用伪代码(我觉得这像是列提纲):

读取一个字符

当有更多输入时

    递增字符计数

    如果读完一行,递增行数计数

    如果读完一个单词,递增单词计数

    读取下一个字符

前面有一个while语句的输入循环模型

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

STOP表示能识别输入末尾的某个值。以前我们用过换行符和句点标记输入的末尾,但是对于一个通用的统计单词程序,他们都不合适。暂时选用一个文本不常用的返回(如“|”)作为输入的末尾标记。下一章会有更好的方法,使程序既能处理文本文件,又能处理键盘输入。

现在我们考虑循环体。因为程序使用getchar( )进行输入每次迭代都需要通过计数器来进行计数。为了统计行数,程序就要能够检测换行符,且有一个用于记录行数的计数器。这里将用STOP来作为末尾标记,如果在文本中间出现了STOP可能会是程序提前终止(即考虑是否还要进行行数叠加),问你可以作为特殊行计数,即没有换行符的一行字符。通过之前读取的来识别这种情况,即如果发现STOP前面的字符不是换行符,那么这一行就是特殊行。

上面的问题都不算太棘手,最棘手的问题是如何识别单词。

我们用一个简单的方法,把单词定义为不含空白的连续字符序列,下面是这个判断方法:

c  !=  '  '  &&  c  !=  ' \n '  &&  c  !=  ' \t '

但是问题来了,像"hk32hug"这样的不是单词的连续字符序列,程序不能识别出来。所以判断方法需要改进。

然而,使用前面介绍过的ctype.h头文件中的isspace()行数或更加简单,如果该程序的参数是空白字符,则返回真。所以如果c是空白字符,isspace(c)为真;如果c不是空白字符,!isspace(c)为真。

要查找一个单词里是否有某个字符,可以在程序读入单词首字母时标记(名为inword)设置值为1.也可以在此时递增单词计数。然后,是要inword为1(或true)后续的非空白字符都不记为单词的开始,下一个空白字符必须标记为0(false),然后程序准备好读取下一个单词。我们把上面的分析写成伪代码:

    如果c不是空白字符,且inword为假

        设置inword为真,并给单词计数

    如果c是空白字符,且inword为真

        设置inword为假

 这种方法在读到每个单词的开头是把inword设置为1(真),读到每个单词末尾时把inword设置为0(假)。只有在标记从0设置为1时增加单词计数。如果能使用Bool类型,可以在程序头加上stdbool.h头文件,并把inword的类型设置为bool类型,其值用true或false表示。编译器不支持就用int类型,设置值为1或0 。

如果使用bool类型变量,通常习惯把自身作为测试条件。如下所示:

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

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

下面是代码

-----------------------------------------------分割线--------------------------------------

/*wordcnt.c -- 统计字符数、单词数、行数*/
#include <stdio.h>
#include <ctype.h>					//为isspace()行函数提供原型 
#include <stdbool.h>				//为bool,true,false提供定义 
#define STOP '|'
int main (void)
{
	char c;							//读入字符
	char prev;						//读入前一个字符
	long n_chars = 0L;				//字符数
	int n_lines = 0;				//行数 
	int n_words = 0;                //单词数
	int p_lines = 0;                //不完整行数 
	bool inword = false;            //如果c在单词中,inword等于true
	
	printf("Enter text to be analyzed (| to terminate):\n");
	prev = '\n';					//用于识别完整的行
	while((c = getchar()) != STOP){
		n_chars++;                  //统计字符
		if(c == '\n'){
			n_lines++;				//统计行数 
		} 
		if(!isspace(c) && !inword){
			inword = true;			//开始一个新的单词 
			n_words++;				//统计单词 
		}
		if(isspace(c) && inword){
			inword = false;         //打到单词的末尾 
		} 
		prev = c;					//保存字符的值 
	} 
	
	if(prev != '\n'){
		p_lines = 1;
	} 
	printf("characters = %ld, word = %d, lines = %d, ", n_chars, n_words, n_lines);
	printf("partial lines = %d\n", p_lines);
	
	return 0;
 } 
Enter text to be analyzed (| to terminate):
Reason is a
powerful servant but
an inadequate master.|

characters = 54, word = 9, lines = 2, partial lines = 1


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值