一道小题,但能引发思路
汉字统计 HDU-2030 统计给定文本文件中汉字的个数。
Input
输入文件首先包含一个整数n,表示测试实例的个数,然后是n段文本。
Output
对于每一段文本,输出其中的汉字的个数,每个测试实例的输出占一行。
Hint:从汉字机内码的特点考虑~
Sample Input
2
WaHaHa! WaHaHa! 今年过节不说话要说只说普通话WaHaHa! WaHaHa!
马上就要期末考试了Are you ready?
Sample Output
14
9
特殊说明:此题的判题环境汉字占两个字节。
这是昨天见到的一到很简单的题,此题跟输入有很大的关系,就试着想用scanf来完成此题。于此分享一下scanf那些很少常用但很强大的格式控制符。
字符集[] 与 %n 格式控制符的使用:
%[] 一个字符集
如果scanf()遇到一个字符集, 那么在括号中的任意字符都会读取到变量中。遇到不在括号中的字符会停止输入。
如%[0-9]表示只读入’0’到’9’之间的字符,%[a-zA-Z]表示只读入字母( - 是范围连接符)遇到其他字符会停止若字符集中有抑制符^,含义是相反的意思,即在括号中的会停止输入,不在的会读入。
如%[^0-9]表示读入任意多的字符,读入’0’到’9’之间的字符会停止,%[^=]表示读入任意多的字符,直到遇到”=”停止。%n 一个等于读取字符数量的整数
%n输出的是截止到%n之前的有效字符数量,在scanf和printf中都可使用。与%n相对应的形参是一个int类型的指针,%n不影响scanf和printf的返回值,如:
scanf(“%d %d%n”, &i, &j, &k);
如果输入123空格空格4567,则k等于9,因为这9个字符都成功输入而scanf的返回值仍然为2.
scanf(“%c%n%c”, &ch1, &k,&ch2);
输入“sbcdefdg”后,k等于1,scanf的返回值仍然为2.同理%n用在printf函数里,表示也是输出的字符数量。若放到最后则与printf()的返回值相同,如:
printf(“a=%d, b=%d\n%n”, i, j, &k);
在a=123,b=456的情况下,k=12,同时%n不影响printf的返回值,其返回值仍然为12,而不是14。
顺提一下:scanf()的返回值是成功赋值的数量,而printf()的返回值是成功打印字符的数量。
由此根据这两个在组合上其他的控制符,scanf()可以完成的功能又大大加强了如
- 可以完成像gets一样的输入scanf(“%[^\n]”),遇到换行才停止。
- 从输入的”765mo885tian195”中只读取整形赋给n,则可有如下方法:
#include <stdio.h>
int main(){
int n;
while(scanf("%*[^0-9]"),scanf("%d",&n)!=EOF)
printf("n=%d\n", n);
}
我们再次回到开始的那道题,博主是这么解决的
#include<stdio.h>
int main(int argc,char *argv[]){
int n,len,sum;
scanf("%d%*c",&n);//除去多余的\n符
while(sum=len=0,n--){//每组数据读入之前初始化数据
while(len=0,1){//每次初始化len,防止重复计算
scanf("%*[^0-9a-zA-Z ?!\n]%n",&len);//只读入汉字,读到的字符存入len中
sum+=len;//加上每节的汉字字符数
if(getchar()=='\n') break;//遇到\n说明输入完成
}
printf("%d\n",sum/2);
}
return 0;
}
注:此题的测试数据不强,非汉字的字符只有样例中的,便于代码简短,就没有加入其他非汉字字符(在%*[^]中加入即可)。