3.2数据的格式化键盘输入

数据的格式化键盘输入

如何按照指定格式从键盘输入指定类型的数据?
C语言提供用于按照指定的格式用于键盘输入数据的函数就是Scanf函数,和Printf函数类似的是,scanf也要求有一个格式控制字符串,在格式控制字符串中,指定输入数据的格式,scanf格式控制字符串也是用一对双引号,引起来的字符串,在这个格式控制字符串中,格式转化说明符也是由一个%开头,并以一个格式字符结束的。例如%d就是指定数据输入格式为10进制整型格式,而%f就是指定输入数据的格式为小数形式,与Printf不同的是,scanf函数,要求后面的参数表,不是一个输出值表,而是一个输入地址表,也就是说,这个参数地址表,它是由若干个变量的地址构成的一个参数表,在这个输入地址表中,指定了用于接收数据的变量的地址,当然这个输入地址表也是可变长度的,也就是在这个地址表中,给定的参数个数,可以是任意的。在C语言中,&这个符号有着特殊的含义,它代表这是,取地址运算符,之所以,要在这个参数表中指定,变量的地址,就是为了告诉编译器,用户从键盘输入的数据,应该保存到哪里?
在这里插入图片描述举例
这程序中,表示按照十进制整型格式来输入两个整型变量的值,而这条语句是将a和b的值,按照指定的格式输出到屏幕上。
假设我们从键盘上输入的是12和34,中间以空格作为分隔符,在用户输入完12 34之后,在按一个回车键之后,那么屏幕就会输出a=12,b=34.
下面我们来运行下这个程序。
如果我们将取地址运算符去掉的话,也就是假设我们使用scanf的时候,忘记使用取地址运算符,那么结果会怎么样呢?程序会异常终止,弹出这样的一个对话框。要求,用户结束这个程序的执行。我们选择关闭这个程序,那么这个程序也就被杀死了。那么对于初学这来说,在使用scanf的时候,忘记使用取地址运算符,是经常容易犯的错误。好的编译器,会在程序编译的时候,给出警告信息、就是提示,变量a与b,没有被初始化,为什么会提示这样的信息呢?因为在C语言中,给出变量的名字,就相当于给出变量的名字来访问变量的值,而在这里,a与b的值,还没有被赋值,我们就来访问a和b的值,当然在程序编译的时候,就会提示,这两个变量的值没有被初始化。
在这里插入图片描述如果我们将这条语句中的格式字符写错了,那么结果会怎么样呢?比如我们写成了%f,也就是说,指定的格式字符,与要输入的变量的类型,不匹配,那么这个时候,会发生什么情况呢?这样scanf,就会读入错误的数据
在这里插入图片描述运行程序,输入的是一堆乱码,这就表明程序,没有正确读入,用户从键盘输入的数据。因为指定的格式字符与要输入的变量的类型是不匹配的。
如果用户要输入多个数据,那么我们应该以什么样的风格符来输入用户从键盘输入的数据呢?
假设多个格式字符之间是没有其他任何字符的,那么这个时候,我们通常以tab,回车,空格,作为输入数据的分隔符,但是如果我们指定了输入数据的位宽,那么在达到输入位宽的时候,系统也认为输入数据结束了,在有就是,当遇到非法字符的时候,系统也会认为输入数据结束,在以上这三种情况下,系统都会认为一个输入数据结束。
在这里插入图片描述刚才的例子,两个字符之间是以空格作为格式分隔符的,那么这个时候在输入数据的时候,用户就可以以空格符作为输入数据的分隔符,这样a得到的值就为12, d得到的值就是34,
在这里插入图片描述同理我们还可以tab键来作为格式的分隔符,但是如果我们将,格式字符分解为%2d,这个时候输入数据,我们就可以不用任何分隔符,直接输入1234,这个时候,系统会按照指定的位宽2,来从输入的数据中截取相应的数据,赋值给a。也就是将12的值给a,32的值给b。
在这里插入图片描述如果我们输入的数据是123456,同样它会截取2个位宽给a,2个位宽给b。那么多余的数据,仍然保留在输入缓冲区中的。
在这里插入图片描述会得到12 3
这是因为在输入数据的时候,12赋值给了a,但是在读到3a的时候,因为a是一个非数值的字符,系统在遇到非法字符的时候就认为,输入数据结束了,因此,b得到的值就是3.
在这里插入图片描述b是乱码,不同编译器,得到b的值不同,
在这里插入图片描述虽然我们没有用到scanf的返回值,但是它还是会有返回值的。
在这里插入图片描述这里我们要读入了2个数据,就可以判断,这个函数的返回值是否等于2?
如它的值等于2,那么就说明,scanf,正确的读入了输入的数据项数,假设我们输入的是123a的话,那么这个函数的返回值,就是1,而不是2.就说明,它正确的读入了一个数据,而没有读入2个数据。因此,通过判断scanf的返回值,是否等于我们希望读入的数据的项数,就可以知道scanf函数是否调用成功?需要用到条件语句。而条件语句,将在后面的语句中介绍。
如果我们在scanf()的格式控制字符串中,假如一个普通的字符逗号。也就是在这两个格式字符之间,加上一个逗号的话,那么应该如何来输入数据呢?和printf中的格式控制字符串原样输出一样,scanf函数格式控制字符串中的普通字符也要原样输入,因此在用户从键盘输入数据的时候,应该以逗号作为分隔符。运行程序,输入12,34 。这个时候就用逗号作为分隔符。
在这里插入图片描述如果我们将,格式控制字符串改成是这种形式,那么同理a=%d逗号b=%d 它也是普通字符,也是需要原样输入的,因此用户在从键盘输入数据的时候就应该输入a=12逗号b等于34
在这里插入图片描述在这里插入图片描述用c格式符,用来输入一个字符型数据的,这里需要注意的是,用c格式符来输入字符型数据的时候,空白符,tab与空格都作为有效输入。而用f输入数据的时候,可以指定输入数据的位宽,但是不能指定输入数据的精度。也就是说,如果我们用这种方式来输入数据的话,就是错误的。见图片常见错误。我们可以指定输入数据的位宽是7,但是我们不能指定输入数据有两位小数。这一点是和printf不同的。
在这里插入图片描述用Pintf输出数据的时候,可以指出输出数据的精度,但是用scanf,输入数据的时候,是不可以指定输入数据的精度。
除了这个常见错误,还有两个
一个忘记取地址运算符
用scanf输入数据的时候,在格式控制字符串,出现了换行符,这三种错误。
在这里插入图片描述
在这里插入图片描述在这里插入图片描述这是为什么呢?调用scanf函数时,输入数据的时候,我们需要输入的数据保存的地址,通过地址来指向变量的,就是必须给出变量的地址,因为不同类型的变量在内存中占据的存储空间的大小时不同的,例如单精度实型,在内存中是占4个字节,而双精度实型在内存中是占八个字节的。从这个起始地址,是用四个字节来保存这个输入数据呢?还是用八个字节来保存这个输入数据呢?
这个就是由格式字符来告诉编译器的,如果,我们写的格式字符是f的话,那么它这个就是告诉编译器,从这个地址,的四个字节,是用于保存一个单精度实型的数据的,如果是Lf的话那么它告诉编译器,就是从这个地址开始就是从八个字节开始用来保存双精度实型的数据的,因此在一个scanf函数输入数据的时候,仅仅给出变量的地址,是不够的,还必须告诉编译器,从这个地址开始的几个字节是用于保存这个数据的,那么这个工作就是由格式字符来告诉编译器的。换句话说,scanf是通过f或者Lf来区分保存的数据是一个单精度实型的,还是一个双精度实型的,也就是需要一个四个字节的还是需要一个八个字节的存储空间来保存这个数据,但是用Printf来输出数据的时候,编译器它会自动将单精度实型的数据,自动转换为双精度实型的数据,这样的话printf就没发区分单精度与双精度,因为单精度实型也被转化为了双精度实型,正因如此,printf在输出实型的时候,是不区分单双精度实型的。因此,只要用%f,就可以输出这两种类型的数据了。
在这里插入图片描述*表示一个抑制字符,输入项在读入以后,不赋给相应的变量。或者说是跳过这个输入项。举例
%*2d 跳过输入项,不赋值给任何变量。

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值