C 统计字符数 行数
#include <stdio.h> int isLetter(char ch); int main() { int countWords=0; int countLines=0; char ch; char chPre; while( (ch=getchar())!=EOF ){//EOF是一个字符型常量 if(ch=='\n'){ countLines++; } if(isLetter(chPre)&& (ch==' '||ch=='\0' || ch=='\n' || ch=='.' )){ countWords++; } chPre=ch; } printf("%d %d",countWords,countLines); return 1; } int isLetter(char ch){ if( (ch>='A'&& ch<='Z') || (ch>='a'&&ch<='z')){ return 1; }else{ return 0; } }
//教程上的做法: #include <stdio.h> #define IN 1 /* 在单词内 */ #define OUT 0 /* 在单词外 */ /* 统计输入的行数、单词数与字符数 */ main() { int c, nl, nw, nc, state; state = OUT; nl = nw = nc = 0; while ((c = getchar()) != EOF) { ++nc; if (c == '\n') ++nl; if (c == ' ' || c == '\n' || c == '\t') state = OUT; else if (state == OUT) { state = IN; ++nw; } } printf("%d %d %d\n", nl, nw, nc); }
程序在执行时,每当遇到单词的第一个字符,它就作为一个新单词加以统计。 s t a t e变量用于 记录程序是否正在处理一个单词(是否在一个单词中),它的初值是“不在单词中”,即被赋初 值为O U T。我们在这里使用了符号常量 I N与O U T而没有使用其字面值1与0,主要是因为这可以 使程序更可读。在比较小的程序中,这样做也许看不出有什么区别,但在比较大的程序中,如 果从一开始就这样做,那么所增加的一点工作量与所提高的程序的明晰性相比是很值得的。读 者也会发现,在程序中,如果幻数仅仅出现在符号常量中,那么对程序做大量修改就显得比较 容易。 语句行
nl = nw = nc = 0; 用于把其中的三个变量n l 、 nw 与n c都置为 0。这种情况并不特殊,但要注意这样一个事实,在兼 有值与赋值两种功能的表达式中,赋值结合次序是由右至左。所以上面这个语句也可以写成:
nl = ( nw = ( nc = 0 ));
运算符 | | 的意思是O R (或) ,所以程序行
if ( c == ' ' ||c == '\n' || c == '\t' )
的意思是“如果c是空格或c是换行符或c是制表符”(回忆一下,换码序列 \ t 是制表符的可见表
示)。与之对应的一个运算符是& &,其含义是A N D(与),其优先级只比 || 高一级。经由& &或 || 连接的表达式由左至右求值,并保证在求值过程中只要已得知真或假,求值就停止。如果 c是 一个空格,那么就没有必要再测试它是否为换行符或制表符,故后两个测试无需再进行。在这 里这倒不特别重要,但在某些更复杂的情况下这样做就显得很重要,不久我们将会看到这种例 子。
测试例子
Dashing through the snow
In a one horse open sleigh
O'er the fields we go
Laughing all the way
Bells on bob tails ring
Making spirits bright
What fun it is to laugh and sing
A sleighing song tonight