printf和scanf整理(后续填补)

scanf和printf头文件:<stdio.h>

  1.%d、%3d、%03d、%-3d区分

%d:以十进制形式输出整数(int)

%3d:指定宽度为3,不足的左边补空格

%03d:一种左边补0 的等宽格式,比如数字12,%03d出来就是: 012

%-3d:左对齐,不足三位右边用空格填补

 #include<stdio.h>
int main()
{ int a = , b = , c = ;
printf("%d %d %d\n", a, b, c);
printf("%3d\n%3d\n%3d\n", a, b, c);
printf("%03d\n%03d\n%03d\n", a, b, c);
printf("%-3d\n%-3d\n%-3d\n", a, b, c);
return ;
}

   2.scanf和scanf_s的区别

    ①一般情况下,两者可互相代替:有个int型变量a,于是有scanf("%d",&a)等价于scanf_s("%d",&a)

    ②scanf_s并非是标准库的函数,而是VS中用以确保数据不会溢出。

      比如,有个char  b[10]的字符数组,一般下用scanf("%s",b),但是如果输入时的字符串长度超过9呢?(大小为10的字符数组最多存储长度为9的字符串,因为最后一个位置要存储空字符)可能会导致溢出或对程序之后的输入造成影响。

      printf和scanf整理(后续填补)

      (图  dev-C++编译)

      可见,scanf可能会造成内存泄漏,尽管可能上图这种情况下能正确执行(和编译器对代码检查严格是否有关),但是的的确确会有逻辑错误(数组b的元素最大下标是9,而这里b[10]竟然能够成立),而这对于程序员而言是不允许的。

      如果换成在VS 2015 IDE中编译(上面这个程序不在VS中执行,是因为scanf函数在VS中会报错,除非对编译环境进行修改(本萌并没有试过~)),采用scanf_s函数如下:

 #include<stdio.h>
int main()
{
char b[] = { '\0' };
scanf_s("%s", b,);
int n;
scanf_s("%d",&n);
printf("b=%s\nn=%d\n", b, n);
printf("b[9]=%c\n", b[]);
return ;
}

执行情况:

printf和scanf整理(后续填补)     printf和scanf整理(后续填补)     printf和scanf整理(后续填补)

    图1:由于输入的字符串长度超过9,并且大于10,以至于读入b数组出错,经过调试会发现,此时b中第一个为ASCII码为0的空字符,之后9个竟然是ASCII值为-2的'?'。b数组输入结束后,由于输入流此时还有数据,缓冲不为空,以至于给整型n赋值时直接从输入流中读取剩下的数字(注意,此时存入n为数字,而不是字符)。

    图2:当刚好输入10个字符时,由于b数组只能存长度为9的字符串,仍然出错。但是此时输入流缓冲为空,所以能继续输入数据,赋值给b。

    图3:当输入的字符串长度小于等于9时,则是正常输入情形。由于b[9]为空字符,而空字符并不能显示输出,就有图3的结果。

    ③scanf_s用法:当不是输入字符串时,和scanf格式相同;当输入字符串时,必须要在最后指出最大读入的字符个数(注意,不是字符串长度,读者可以尝试将上个代码中的10改为9,然后采用图3的输入数据,b数组则会出错)。

上一篇:【紫书】Trees on the level UVA - 122 动态建树及bfs


下一篇:CSS自定义字体的实现,前端实现字体压缩