羽夏闲谈——C的scanf的高级用法

博客 分享
0 360
优雅殿下
优雅殿下 2022-02-10 10:55:10
悬赏:0 积分 收藏

羽夏闲谈—— C 的 scanf 的高级用法

羽夏闲谈之 scanf 的高级用法,详细介绍该函数的高级用法。

前言

??今天看到博友发了个有关scanf的使用的注意事项,就是讨论缓冲区残存数据的问题,用简单的代码示例复述一下:

#define _CRT_SECURE_NO_WARNINGS#include <stdlib.h>#include <stdio.h>int main(int argc, char *argv[]){    int a;    char b;    scanf("%d", &a);    scanf("%c", &b);    printf("a = %d , b = %d\n", a, b);    system("pause");    return 0;}

??你或许碰到这个输出:

5a = 5 , b = 10请按任意键继续. . .

??我明明想输入个5,然后回车输入下一个字符,但是,回车符也是个字符,会被scanf进去,绝大多数人的解决方案就是提前把这个字符读取走,但是如果缓冲区的东西太多的话,需要加个循环,才能处理,下面我来介绍scanf的高级用法,之间研究过,忘记在哪里看到的,这个是我总结的,那些基础用法自己看看书就行了。

清空缓存区

??我先把清空缓冲区的代码放上,因为后面的代码都会用到,至于为什么后面会有详细介绍:

scanf("%*[^\n]"); //清除到回车符的所有字符scanf("%*c");  //清除回车符

指定输入长度

??我们都知道scanf可以指定小数位数和长度,如下是代码示例:

#define _CRT_SECURE_NO_WARNINGS#include <stdlib.h>#include <stdio.h>int main(int argc, char *argv[]){    int n;    float f;    char str1[23];    scanf("%2d", &n);    //清空缓冲区代码{    scanf("%*[^\n]");    scanf("%*c");    //}    scanf("%5f", &f);    //清空缓冲区代码{    scanf("%*[^\n]");    scanf("%*c");    //}    scanf("%5s", str1);    puts("执行后:");    printf("n=%d, f=%g, str=%s\n", n, f, str1);        system("pause");    return 0;}

??如下是输入和输出结果:

5653 122.56458452 2356.9999helloworld执行后:n=56, f=2.564, str=hello请按任意键继续. . .

??看到没,清空缓冲区的代码有效果了,如果没有这行清空缓冲区的代码,就会成这样子:

5653 12执行后:n=56, f=53, str=12请按任意键继续. . .

??这就是清除缓冲区的作用。

单范围匹配

??不要惊讶,scanf也是支持类似正则表达式的功能的,我们用如下代码进行演示:

#define _CRT_SECURE_NO_WARNINGS#include <stdlib.h>#include <stdio.h>int main(int argc, char *argv[]){    char str2[30];    scanf("%[abcd]", str2); //%[abcd]表示只要字符串只有 a,b,c,d 范围内就匹配    puts("执行后:");    printf("%s\n", str2);    system("pause");    return 0;}

??如下是输入和输出结果:

babccbaxyz执行后:babccba请按任意键继续. . .

??代码中的注释可能说的不明白,这里我长篇大论一下:字符串从开头开始匹配,必须字符串只有abcd中这四个字符任意一个才有效,如果开头没有这四个字符,则匹配为空。

多范围匹配

??既然支持单范围了,肯定也支持多范围,什么是多范围匹配可以先看看一些基础示例,如果会正则表达式的话很容易懂:

  • %[a-z]表示读取 abc...xyz 范围内的字符,也即小写字母;
  • %[A-Z]表示读取 ABC...XYZ 范围内的字符,也即大写字母;
  • %[0-9]表示读取 012...789 范围内的字符,也即十进制数字;
  • %[a-zA-Z]表示读取大写字母和小写字母,也即所有英文字母;
  • %[a-z-A-Z0-9]表示读取所有的英文字母和十进制数字;
  • %[0-9a-f]表示读取十六进制数字

??如果经常使用的话也就这些类型,如下是代码示例:

#define _CRT_SECURE_NO_WARNINGS#include <stdlib.h>#include <stdio.h>int main(int argc, char *argv[]){    char str3[30];    scanf("%[a-zA-Z]", str3); //只读取字母    puts("执行后:");    printf("%s\n", str3);    system("pause");    return 0;}

??如下是输入和输出结果:

abcXYZ123abcXYZ123执行后:abcXYZ请按任意键继续. . .

不匹配某些字符

??既然有匹配的字符,肯定有不想匹配的字符。对于不匹配某些字符,scanf允许我们在%[ ]中直接指定某些不能匹配的字符,具体方法就是在不匹配的字符前面加上^,给几个例子:

  • %[^\n]表示匹配除换行符以外的所有字符,遇到换行符就停止读取;
  • %[^0-9]表示匹配除十进制数字以外的所有字符,遇到十进制数字就停止读取。

??如下是代码示例:

#define _CRT_SECURE_NO_WARNINGS#include <stdlib.h>#include <stdio.h>int main(int argc, char *argv[]){     char str11[30], str12[30];    scanf("%[^0-9]", str11);    scanf("%*[^\n]");    scanf("%*c");           //清空缓冲区        scanf("%[^\n]", str12); //等效为gets()    puts("执行后:");    printf("str1=%s \nstr2=%s\n", str11, str12);    system("pause");    return 0;}

??如下是输入和输出结果:

abcXYZ@#87edfCnblog wingsummer执行后:str1=abcXYZ@#str2=Cnblog wingsummer请按任意键继续. . .

丢弃数据

??scanf还允许把读取到的数据直接丢弃,不往变量中存放,具体方法就是在%后面加一个*,如下是代码示例:

#define _CRT_SECURE_NO_WARNINGS#include <stdlib.h>#include <stdio.h>int main(int argc, char *argv[]){    int nn;    char str[30];    scanf("%*d %d", &nn);    scanf("%*[a-z]");    scanf("%[^\n]", str);    puts("执行后:");    printf("n=%d, str=%s\n", nn, str);    system("pause");    return 0;}

??如下是输入和输出结果:

100 999abcxyzABCXYZ执行后:n=999, str=ABCXYZ请按任意键继续. . .
知识共享许可协议
知识共享许可协议
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可
本文来自博客园,作者:寂静的羽夏 ,一个热爱计算机技术的菜鸟
转载请注明原文链接:https://www.cnblogs.com/wingsummer/p/15878000.html
posted @ 2022-02-10 10:15 寂静的羽夏 阅读(16) 评论(2) 编辑 收藏 举报
回帖
    优雅殿下

    优雅殿下 (王者 段位)

    2018 积分 (2)粉丝 (47)源码

    小小码农,大大世界

     

    温馨提示

    亦奇源码

    最新会员