scanf冷门的格式控制符(%n%[])

一道小题,但能引发思路

汉字统计 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()可以完成的功能又大大加强了如

  1. 可以完成像gets一样的输入scanf(“%[^\n]”),遇到换行才停止。
  2. 从输入的”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;
}

注:此题的测试数据不强,非汉字的字符只有样例中的,便于代码简短,就没有加入其他非汉字字符(在%*[^]中加入即可)。

  • 14
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值