在LinuxC中(gcc编译器)关于输入输出的函数有很多,例如:scanf()、printf()、gets()、puts()、putchar()、getchar()、fscanf()、fprintf()、fgets()、fputs()等等。在这我分享一下我对这些函数的总结。
一、printf()与scanf()
printf()与scanf()被称为格式化输出输入函数。
部分格式化说明符如下:
%d 十进制有符号整数
%ld 十进制有符号长整型数
%u 十进制无符号整数
%f 单精度浮点数
%lf 双精度浮点数
%s 字符串
%c 单个字符
%p 指针的值
%e 指数形式的浮点数
%x, %X 十六进制表示的整数
%#x, %#X 十六进制表示的整数(数字前有0x,0X)
%0 无符号以八进制表示的整数
%g 自动选择合适的表示法
'\n'表示换行符,'\0'表示空字符。
使用这两个函数需要包含stdio.h这个头文件。
(1)printf()的用法为int printf( const char* format , [argument] ... );,format为格式字符串,argument为可选参数。作用是根据指定格式向标准输出设备(屏幕)打印数据。
例如:
int a = 10;
printf ("a = %d\n",a);
格式字符串包括两部分内容,一部分是正常字符,这些字符将按原样输出;另一部分是格式说明符,用来确定输出内容格式。可选参数列表是需求输出的一系列参数, 需要用逗号分隔,且和前面的格式说明符一一对应。
例如:
int a = 10;
float b = 1.2;
char ch = 'A';
printf ("a = %d\nb = %f\nch = %c\n",a,b,ch);
使用时需要注意的是,当输出整型时,可以在%后加上数字以规定所占空间,如果长度超过,则按实际长度输出,如果长度不足,则留下多出空间。在%后加“-”号是让输出结果左对齐,默认是右对齐。在%与数字之间加0表示多出的位置补零。
例如:
int a = 123;
int b = 234;
printf ("%6d%6d\n",a,b);
printf ("%2d%2d\n",a,b);
printf ("%-6d%-6d\n",a,b);
printf ("%06d%06d\n",a,b);
输出浮点型时,可以在%后加浮点数,整数部分表示输出的有效数字位数(包括小数点),小数部分表示小数的位数,长度不足,小数后面补零,长度超过,小数四舍五入输出。
例如:
float a = 1.23;
float b = 123.123456789;
printf ("a = %8.4f\n",a);
printf ("b = %8.4f\n",b);
特别要注意的是,输出字符串时,printf()是从起始地址开始输出,直到碰到空字符,表示字符串结束。所以,在输出字符数组时,若是最后没有空字符,printf()可能会输出乱码。
例如:
char str1[10] = "hello";
char str2[5] = "hello";
printf ("%s\n",str1);
printf ("%s\n",str2);
如果用在%后加浮点数表示字符串或整型的输出格式,小数部分代表最大宽度,整数部分代表最小宽度。
例如:
char str[] = "abcdefg";
printf ("str = %4.6s\n",str);
printf ("str = %8.9s\n",str);
注意可选参数列表的写法,当输出普通变量的值时,不需要加取地址符&,但在输出指针指向的内存的值时,要加取值符*。值得注意的是,如果指针指向一个字符串,或者是输出存放了字符串的数组(有空字符),指针和数组名不需要加取值符*,直到碰到空字符,输出结束。
例如:
char str[10] = "hello";
char *p = str;
printf ("str = %s\n",str);
printf ("p = %s\n",p);
(2)scanf()的用法为int scanf(char *format,[argument]...);,format为格式字符串,argument为可选参数列表,存放着指针。作用是从标准输入设备(键盘)读取数据。
例如:
int a;
scanf ("%d",&a);
printf ("a = %d\n",a);
scanf()是从缓冲区读取数据并存入指定的内存空间,当键入换行符时,scanf()开始按照格式说明符规定的长度(格式)读取数据,当读取到空格符或换行符时,进入下一次读取。
当连续输入时,格式字符串内的格式说明符可以不用分隔,也可以使用逗号或空格分隔,在输入的时候就要对应这个格式去输入,当然,无论怎样,输入时使用回车分隔是可以的。格式字符串后的地址列表需要用逗号分隔,且和前面的格式说明符一一对应。
例如:
int a;
float b;
scanf ("%d%f",&a,&b);
printf ("a = %d\nb = %f\n",a,b);
在使用的时候需要注意的是,使用scanf()连续输入单个字符时,当输入第一个字符,然后敲下回车,scanf()开始从缓冲区读一个字符,这个时候,缓冲区不为空,而是有一个换行符,下一个scanf()会把换行符读入,这样明显就不符合我们的意思,这个时候可以在中间多加一个scanf(),也可以使用其他办法吃掉这个换行符。
例如:
char ch1;
char ch2;
scanf ("%c",&ch1);
scanf ("%c",&ch2);
scanf ("%c",&ch2);
printf ("ch1 = %c\nch2 =%c\n",ch1,ch2);
另外,scanf()在读取字符串时,碰到空格就进入下一次读取,并不会读取空格符,这就导致我们无法用scanf()读取一个带空格的字符串,所以想要输入这样的字符串,需要使用其他的函数,如gets()或fgets(),这我之后会讲到。
同时,输入字符串时,scanf()存在内存溢出的风险,解决这个问题可以换用其他的函数,也可以在%s中间加入一个数字,以限定读取的长度(不包括空字符),之后的就不读取了。
例如:
char str[10];
scanf ("%6s",str);
printf ("%s\n",str);
还有一点很重要,不要在格式字符串内加换行符等符号,这是不合法的。
错误示例:
char str[10];
scanf ("%s\n",str);
注意可选参数列表的写法,当给普通变量赋值时,变量名前要加取地址符&,是要取得对应内存空间的地址。所以,在给数组、字符串、指针指向的内存赋值时,由于数组名、字符串、指针都是地址,所以不用加取地址符。
例如:
char str[10];
char *p = str;
scanf ("%s",p);
printf ("str = %s\n",str);