一、printf
控制符
- ①精度控制:输入小数点后m位(%.mf)。右对齐5位,保留小数点后m位(%d.mf)%f、%lf默认输出6位小数
- ②宽度:%md(打印m为,右对齐,多出m位照常打印)。%-md(打印m位,左对齐,多出m位照常打印)
- ③长度:h表示短(打印短整型short:%hd),l表示长(打印长整型long:%ld)
- ④标记(#:%#0输出八进制,%#x输出十六进制)(0:对齐中空白处用0补齐(%010d))
自己控制输出位
- printf("%*d",3,2); //打印2,向右对齐3位
- printf("%-*d",3,2); //打印2,向左对齐3位
返回值
- 输出正确:返回打印的字符串的长度(包括空白符、换行符等)
- 输出出错:返回负数(如果不用变量接收错误的printf,程序就会出错。如果用变量去接收错误printf,程序就不会出错)
你以为你输出了helloworld就掌握了printf,来,我接着带你重新认识printf,我这个人比较爱刚代码,来看第一个代码:
#include <stdio.h>
int main(){
char a = 'a';
int b = 2;
printf("%d\n",a,b = b+1);
printf("b is: %d\n",b);
return 0;
}
首先不要惊讶这个代码怎么会这么写,第五行是不是少写了个%d, 你认为输出是什么:是’a‘对应的整型数值 97呢还是数值2?
实际上从printf的使用情况来看,我们不难发现一个规律,就是无论其可变的参数有多少个,printf的第一个参数总是一个字符串。
而正是这第一个参数,使得它可以确认后面还有有多少个参数尾随。
而尾随的每个参数占用的栈空间大小又是通过第一个格式字符串确定的。
然而printf到底是怎样取第一个参数后面的可变的参数值的呢, 实际上可变参数函数的实现与函数调用的栈结构有关,正常情况下c/c++的函数参数入栈规则为__stdcall, 它是从右到左的,即函数中的最右边的参数最先入栈。
所以,你觉得你真的掌握了printf函数吗?
二、scanf
- scanf()函数是通用终端格式化输入函数,它从标准输入设备(键盘) 读取输入的信息。可以读入任何固有类型的数据并自动把数值变换成适当的机内格式。
- 其调用格式为: scanf("<格式化字符串>",<地址表>);
- scanf()函数返回成功赋值的数据项数,出错时则返回EOF。
- 其控制串由三类字符构成:
- 1。格式化说明符;
2。空白符;
3。非空白符; - (A) 格式化说明符
- 格式字符 说明
- %a 读入一个浮点值(仅C99有效)
%A 同上
%c 读入一个字符
%d 读入十进制整数
%i 读入十进制,八进制,十六进制整数
%o 读入八进制整数
%x 读入十六进制整数
%X 同上
%c 读入一个字符
%s 读入一个字符串
%f 读入一个浮点数
%F 同上
%e 同上
%E 同上
%g 同上
%G 同上
%p 读入一个指针
%u 读入一个无符号十进制整数
%n 至此已读入值的等价字符数
%[] 扫描字符集合
%% 读%符号
附加格式说明字符表 - 修饰符 说明
- L/l 长度修饰符 输入"长"数据
h 长度修饰符 输入"短"数据
W 整型常数 指定输入数据所占宽度
* 星号 空读一个数据
hh,ll同上h,l但仅对C99有效。 - 如果你认为就这么简单的一个输入函数匆匆了事,那你可能会写出bug,不信你看如下代码:
#include <stdio.h>
int main()
{
int a;
printf( "input the data\n ");
scanf( "%d\n ",&a);//这里多了一个回车符/n
printf( "%d ",a);
return 0;
}
结果要输入两个数程序才结束,而不是预期的一个。why?
原因:用空白符结尾时,scanf会跳过空白符去读下一个字符,所以你必须再输入一个数。这里的空白符包括
空格,制表符,换行符,回车符和换页符。所以如果你用scanf( "%d ",&a)也会出现同样的问题。
解决方法:这种错误大多是输入的时候不小心,多注意一点就好了。这种问题也不好检查,编译没有问题