栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

c语言scanf用法详解

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

c语言scanf用法详解

看了一下glibc scanf的源码之后,对scanf的使用方法有了更深入的理解,下面给大家讲解一下scanf函数的用法.

1.以%开头的字符串
%[argpos$] [I'*] [maximum field width] [type modifiers] [arg]
  1. argpos: 指定了参数的位置
  2. I’*
    • I:use locale’s digits
    • ': Group numbers
    • *: 跳过这个参数
  3. maximum field width : 从输入的内容中最多读取几个字符
  4. type modifiers:
    - hh 写 一个字节
    - h 写两个字节
    - 写四个字节
    - l 写八个字节
    - ll 写八个字节
    - m 有scanf分配缓冲区
  5. arg
    - % 输出%
    - n将前面已经读取的字符个数写到参数指定的位置
    - c 字符
    - C wchar_t
    - s 字符串
    - S wchar_t字符串
    - p 地址
    - x/X 十六进制字符串
    - u/d 无符号/有符号整数
    - e/E/f/F 浮点数
    - [] []内字符以外的字符作为定界符
    - [^] [] 内的字符作为定界符
2.非%开头的字符串

读取一个字符,与之相比较,不同的话scanf失败。

3.演示 3.1 例1
char*p = NULL;
int n = 0;
scanf("Hello%2$10ms%3$n",0,&p,&n);

解析流程:

  1. scanf会从格式串的第一个字符开始遍历,若字符不是%,那么与读入的字符相比较,相同的话,遍历下一个字符。
  2. 当scanf遇到%的时候,之后读取到了2,读取到$后,scanf会把数据保存在第二个参数
  3. 继续解析10 ,这个10的含义就是,从输入的内容中最多读取10个字符。
  4. 解析到m,scanf会自己创建一个缓冲区,把从输入的内容中转换的结果写到这个缓冲区内,最后把缓冲区地址写到参数指定的位置
  5. 解析到s,scanf之后将会读取字符串到指定的buffer内.
  6. 后面的%3 $n同理,scanf会把前面已经读取的字符数写到第三个参数指定的地址处。

接着我们输入 HelloAAAAAAAAAAAA
Hello与格式串中开始位置的Hello相匹配,继续看后面
%2$10ms,最多读取10个字符,并且自己创建缓冲区,把字符串,也就是10个A读到自己创建的缓冲区内,并把地址写到第二个参数指定的位置。
%3 $n ,前面读取了15个字符,所以这里会把15写到第三个参数指定的位置
运行看一下:

再输入内容 Helaaaaaa看一下,匹配成功三个字符,然后第四个失败,scanf结束,最后p 任然是0,n任然为0

3.2 例二
int val = 0;
scanf("Haha%2$10hhd",0,&val);

解析流程:

  1. 匹配Haha
  2. 2$将转换后的结果写到第二个参数指定的位置
  3. 10从输入内容中最多读取10个字符
  4. 只写1个字节

接下来输入内容Haha000000000000000123,由于匹配Haha之后最多读取10个字符,所以最后得到的整数是0。

接着我把这里val的初始值改一下,改为0xabcd,然后输入同样的内容。

最后的val并不是0,为什么呢???
原因是我们这里指定了只写一个字节.所以最后val的值是0xab00,只有低字节发生了变化。

3.3例三
char buffer[256] = {0};
int n = 0;
scanf("Hello%2$10[^abc]%1$n",&n,buffer);

解析流程:

  1. 匹配Hello
  2. 2$将转换结果写到第二个参数指定的位置
  3. 10最多读取10个字符
  4. [^abc],abc这三个字符中的任意一个都是定界符
  5. %1 $n将前面读取的字符个数写到第一个参数指定的位置

接下来输入内容: Hellohhhhhhhhhhhh,匹配Hello之后,最多读取10个字符到第二个参数里面,所以最后buffer里面有10个h,%1 $n,解析到这里时,前面读取了15 个字符,所以会把15写到n里面。

接下来输入 Hellohhhhhh,然后按下回车,我们会发现,什么也没输出。

为什么呢???因为我们指定了定界符为abc,此时的换行符已经不是定界符了,换行符也被读到了buffer里面。
我们继续输入gga,然后回车。scanf会把gg读到buffer里面,然后遇到a,结束。一共读取了 5(Hello) + 6 (hhhhhh) + 1 (n) + 2(gg) = 14个字符

并且我们可以发现,hhhhhh和gg中间是有一个换行符的,说明换行符确实被读进去了。

End

上面这些用法是我在阅读scanf的源码时发现的,(glibc-2.23),msvc上可能有一部分功能是无法使用的,或者某些功能并不是标准里面含有的。有一部分这里没有介绍到,感兴趣的话大家自己实验吧(有些没用过,代码太多,最后懒得看了,毕竟主要是为了找到哪里调用了malloc来触发malloc_hook)

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/873160.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号