printf和scanf整理(后续填补)

scanf和printf头文件:<stdio.h>  1.%d、%3d、%03d、%-3d区分

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

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

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

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

 1 #include<stdio.h> 2 int main() 3 { 4  5     int a = 23, b = 123, c = 1234; 6     printf("%d %d %d\n", a, b, c); 7     printf("%3d\n%3d\n%3d\n", a, b, c); 8     printf("%03d\n%03d\n%03d\n", a, b, c); 9     printf("%-3d\n%-3d\n%-3d\n", a, b, c);10     return 0;11 }

   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的字符串,因为最后一个位置要存储空字符)可能会导致溢出或对程序之后的输入造成影响。

      

      (图 dev-C++编译)

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

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

 1 #include<stdio.h> 2 int main() 3 { 4     char b[10] = { '\0' }; 5     scanf_s("%s", b,10); 6     int n; 7     scanf_s("%d",&n); 8     printf("b=%s\nn=%d\n", b, n); 9     printf("b[9]=%c\n", b[9]);10     return 0;11 }

执行情况:

    图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数组则会出错)。

通电话,旅行,重复一个承诺和梦想,

printf和scanf整理(后续填补)

相关文章:

你感兴趣的文章:

标签云: