C语言scanf函数奇遇记

作者:ocean    撰写日期:2011-11-20

博客链接:http://oceanspace.tk

看《The C Programming Language》中关于scanf函数部分时随意敲了几行代码,本以为简单的不得了,都有点“不屑于”敲,却没想到这一敲竟然敲出个不小的问题,涉及到好多东西啊,哈哈!下面把我这次的经历和大家分享一下,希望也能对大家有所帮助。

一、代码实例

我当时敲的代码:

#include<stdio.h>

int main()

{

int a;

int b;

char mon[20];

int count;

 count = scanf("%d,%s,%d", &a,mon,&b);

 printf("%d,%s,%d\n",a,mon,b);

 printf("%d\n",count);

return 0;

}

运行结果:

ocean@ocean-desktop:~/桌面$ ./re

12,fefe,45   /*这是我的输入*/

12,fefe,45,10359588

2

结果看起来挺像我们想要的结果的,只是最后多了个奇怪的数字;但仔细看下count的值我们就纳闷了,怎么是2不是3呢?怎么scanf只读了两个值?到底怎么回事呢?先用gdb调试一下吧,看看a和mon里都是些什么。

二、GDB调试情况

(gdb) p a

$1 = 12

(gdb) p mon

$2 = "fe,45\000\377\277\245\324\025\000\060\340\021\000K\205\004\b"

明白了吧?原来fe,45作为一个整体被存到mon里了,b根本没读到值,显示了个原内存里的乱七八糟的数值(不相信的话可以在程序开头给b赋个值,最后结果肯定是输出当初赋的值,因为根本没有给b读入新的值),scanf真的只读了两个值,所以count显示2。那为什么会这样呢?让我们来看看scanf函数的相关信息吧。

三、scanf函数工作原理

scanf()是从输入流缓冲区中读取值的,而并非从键盘(也就是终端)缓冲区读取。往输入流缓冲区送数据是遇到回车(\n)而结束的,这个\n会一起读入输入流缓冲区。scanf() 开始读取输入以后,会在遇到的第一个空白字符空格(blank)、制表符(tab)或者换行符(newline)处停止读取。

格式控制字符串中有普通字符(非格式字符)时,这些字符作为输入数据的分隔符,在scanf函数读入数据时自动去掉。

scanf()格式控制字符串中如果使用%s说明符,那么空白字符以外的所有字符都是可以接受的,所以scanf() 跳过空白字符直到遇到第一个非空白字符,然后保存再次遇到空白字符之前的所有非空白字符。这就意味着%s使scanf() 读取一个单词,也就是说,一个不包含空白字符的字符串。

好,让我们分析下上述的结果是如何出现的吧。

四、原因分析

首先,scanf()跳过空白字符(这里没有,因为第一个字符就是1)直到遇到一个非空白字符1,然后继续读2,读到逗号这个非数字符号时scanf知道整数读完了,将12赋给a,此时输入流缓冲区中第一个开头的字符是逗号;scanf继续读,读到逗号与格式控制字符串的逗号匹配,pass;从f继续读,一直读到下一个空白符——我们结束时敲的回车(scanf自动把这个回车符去掉了,没有送到字符串里),字符串读完了,此时输入流缓冲区里第一个开头的字符是我们敲的回车符;继续读,回车符与格式控制字符串里的逗号不批配,读取失败,不读了。   综上所述,scanf确实只读了一个整数和一个字符串,返回值是2。

那有什么办法实现用逗号作为间隔符的情况呢?下面提供两种方法:

五、解决方法

1:

scanf("%d,%[^,],%d", &a,mon,&b);

printf("%d,%s,%d\n",a,mon,b);

相关知识:scanf中一种很少见但很有用的转换字符:[...]和[ ^...]

%[...]如果输入的字符属于方括号内字 符串中某个字符,那么就提取该字符;如果一经发现不属于就结束提取。%[^...]如果一经发现输入的字符属于方括号内字符串中某个字符,那么就结束提取;如果不属于就提取该字符。这两种方法会自动加上一个字符串结束符到已经提取的字符后面。例如:

#include<stdio.h>

main()

{

char strings[100];

scanf("%[1234567890]",strings);

printf("%s",strings);

return  0;

}

运行,输入:1234werew后,结果是:1234。

采用这种方法,读完fefe后遇到逗号便结束字符串的读取,继续读时输入流缓冲区的逗号与格式控制字符串中逗号刚好匹配,成功!

2(不够彻底):

scanf("%d,%s ,%d", &a,mon,&b);   /*注意%s后面有个空格 */

printf("%d,%s,%d\n",a,mon,b);

并且在输入时加个空格

12,fefe ,45   /*fefe和逗号之间加个空白*/

相关知识:当scanf()格式控制字符串中出现空白时,表示取数时跳过任何空白。

scanf读到fefe后的空格后结束字符串的读取,此时输入流缓冲区第一个字符为空格;继续读,由于格式控制字符串里有个空格,所以读取时会跳过任何空白(不信可以在fefe后面多敲几个空白试试,全都跳过,甚至连回车都跳过),读到逗号匹配成功。

转载于:https://www.cnblogs.com/happyblog/archive/2012/03/15/2398187.html

C语言scanf函数奇遇记相关推荐

  1. c语言添加输入函数吗,C语言scanf()函数下支持中文输入吗?

    C语言scanf()函数下支持中文输入吗? C语言scanf()函数下支持中文输入吗? 如果我编写一个程序,要求是先输入姓,再输入名,然后按照常姓名的方式排列出来,如果我需要输入中文该怎么办? 搜索更 ...

  2. C语言scanf()函数的返回值

    C语言scanf()函数的返回值 代码例子: #include<stdio.h> int main(){int num1=0,num2=0;int value= scanf("% ...

  3. c语言scanf函数计算乘积,C语言Scanf函数

    C语言的scanf函数 一.变量的内存分析 (一)字节与地址 ①. 内存以字节为单位 每个字节都有自己的内存地址,根据地址就可以找到该字节.整个内存相当于一整个酒店,而酒店以房间为单位,在这里每个房间 ...

  4. c语言scanf函数作用,C语言scanf函数应用问题解答

    C语言scanf函数应用问题解答 C语言的输入是由系统提供的库函数完成的.scanf函数是C语言中最常用且功能最强的输入函数,但该函数如使用不慎,就会出现错误或得不到预想的结果.以下结果都是基于VC+ ...

  5. C语言scanf函数

    C语言scanf函数 函数名:scanf 功能:实现格式化输入 格式:scanf("<格式化字符串>",地址表) scanf函数是通用终端格式化输入函数,它从标准设备键 ...

  6. C语言 | scanf函数

    C语言使用scanf输入一个数 #include<stdio.h>//头文件 int main()//主函数 程序的入口 {int num;printf("请输入一个数:&quo ...

  7. C语言scanf函数详解

    函数名: scanf  功 能: 运行格式化输入  用 法: int scanf(char *format[,argument,...]); scanf()函数是通用终端格式化输入函数,它从标准输入设 ...

  8. C语言scanf函数详解和示例

    文章目录 一.数据输入 二.断章取义 三.scanf输入 1.输入整数 2.输入字符 3.输入浮点数 4.输入字符串 5.输入多个内容 6.示例(book13.c) 四.注意事项 五.获取视频教程 六 ...

  9. C语言scanf函数用法详细解释!!!

    函数名: scanf  功 能: 执行格式化输入  用 法: int scanf(char *format[,argument,...]); scanf()函数是通用终端格式化输入函数,它从标准输入设 ...

最新文章

  1. FTP在aliyun上使用经验
  2. java基础----IO序列化Serializable
  3. 在创建表时,对于auto_now=True与 auto_now_add=True 的区别
  4. Angular 快速入门
  5. 【教程】PDF控件Spire.PDF 教程:在C#中检测PDF文件是否为PDF/A
  6. 概率论与数理统计——常用结论
  7. 教你用迅雷下载百度网盘的文件
  8. 产品经理,原型设计之前你要做些什么?
  9. 300etf期权怎么玩?正规平台有哪些呢?
  10. 数据库编程需要下载什么软件
  11. 如何应对云安全技术遇到的挑战?可从这三点入手
  12. 1256:献给阿尔吉侬的花束
  13. 边缘设备、系统及计算杂谈(2)——go语言
  14. 2019.10.8 多校赛Day1【including 流量,个人练习生,假摔
  15. 改善Unity编辑器对Lua文件的支持
  16. win10电脑怎么操作让动态盘转成基本盘?
  17. java 循环依赖_浅谈Spring解决循环依赖的三种方式
  18. JavaScript 中的模块化
  19. “我辞退了一位学位学历造假的程序员”
  20. Unity VUFORIA 推荐设备

热门文章

  1. LeetCode 1297. 子串的最大出现次数
  2. LeetCode 187. 重复的DNA序列(哈希/位运算)
  3. LeetCode 801. 使序列递增的最小交换次数(动态规划)
  4. LintCode 563. 背包问题 V(DP)
  5. LeetCode 1042. 不邻接植花(图的数据结构)
  6. LeetCode 29. 两数相除(位运算)
  7. LeetCode 784. 字母大小写全排列(位运算回溯)
  8. LeetCode 559. N叉树的最大深度
  9. arcgis 属性表 汇总_ArcGIS实践教程(19)ArcGIS/ArcMap中属性表的合并方法
  10. wltc循环多少公里_原来所有车都烧机油!但是烧多少才算正常你知道吗?