读取仅包含指定字符集的字符串
sscanf("123456abcdefBCDEF", "%[1-9a-z]", buf); // 结果为:123456abcdef // 表达式是要匹配数字和小写字母,匹配到大写字母就停止匹配了。读取指定字符集为止的字符串
sscanf("123456abcdefBCDEF", "%[^A-Z]", buf); // 结果为:123456abcdef读取两个符号之间的内容(@和.之间的内容)
sscanf("liwei0526vip@linuxblogs.cn", "%*[^@]@%[^.]", buf); // 结果为:linuxblogs // 先读取@符号前边内容并丢弃,然后读@,接着读取.符号之前的内容linuxblogs,不包含字符.给一个字符串
sscanf("hello, world", "%*s%s", buf); // 结果为:world // 先忽略一个字符串"hello,",遇到空格直接跳过,匹配%s,保存 world 到 buf // %*s 表示第 1 个匹配到的被过滤掉,即跳过"hello,",如果没有空格,则结果为 NULL稍微复杂点的
sscanf("ABCabcAB=", "%*[A-Z]%*[a-z]%[^a-z=]", buf); // 结果为:AB 自己尝试分析哈包含特殊字符处理
sscanf("201*1b_-cdZA&", "%[0-9|_|--|a-z|A-Z|&|*]", buf); // 结果为:201*1b_-cdZA&如果能将上述几个例子搞明白,相信基本上已经掌握了 sscanf 的用法,实践才是检验真理的唯一标准,只有多使用,多思考才能真正理解它的用法。
(3). fprintf / fscanffprintf 打印到指定的文件 stream 中,fscanf 从文件中格式化读取数据,类似 scanf 函数。相关函数的声明如下:
int fprintf(FILE *stream, const char *format, ...); int fscanf(FILE *stream, const char *format, ...);还是通过简单实例来说明基本用法。
FILE *fp = fopen("file.txt", "w"); fprintf(fp, "%d-%s-%f\n", 32, "hello", 0.12); fclose(fp); liwei:/tmp$ cat file.txt 32-hello-0.120000而 fscanf 函数的使用基本上与 sscanf 函数使用方式相同。
八、IO缓冲区还有个关于 IO 非常重要的概念,就是 IO 缓冲区。
C 标准库为每个打开的文件分配一个 I/O 缓冲区,用户调用读写函数大多数都在 I/O 缓冲区中读写,只有少数请求传递给内核。
以 fgetc/fputc 为例,当第一次调用 fgetc 读一个字节时,fgetc 函数可能通过系统调用进入内核读 1k 字节到缓冲区,然后返回缓冲区中第一个字节给用户,以后用户再调用 fgetc,就直接从缓冲区读取。
另一方面,fputc 通常只是写到缓冲区中,如果缓冲区满了,fputc 就通过系统调用把缓冲区数据传递给内核,内核将数据写回磁盘。如果希望把缓冲区数据立即写入磁盘,可以调用 fflush 函数。
C 标准库 IO 缓冲区有三种类型:全缓冲、行缓冲和无缓冲区,不同类型的缓冲区具有不同的特性。
全缓冲:如果缓冲区写满了就写回内核。常规文件通常是全缓冲的。
行缓冲:如果程序写的数据中有换行符就把这一行写回内核,或者缓冲区满就写回内核。标准输入和标准输出对应终端设备时通常是行缓冲的。
无缓冲:用户程序每次调用库函数做写操作都要通过系统调用写回内核。标准错误输出通常是无缓冲的,用户程序的错误信息可以尽快输出到设备。
printf("hello world"); while(1); // 运行程序会发现屏幕并没有打印hello world // 因为缓冲区没满,且没有\n符号除了写满缓冲区、写入换行符之外,行缓冲还有一种情况会自动做 flush 操作,如果:
用户程序调用库函数从无缓冲的文件中读取
或从行缓冲的文件中读取,且这次读操作会引发系统调用从内核读取数据,那么会读之前自动 flush 所有行缓冲
程序退出时通常也会自动 flush 缓冲区
如果不想完全依赖自动的 flush 操作,可以调用 fflush 函数手动操作。若调用 fflush(NULL) 可以对所有打开文件的 IO 缓冲区做 flush 操作。缓冲区大小也可以自定义设置,一般情况无需设置,默认即可。
Linux公社的RSS地址:https://www.linuxidc.com/rssFeed.aspx