格式化I/O(常用的 sprintf 和 sscanf 总结)
2017-10-18 19:50
501 查看
2
3
4
5
6
printf 将格式化数据写到标准输出,fprintf 写至指定流,dprintf 写至指定文件描述符。
sprintf 将格式化字符写入数组 buf。sprintf 在该数组的尾端自动加入一个 null 字节,但该字符不包括在返回值中。sprintf 函数可能会造成由 buf 指向的缓冲区的溢出。调用者有责任确保该缓冲区足够大。缓冲区溢出会造成程序不稳定甚至安全隐患,为解决这种缓冲区溢出问题,引入 snprintf 函数。
snprintf 函数中,缓冲区长度是一个显式参数,超过缓冲区尾端写的所有字符都被丢弃。如果缓冲区足够大,snprintf 会返回写入缓冲区的字符数,该值不包括尾端的 null 字节。若 snprintf 函数返回小于缓冲区长度的正值,则没有截断输出;若返回负值,则说明出现编码错误。
格式说明控制其余参数如何编写,以及如何显示。每个参数按照转换说明编写,转换说明以百分号%开始。一个转换说明有4个可选部分:
flag:
fldwidth:说明最小字段宽度
precision:说明整型转换后最少输出数字位数、浮点数转换后小数点后最少位数、字符串转换后最大字节数。精度为一个点(.),其后跟随一个可选非负十进制数或星号(*)。
convtype:
sprintf 是较常用的输出函数之一,用法如下:
a. 格式化数字字符串
sprintf最常见的应用之一莫过于把整数打印到字符串中,所以,spritnf在大多数场合可以替代itoa。如:
2
3
4
5
6
7
8
9
b. 控制浮点数打印格式,默认保留小数点后6位
但有时我们希望自己控制打印的宽度和小数位数,这时就应该使用:”%m.nf” 格式,其中m表示打印的宽度,n表示小数点后的位数。比如:
2
3
对于如下代码:
2
其结果是什么? “0.000”。。
原因是参数压栈时调用者并不知道跟 i 相对应的格式控制符是个”%f”。而函数执行时函数本身则并不知道当年被压入栈里的是个整数,于是保存整数 i 的那4个字节就被强行作为浮点数格式来解释了,导致出错了
c.利用sprintf的返回值
例如,下面代码生成10个[0,100)的随机数,并输出到数组中,以逗号隔开:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
scanf 族函数用于分析输入字符串,并将字符序列转换成指定类型的变量。在格式之后的各参数包含了变量的地址,用转换结果对这些变量赋值。
格式说明控制如何转换参数,以便对它们赋值。转换说明以百分号 % 开始,除转换说明和空白字符外,格式字符串中其他字符必须与输入匹配,若有一个字符不匹配,则停止后续处理,不再读输入的其他部分。
一个转换说明有 3 个如下的可选择的部分:
其中,可选择的星号(*)用于抑制转换。按照转换说明的其余部分对输入进行转换,但转换结果并不存放在参数中。
fldwidth 说明最大宽度(即最大字符数),lenmodifier 说明要用转换结果赋值的参数大小。
convtype 字段类似于printf 族的转换类型字段,但两者之间还有些差别。一个差别是作为一种选项,输入中带符号的可赋予无符号类型。
在字段宽度和长度修饰符之间的可选项m 是赋值分配符,它可以用于%c、%s 以及 %[ 转换符,迫使内存缓冲区分配空间以接纳转换字符串。在这种情况下,相关参数必须是指针地址,分配的缓冲区地址必须复制给该指针。如果调用成功,该缓冲区不再使用时,由该调用者负责通过调用 free 函数来释放缓冲区。
sscanf 与scanf 类似,都是用于输入的,只是后者以屏幕(stdin)为输入源,前者以固定字符串为输入源。其中的format可以是一个或多个:
注:
2
3
4
5
6
支持集合操作:
2
3
sscanf 用法:
a. 常见用法
2
3
b. 取指定长度的字符串。如在下例中,取最大长度为4字节的字符串。
2
c. 取到指定字符为止的字符串。如在下例中,取遇到空格为止字符串。
2
d.取仅包含指定字符集的字符串。如在下例中,取仅包含1到9和小写字母的字符串。
2
3
4
5
6
7
e.取到指定字符集为止的字符串。如在下例中,取遇到大写字母为止的字符串。
2
f.给定一个字符串”iios/12DDWDFF@122”,获取 / 和 @ 之间的字符串,先将 “iios/”过滤掉,再将非’@’的一串内容送到buf中
2
g.给定一个字符串““hello, world”,仅保留world。(注意:“,”之后有一空格)
2
3
4
h.提取字符串中的各个数字到各变量中
2
2
如果读取的字符串,不是以空格来分隔的话,就可以使用%[]。 %[]类似于一个正则表达式。[a-z]表示读取a-z的所有字符,[^a-z]表示读取除a-z以外的所有字符。 上述写法也可换作:
sscanf 的功能很类似于正则表达式,但却没有正则表达式强大,所以如果对于比较复杂的字符串处理,建议使用正则表达式。
转载地址:http://blog.csdn.net/fool_duck/article/details/51201723
1.格式化输出
#include <stdio.h> int printf(const char *restrict format, ...); int fprintf(FILE *restrict fp, const char *restrict format, ...); int dprintf(int fd, const char *restrict format, ...); int sprintf(char *restrict buf, const char *restrict format, ...); int snprintf(char *restrict buf, size_t n, const char *restrict format, ...);1
2
3
4
5
6
printf 将格式化数据写到标准输出,fprintf 写至指定流,dprintf 写至指定文件描述符。
sprintf 将格式化字符写入数组 buf。sprintf 在该数组的尾端自动加入一个 null 字节,但该字符不包括在返回值中。sprintf 函数可能会造成由 buf 指向的缓冲区的溢出。调用者有责任确保该缓冲区足够大。缓冲区溢出会造成程序不稳定甚至安全隐患,为解决这种缓冲区溢出问题,引入 snprintf 函数。
snprintf 函数中,缓冲区长度是一个显式参数,超过缓冲区尾端写的所有字符都被丢弃。如果缓冲区足够大,snprintf 会返回写入缓冲区的字符数,该值不包括尾端的 null 字节。若 snprintf 函数返回小于缓冲区长度的正值,则没有截断输出;若返回负值,则说明出现编码错误。
格式说明控制其余参数如何编写,以及如何显示。每个参数按照转换说明编写,转换说明以百分号%开始。一个转换说明有4个可选部分:
%[flag][fldwidth][precision][lenmodifier]convtype1
flag:
标志 | 说明 |
---|---|
‘ | (撇号)将整数按千位分组字符 |
- | 在字段内左对齐输出 |
+ | 总是显示带符号转换的正负号 |
(空格) | 如果第一个字符不是正负号,则在其前加入一个空格 |
# | 指定另一种转换形式 |
0 | 添加前导0(而非空格)进行填充 |
precision:说明整型转换后最少输出数字位数、浮点数转换后小数点后最少位数、字符串转换后最大字节数。精度为一个点(.),其后跟随一个可选非负十进制数或星号(*)。
convtype:
转换类型 | 说明 |
---|---|
d、i | 有符号十进制 |
o | 无符号八进制 |
u | 无符号十进制 |
x、X | 无符号十六进制 |
f、F | 双精度浮点数 |
e、E | 指数格式双精度浮点数 |
g、G | 根据转换后的值解释为 f、F、e、E |
a、A | 十六进制指数格式双精度浮点数 |
c | 字符 |
s | 字符串 |
p | 指向 void 的指针 |
n | 到目前为止,此printf调用输出的字符数目将被写入到指针所指向的带符号整型中 |
% | 一个 % 字符 |
C | 宽字符 |
S | 宽字符串 |
a. 格式化数字字符串
sprintf最常见的应用之一莫过于把整数打印到字符串中,所以,spritnf在大多数场合可以替代itoa。如:
//把整数123打印成一个字符串保存在s中。 sprintf(s, "%d", 123); // "123" //可以指定宽度,不足的左边补空格: sprintf(s, "%8d%8d", 123, 4567); // " 123 4567" //当然也可以左对齐: sprintf(s, "%-8d%8d", 123, 4567); // "123 4567" //也可以按照16进制打印: sprintf(s, "%8x", 4567); //小写16进制,宽度占8个位置,右对齐 sprintf(s, "%-8X", 4568); //大写16进制,宽度占8个位置,左对齐1
2
3
4
5
6
7
8
9
b. 控制浮点数打印格式,默认保留小数点后6位
sprintf(s, "%f", 3.1415926); // "3.141593"1
但有时我们希望自己控制打印的宽度和小数位数,这时就应该使用:”%m.nf” 格式,其中m表示打印的宽度,n表示小数点后的位数。比如:
sprintf(s, "%10.3f", 3.1415626); // " 3.142" sprintf(s, "%-10.3f", 3.1415626); // "3.142 " sprintf(s, "%.3f", 3.1415626); // "3.142"1
2
3
对于如下代码:
int i = 123; sprintf(s, "%.3f", i);1
2
其结果是什么? “0.000”。。
原因是参数压栈时调用者并不知道跟 i 相对应的格式控制符是个”%f”。而函数执行时函数本身则并不知道当年被压入栈里的是个整数,于是保存整数 i 的那4个字节就被强行作为浮点数格式来解释了,导致出错了
sprintf(s, "%.3f", (float)i); // 结果为 "123.000"1
c.利用sprintf的返回值
例如,下面代码生成10个[0,100)的随机数,并输出到数组中,以逗号隔开:
#include <stdio.h> #include <time.h> #include <stdlib.h> int main() { srand(time(0)); char s[64]; int offset = 0; for (int i = 0; i < 10; i++) { offset += sprintf(s + offset, "%d,", rand() % 100); } s[offset - 1] = '\n';//将最后一个逗号换成换行符。 printf(s); return 0; }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2.格式化输入
#include <stdio.h> int scanf(const char *restrict format, ...); int fscanf(FILE *restrict fp, const char *restrict format, ...); int sscanf(const char *restrict buf, const char *restrict format, ...);1
2
3
4
scanf 族函数用于分析输入字符串,并将字符序列转换成指定类型的变量。在格式之后的各参数包含了变量的地址,用转换结果对这些变量赋值。
格式说明控制如何转换参数,以便对它们赋值。转换说明以百分号 % 开始,除转换说明和空白字符外,格式字符串中其他字符必须与输入匹配,若有一个字符不匹配,则停止后续处理,不再读输入的其他部分。
一个转换说明有 3 个如下的可选择的部分:
% [*][fldwidth][m][lenmodifier]convtype1
其中,可选择的星号(*)用于抑制转换。按照转换说明的其余部分对输入进行转换,但转换结果并不存放在参数中。
fldwidth 说明最大宽度(即最大字符数),lenmodifier 说明要用转换结果赋值的参数大小。
convtype 字段类似于printf 族的转换类型字段,但两者之间还有些差别。一个差别是作为一种选项,输入中带符号的可赋予无符号类型。
在字段宽度和长度修饰符之间的可选项m 是赋值分配符,它可以用于%c、%s 以及 %[ 转换符,迫使内存缓冲区分配空间以接纳转换字符串。在这种情况下,相关参数必须是指针地址,分配的缓冲区地址必须复制给该指针。如果调用成功,该缓冲区不再使用时,由该调用者负责通过调用 free 函数来释放缓冲区。
转换类型 | 说明 |
---|---|
d | 有符号十进制,基数为10 |
i | 有符号十进制,基数由输入格式决定 |
o | 无符号八进制(输入可选地有符号) |
u | 无符号十进制,基数为10(输入可选地有符号) |
x、X | 无符号十六进制(输入可选地有符号) |
a、A、e、E、f、F、g、G | 浮点数 |
c | 字符(若带长度修饰符l,为宽字符) |
s | 字符串(若带长度修饰符l,为宽字符串) |
[ | 匹配列出的字符序列,以 ] 终止 |
[^ | 匹配除列出字符以外的所有字符,以 ] 终止 |
p | 指向 void 的指针 |
n | 到目前为止,此printf调用输出的字符数目将被写入到指针所指向的带符号整型中 |
% | 一个 % 字符 |
C | 宽字符 |
S | 宽字符串 |
{%[*] [width] [{h | l | I64 | L}]type | ' ' | '\t' | '\n' | 非%符号}1
注:
1.* 亦可用于格式中, (即 %*d 和 %*s) 加了星号 (*) 表示跳过此数据不读入. (也就是不把此数据读入参数中) 2.{a|b|c}表示a,b,c中选一,[d],表示可以有d也可以没有d。 3.width表示读取宽度。 4.{h | l | I64 | L}:参数的size,通常h表示单字节size,I表示2字节 size,L表示4字节size(double例外),l64表示8字节size。 5.type :%s,%d之类。 6.特别的:%*[width] [{h | l | I64 | L}]type 表示满足该条件的被过滤掉,不会向目标参数中写入值1
2
3
4
5
6
支持集合操作:
%[a-z] 表示匹配a到z中任意字符,贪婪性(尽可能多的匹配) %[aB'] 匹配a、B、'中一员,贪婪性 %[^a] 匹配非a的任意字符,贪婪性1
2
3
sscanf 用法:
a. 常见用法
char buf[512]; sscanf("123456 ", "%s", buf); printf("%s\n", buf); // "123456"1
2
3
b. 取指定长度的字符串。如在下例中,取最大长度为4字节的字符串。
sscanf("123456 ", "%4s", buf); printf("%s\n", buf); // "1234"1
2
c. 取到指定字符为止的字符串。如在下例中,取遇到空格为止字符串。
sscanf("123456 abcdedf", "%[^ ]", buf); printf("%s\n", buf); // "123456"1
2
d.取仅包含指定字符集的字符串。如在下例中,取仅包含1到9和小写字母的字符串。
sscanf("123456abcdedfBCDEF", "%[1-9a-z]", buf); printf("%s\n", buf); // "123456abcdedf" char s[] = "abcdef 1987:10:20"; char buf[512]; sscanf(s, "%[a-z0-9, ,:]", buf); // "abcdef 1987:10:20"1
2
3
4
5
6
7
e.取到指定字符集为止的字符串。如在下例中,取遇到大写字母为止的字符串。
sscanf("123456abcdedfBCDEF", "%[^A-Z]", buf); printf("%s\n", buf); // "123456abcdedf"1
2
f.给定一个字符串”iios/12DDWDFF@122”,获取 / 和 @ 之间的字符串,先将 “iios/”过滤掉,再将非’@’的一串内容送到buf中
sscanf("iios/12DDWDFF@122", "%*[^/]/%[^@]", buf); printf("%s\n", buf); // "12DDWDFF"1
2
g.给定一个字符串““hello, world”,仅保留world。(注意:“,”之后有一空格)
sscanf(“hello, world”, "%*s%s", buf); //%*s表示第一个匹配到的%s被过滤掉,即hello被过滤了,如果没有空格则结果为NULL。 printf("%s\n", buf); // "world"1
2
3
4
h.提取字符串中的各个数字到各变量中
int a, b, c; sscanf("2016:04:21", "%d:%d:%d", a, b, c); // a=2016, b=4, c=211
2
char sztime1[16] = "", sztime2[16] = ""; sscanf("2006:03:18 - 2006:04:18", "%s - %s", sztime1, sztime2);1
2
如果读取的字符串,不是以空格来分隔的话,就可以使用%[]。 %[]类似于一个正则表达式。[a-z]表示读取a-z的所有字符,[^a-z]表示读取除a-z以外的所有字符。 上述写法也可换作:
sscanf("2006:03:18 - 2006:04:18", "%[0-9,:] - %[0-9,:]", sztime1, sztime2);1
sscanf 的功能很类似于正则表达式,但却没有正则表达式强大,所以如果对于比较复杂的字符串处理,建议使用正则表达式。
转载地址:http://blog.csdn.net/fool_duck/article/details/51201723
相关文章推荐
- 格式化I/O(常用的 sprintf 和 sscanf 总结)
- fprintf、printf、sprintf、fscanf、scanf、sscanf 格式化输入输出
- python 字符串格式化以及常用函数总结
- sscanf和sprintf函数用法总结
- Sprintf,Format中格式化的常用用法!
- fprintf、printf、sprintf、fscanf、scanf、sscanf 格式化输入输出
- fprintf、printf、sprintf、fscanf、scanf、sscanf 格式化输入输出
- Printf,Sprintf 格式化简要总结
- sscanf与sprintf用法总结
- 日期格式化常用总结
- C语言--格式化输入/输出函数(printf/scanf,fprintf/fscanf,sprintf,sscanf)
- 关于 sprintf 和 sscanf 在ACM中的常用方法
- numpy常用功能总结、python格式化输入输出
- C# .ToString()格式化 常用数据转化小总结
- Sprintf,Format中格式化的常用用法!
- PHP中常用的字符串格式化函数总结
- PHP中常用的字符串格式化函数总结
- PHP中常用的字符串格式化函数总结
- Sprintf,Format中格式化的常用用法!
- C# .ToString()格式化 常用数据转化小总结