对标Word不要当真
题目要求:
- 文件中读取字符
- 打印输出每个段落中的单词个数
- 按段落(回车换行为分段)打印输出
- 打印输出每段中最长单词的长度
要求细化:
根据英文构词法,一般统计单词时
- 将形如I’m, Mr.Wang, prat-time, short-term, No.1等统计为一个单词
- 将数字与单词混合的,形如 Round2, Part1, B2C 等统计为一个单词
- 将数字与特殊符号的,形如150.5,99%, ¥100, $0.1等统计为一个单词。
- 单个字符需根据具体要求:+,-可认为是plus mix, minus, hyphen positive negative 等
- ……
此处考虑常见前三种情况
拆分内容->整合数据
拆分 |
---|
段落拆分为单词 |
单词拆分为字母 |
设置判断器检查字母是否符合构词法 |
整合 |
---|
将段落单词数打印,统计入总数 |
//未优化版
#include<stdio.h>
#include<stdlib.h>
int isPartOfWord( char ch, char *Pre){ //当前字符,指向前驱字符的指针
int Cur_Flag = 1,
general = 0,
number = 0,
other = 0;
//字母判断
general = ( ('a'<=*Pre&&*Pre<='z'||'A'<=*Pre&&*Pre<='Z')
&& (ch =='\''|| ch =='-'|| ch == '\.') )
||( ('a'<=ch && ch<='z'||'A'<= ch&& ch<='Z')
&& (*Pre =='\''|| *Pre =='-'|| *Pre =='\.'))
|| ('a'<=ch&&ch<='z'||'A'<=ch&&ch<='Z');
//数字判断
number = ((*Pre=='\.') && ('0'<= ch&& ch<='9'))
|| (( ch=='\.') && ('0'<=*Pre&&*Pre<='9'))
|| ( '$'==*Pre &&('0'<= ch&& ch<='9'))
|| (( ch=='%') && ('0'<=*Pre&&*Pre<='9'))
|| ( '0'<=ch&&ch<='9');
Cur_Flag = ( general||number||other ); //归总判断
*Pre = ch; //更新前驱指针
return Cur_Flag;
}
//计数器: 返回统计单词数
int Count_words( char *string){
char PreLetter = 0;
int i = 0,
flag = 0,
count = 0;
//解决.98%计数为2个的bug:将光标初始化于数字或者字母位置
while(!(('a'<=string[i]&&string[i]<='z'||'A'<=string[i]&&string[i]<='Z')
||( '0'<=string[i]&&string[i]<='9')) ) i++;
while(1){
if((string[i]!='\n')&&(string[i]!='\0')){
if (isPartOfWord(string[i],&PreLetter)) flag = 0;
else if(flag==0){
flag = 1;
count++ ; //单词数
}//end if
++i;
}//end if
else { //bug:'\0'或'\n'的直接前驱合法字符未被计入,解决:单独处理边界
if(flag==0) {
++count;
++i;
}
break;
}//end else
}//end while
return count;
}
int functional( FILE *fl){
int len = 0,
i = 0,
max = 0,
n = 10000,
count_words_all = 0,
count_words_this_paragraph = 0;
char pre,
str[n];
memset(str,0,n);
while(fgets(str,n,fl)){
count_words_this_paragraph = Count_words(str);
count_words_all += count_words_this_paragraph;
//打印输出每个段落中的单词个数,打印输出段落
printf("count_words_this_paragraph: \t%d\n\n%s\n",count_words_this_paragraph,str);
//寻找最长单词的长度,可以独立为一个函数
for(i = 0; i < n; i++ ){
if(isPartOfWord(str[i],&pre)&&str[i]!='\n') max = ++len>max ? len : max;
else len = 0;
}//end for
printf("---max length :%d\t\n---------------------------------\n",max);
max = 0 ;
memset(str,0,n); //缺失导致for循环遍历无意义内存得到错误答案
}//end while
return count_words_all;
}
int main(){
FILE *fl = fopen( "D:\\Temp\\FileTest\\Words.txt", "r");
printf("\n\ncount_words_all:%d\n",functional(fl));
fclose(fl);
return 0;
}
运行结果
当前已解决bug:
- 合法字符直接后继为换行符或终止符未被计数
- 首字符为.被重复计数
- 内存未初始化导致遍历无意义内存得到错误答案