针对scanf/sscanf/fscanf和printf/sprintf/fprintf进行详细讲解,以及两组函数的对比
int scanf( const char* format [,argument]… );(一种格式化的输入函数)
解释:
format是C字符串(可以是一个变量),包含了以下各项中的一个或多个
其形式为:"%[*][width(宽度)][length(类型长度)][type]“
参数 | 作用说明 |
---|---|
* | 这是一个可选星号,表示数据是从流stream中读取的,但是可以被忽视,即它不存储在对应的参数中 |
width | 指定了在当前读取操作中读取的最大字符数 |
length | h :短整型或无符号短整型 l :长整型或无符号长整型或双精度型 L :长双精度型 |
type | 一个字符,指定了要被读取的数据类型以及数据读取方式。具体参见下一个表格 |
占位符 | 输入说明 | 对应类型 |
---|---|---|
%c | 单个字符:读取下一个字符。如果指定了一个不为 1 的宽度 width,函数会读取 width 个字符,并通过参数传递,把它们存储在数组中连续位置。在末尾不会追加空字符。 | char * |
%d | 十进制整数:数字前面的 + 或 - 号是可选的 | int * |
%e、%E、%f、%F、%g、%G | 浮点数:包含了一个小数点、一个可选的前置符号 + 或 -、一个可选的后置字符 e 或 E,以及一个十进制数字。两个有效的实例 -732.103 和 7.12e4 | float * |
%i | 读入十进制,八进制,十六进制整数:数字前面的 + 或 - 号是可选的 | int * |
%o | 八进制整数:数字前面的 + 或 - 号是可选的 | int * |
%s | 字符串。这将读取连续字符,直到遇到一个空格字符(空格字符可以是空白、换行和制表符)。 | char * |
%u | 无符号的十进制整数。 | unsigned int * |
%x、%X | 十六进制整数:数字前面的 + 或 - 号是可选的 | int * |
%p | 读入一个指针 。 | |
%[] | 扫描字符集合 。 | |
%*c | 忽略一个输入字符。 | |
%n | 获取前一次输入的长度 | |
%% | 读 % 符号。 |
注意:
1.占位符为%s
scanf在输入字符串时,虽然不会接收空白符(回车‘\n’,空格‘ ’,水平制表符Tab‘\t’)(均作为结束标志,并将空白符变成空字符‘\0’补充在输入的最后一个字符后面),并且在输入第一个字符前忽略所有空白符。但scanf在输入字符时,并不会忽略空白符,反而会直接接收任何空白符,因此我们在输入前应该先将容易在缓冲区留下来的空白符清除。
这里补充空字符的概念:在C语里,‘\0’是一个‘空操作’字符,它不做任何操作,但不能理解为没有字符,应该理解为代表什么都没有的字符,是一个特殊标志,默认作为字符串结束的标志。并且‘\0’的代码值为0,不计入串的长度,但需要提供一个空间存储以防数据溢出,所以常常数组大小需要至少比字符串多一位。
2.占位符为%[]
在代码中 scanf(“%[^Q] %*c%*c”, &str); 使用了两个 %*c 是为了接收字符Q和回车符号(\n)。
因为 scanf("%[^Q] ", &str);本意为除了Q字符以外的字符全部接收写入到str中。一旦遇到Q就停止匹配,并且停止匹配后Q字符和Q字符之后输入的回车符都在我们的输入缓冲区中,如果我们不对这些字符做出清理就会影响下一次的输入。
一些常见的组合用法:
#include<stdio.h>
int main()
{
char str[100];
// scanf("%[^!]", str);//以!结束输入 注:记得清理缓冲区中剩余字符
// scanf("%[^\n]",str);//以回车结束输入 注:。。。
//
// scanf("%[123]",str); //只能输入123,遇到其他字符后停止匹配
// scanf("%[^123]",str); //只能输入非123,遇到其123后停止匹配
//
// scanf("%[a-z,A-Z]", str); //只能输入英文字符,遇到其他字符后停止匹配
// scanf("%[^a-z,A-Z]",str); //只能输入非英文字符,遇到其他字符后停止匹配
//
// scanf("%*c",str);//清理缓冲区中第一个字符,比如:上次遗留下的\n
// scanf("%*[^!] %*c",str); //跳过一行
printf("%s", str);
return 0;
}
int sscanf( const char *buffer, const char *format [, argument ] … );(把一个字符串转换成格式化的数据)
解释:
buffer是C字符串(可以是一个变量),表示输入流,其他见前文。
本质是scanf的输入流stdin改成了buffer,在进行输入数据时,数据来源不是键盘了,而是buffer这个字符串。
例如:
struct student{
char name[256];
int age;
}stu;
int main(){
char buf[256] = "zhangsan 20";
sscanf(buf, "%s %d", stu.name, &(stu.age));
printf("%s %d", stu.name, stu.age);
return 0;
}
结果为:zhangsan 20
int fscanf( FILE *stream, const char *format [, argument ]… );(针对所有输入流的格式化的输入函数)
解释:
stream是输入流名称,其他见前文。
在进行输入数据时,数据来源不一定是键盘了,而可以自定义。
int printf( const char *format [, argument]… );(-格式化的输出函数)
解释:
format是C字符串(可以是一个变量),包含了以下各项中的一个或多个
其形式为:"%[flags(标志)][width(宽度)][.prec(精度)][length(类型长度)][type(类型)]“
解释
flags:
标志 | 意义 |
---|---|
- | 项目是左对齐的;也就是说,会把项目打印在字段的左侧开始处。示例:“%-20s” |
+ | 有符号的值若为正,则显示带加号的符号;若为负,则带减号的符号。示例:“%+6.2f” |
空格 | 带符号的值若为正,则显示时带前导空格(但是不显示符号);若为负,则带减号符号。+标志会覆盖空格标志;示例:“% 6.2f” |
# | 使用转换说明的可选形式。若为%o格式,则以0开始;若为%x或%X格式,则以0x或0X开始。对于所有的浮点形式,#保证了即使不跟任何数字,也打印一个小数点符号。对于%g和%G格式,它防止尾随0被删除;示例:“%#o” |
0 | 对于所有的数字格式,用前导0而不是用空格填充字段。如果出现-标志或者指定了精度(对于整数)则忽略该标志;示例:“%010d” |
width和.prec:
修饰符 | 意义 |
---|---|
digit(s) | 字段宽度的最小。如果该字段不能容纳要打印的数或者字符串,系统就会使用更宽的字段。示例:“%4d” |
.digit(s) | 精度,对于%e,%E和%f转换,是将要在小数点的右边打印的数字的位数。对于%g和%G转换,是有效数字的最大位数。对于%s转换,是将要打印的字符的最大数目。对于整数转换,是将要打印的数字的最小位数;如果必要,要使用前导0来达到这个位数。只使用".“表示其后跟随一个零,所以%.f和%.0f相同;示例:”%5.2f"打印一个浮点数,他的字段宽度为5个字符,小数点后面有两位数字 |
length:
修饰符 | 意义 |
---|---|
h | 和整数转换说明符一起使用,表示一个short int或unsigned short int类型数值;示例:“%hu” “%hd” “%hx” |
hh | 和整数转换说明符一起使用,表示一个signed char或unsigned char类型数值;示例:“%hhu” “%hhd” “%hhx” |
j | 和整数转换说明符一起使用,表示一个intmax_t或uintmax_t值;示例:“%jd” “%jX” |
l | 和整数转换说明符一起使用,表示一个long int或unsigned long int类型数值;示例:“%lu” “%ld” |
ll | 和整数转换说明符一起使用,表示一个long long int或unsigned long long int类型数值(c99);示例:“%llu” “%lld” |
L | 和浮点转换说明符一起使用,表示一个long double值;示例:“%Lf” “%Le” |
t | 和整数转换说明符一起使用,表示一个ptrdiff_t值(与两个指针之间的差对应的类型)(c99);示例:“%td” |
z | 和整数转换说明符一起使用,表示一个size_t值(sizeof返回类型)(c99);示例:“%zd” |
I64 | 和整数转换说明符一起使用,表示一个_int64值 |
type:
转换说明 | 输出 |
---|---|
%a | 浮点数、十六进制数字和p-计数法(c99) |
%A | 浮点数、十六进制数字和P-计数法(c99) |
%c | 一个字符 |
%d | 有符号十进制整数 |
%e | 浮点数、e-记数法 |
%E | 浮点数、E-计数法 |
%f | 浮点数、十进制记数法 |
%g | 根据数值不同自动选择%f或%e。%e格式在指数小于-4或者大于精度时使用 |
%G | 根据数值不同自动选择%f或%E。%E格式在指数小于-4或者大于精度时使用 |
%i | 有符号十进制整数(与%d相同) |
%o | 有符号八进制整数 |
%p | 指针 |
%s | 字符串 |
%u | 无符号十进制整数 |
%x | 使用十六进制数0x的无符号十六进制整数 |
%X | 使用十六进制数字0X的无符号十六进制整数 |
%% | 打印一个百分号 |
浮点参数的转换:
有用于打印浮点类型double和long double的转换说明符,但没有用于float的说明符。原因是在K&R C中float值在被用于表达式中或者被用作参数之前,会被自动转换成double类型。一般情况下,ANSI C不会自动把float转换成double。不过,为了保护大量现有的假设float参数仍会自动被转换成double。因此,不过是K&R C还是ANSI C,都无需专门的转换说明符来显示float。
int sprintf( char *buffer, const char *format [, argument] … );(把一个字符串转换成格式化的数据)
解释:
buffer是C字符串(可以是一个变量),表示输入流,其他见前文。
例如:
struct student{
char name[256];
int age;
}student= { "zhangsan", 20 };
int main(){
char buf[256] ;
sprintf(buf, "%s %d", student.name, student.age);
printf("%s", buf);
return 0;
}
结果为:zhangsan 20
int fprintf( FILE *stream, const char *format [, argument ]…);(针对所有输入流的格式化的输入函数)
解释:
stream是输入流名称,其他见前文。