【C】标准IO库函数
fopen/fclose
#include <stdio.h>FILE *fopen(const char *path, const char *mode);
返回值:成功返回文件指针,出错返回NULL并设置errnoint fclose(FILE *fp);
返回值:成功返回0,出错返回EOF并设置errno
mode
参数是一个字符串,由rwatb+
六个字符组合而成,
r
表示读,w
表示写,a
表示追加(Append),在文件末尾追加数据使文件的尺寸增大。t
表示文本文件,b
表示二进制文件,有些操作系统的文本文件和二进制文件格式不同,而在UNIX系统中,无论文本文件还是二进制文件都是由一串字节组成,t
和b
没有区分,用哪个都一样,也可以省略不写。如果省略t
和b
,rwa+
四个字符有以下6种合法的组合:
“r” | 只读,文件必须已存在 |
---|---|
”w“ | 只写,如果文件不存在则创建,如果文件已存在则把文件长度截断为0字节再重新写,也就是替换掉原来的文件内容 |
”a“ | 只能再文件末尾追加数据,如果文件不存在则创建 |
”r+“ | 允许读和写,文件必须存在 |
”w+“ | 允许读和写,如果文件不存在则创建,如果文件已存在则把文件长度截断为0字节再重新写 |
”a+“ | 允许读和追加数据,如果文件不存在则创建 |
stdin/stdout/stderr
我们经常用printf
打印到屏幕,也用过scanf
读键盘输入,这些也属于I/O操作,但不是对文件做I/O操作而是对终端设备做I/O操作。
那为什么printf
和scanf
不用打开就能对终端设备进行操作呢?因为在程序启动时(在main
函数还没开始执行之前)会自动把终端设备打开三次,分别赋给三个FILE *
指针stdin
、stdout
和stderr
,这三个文件指针是libc
中定义的全局变量,在stdio.h
中声明,printf
向stdout
写,而scanf
从stdin
读,后面我们会看到,用户程序也可以直接使用这三个文件指针。这三个文件指针的打开方式都是可读可写的,但通常stdin
只用于读操作,称为标准输入(Standard Input),stdout
只用于写操作,称为标准输出(Standard Output),stderr
也只用于写操作,称为标准错误输出(Standard Error),通常程序的运行结果打印到标准输出,而错误提示(例如gcc
报的警告和错误)打印到标准错误输出,所以fopen
的错误处理写成这样更符合惯例:
if ( (fp = fopen("/tmp/file1", "r")) == NULL) {fputs("Error open file /tmp/file1\n", stderr);exit(1);
}
errno与perror函数
很多系统函数在错误返回时将错误原因记录在libc
定义的全局变量errno
中,每种错误原因对应一个错误码,请查阅errno(3)
的Man Page了解各种错误码,errno
在头文件errno.h
中声明,是一个整型变量,所有错误码都是正整数。
如果在程序中打印错误信息时直接打印errno
变量,打印出来的只是一个整数值,仍然看不出是什么错误。比较好的办法是用perror
或strerror
函数将errno
解释成字符串再打印。
#include <stdio.h>void perror(const char *s);
perror
函数将错误信息打印到标准错误输出,首先打印参数s
所指的字符串,然后打印:号,然后根据当前errno
的值打印错误原因。例如:
FILE *fp = fopen("abcde", "r");if (fp == NULL){perror("Open file abcde");exit(1);}
如果文件abcde
不存在,fopen
返回-1并设置errno
为ENOENT
,紧接着perror
函数读取errno
的值,将ENOENT
解释成字符串No such file or directory
并打印,最后打印的结果是Open file abcde: No such file or directory
。
大多数系统函数都有一个Side Effect,就是有可能改变errno
变量(当然也有少数例外,比如strcpy
),所以一个系统函数错误返回后应该马上检查errno
,在检查errno
之前不能再调用其它系统函数。
strerror
函数可以根据错误号返回错误原因字符串。
#include <string.h>char *strerror(int errnum);
返回值:错误码errnum所对应的字符串
有些函数的错误码并不保存在errno
中,而是通过返回值返回,就不能调用perror
打印错误原因了,这时strerror
就派上了用场:
以字节为单位的I/O函数
fgetc
函数从指定的文件中读一个字节,getchar
从标准输入读一个字节,调用getchar()
相当于调用fgetc(stdin)
。
#include <stdio.h>int fgetc(FILE *stream);
int getchar(void);
返回值:成功返回读到的字节,出错或者读到文件末尾时返回EOF
对于fgetc函数的使用有以下几点说明:
- 要用
fgetc
函数读一个文件,该文件的打开方式必须是可读的。 - 系统对于每个打开的文件都记录着当前读写位置在文件中的地址(或者说距离文件开头的字节数),也叫偏移量(Offset)。当文件打开时,读写位置是0,每调用一次
fgetc
,读写位置向后移动一个字节,因此可以连续多次调用fgetc
函数依次读取多个字节。 fgetc
成功时返回读到一个字节,本来应该是unsigned char
型的,但由于函数原型中返回值是int
型,所以这个字节要转换成int
型再返回,那为什么要规定返回值是int
型呢?因为出错或读到文件末尾时fgetc
将返回EOF
,即-1,保存在int
型的返回值中是0xffffffff,如果读到字节0xff,由unsigned char
型转换为int
型是0x000000ff,只有规定返回值是int
型才能把这两种情况区分开,如果规定返回值是unsigned char
型,那么当返回值是0xff时无法区分到底是EOF
还是字节0xff。如果需要保存fgetc
的返回值,一定要保存在int
型变量中,如果写成unsigned char c = fgetc(fp);
,那么根据c
的值又无法区分EOF
和0xff字节了。注意,fgetc
读到文件末尾时返回EOF
,只是用这个返回值表示已读到文件末尾,并不是说每个文件末尾都有一个字节是EOF
(根据上面的分析,EOF并不是一个字节)。
fputc
函数向指定的文件写一个字节,putchar
向标准输出写一个字节,调用putchar(c)
相当于调用fputc(c, stdout)
。
#include <stdio.h>int fputc(int c, FILE *stream);
int putchar(int c);
返回值:成功返回写入的字节,出错返回EOF
对于fputc
函数的使用也要说明几点:
- 要用
fputc
函数写一个文件,该文件的打开方式必须是可写的(包括追加)。 - 每调用一次
fputc
,读写位置向后移动一个字节,因此可以连续多次调用fputc
函数依次写入多个字节。但如果文件是以追加方式打开的,每次调用fputc
时总是将读写位置移到文件末尾然后把要写入的字节追加到后面。
操作读写位置的函数
#include <stdio.h>int fseek(FILE *stream, long offset, int whence);
返回值:成功返回0,出错返回-1并设置errnolong ftell(FILE *stream);
返回值:成功返回当前读写位置,出错返回-1并设置errnovoid rewind(FILE *stream);//把读写位置移到文件开头
fseek
的whence
和offset
参数共同决定了读写位置移动到何处,whence
参数的含义如下:
SEEK_SET
从文件开头移动offset
个字节
SEEK_CUR
从当前位置移动offset
个字节
SEEK_END
从文件末尾移动offset
个字节
offset
可正可负,负值表示向前(向文件开头的方向)移动,正值表示向后(向文件末尾的方向)移动,如果向前移动的字节数超过了文件开头则出错返回,如果向后移动的字节数超过了文件末尾,再次写入时将增大文件尺寸,从原来的文件末尾到fseek
移动之后的读写位置之间的字节都是0。
以字符串为单位的I/O函数
fgets
从指定的文件中读一行字符到调用者提供的缓冲区中,gets
从标准输入读一行字符到调用者提供的缓冲区中。
#include <stdio.h>char *fgets(char *s, int size, FILE *stream);
返回值:成功时s指向哪返回的指针就指向哪,出错或者读到文件末尾时返回NULL
参数s
是缓冲区的首地址,size
是缓冲区的长度,该函数从stream
所指的文件中读取以'\n'
结尾的一行(包括'\n'
在内)存到缓冲区s
中,并且在该行末尾添加一个'\0'
组成完整的字符串。如果文件中的一行太长,fgets
从文件中读了size-1
个字符还没有读到'\n'
,就把已经读到的size-1
个字符和一个'\0'
字符存入缓冲区,文件中剩下的半行可以在下次调用fgets
时继续读。
fputs
向指定的文件写入一个字符串,puts
向标准输出写入一个字符串。
#include <stdio.h>int fputs(const char *s, FILE *stream);
int puts(const char *s);
返回值:成功返回一个非负整数,出错返回EOF
以记录为单位的I/O函数
#include <stdio.h>size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
返回值:读或写的记录数,成功时返回的记录数等于nmemb,出错或读到文件末尾时返回的记录数小于nmemb,也可能返回0
fread
和fwrite
用于读写记录,这里的记录是指一串固定长度的字节,比如一个int
、一个结构体或者一个定长数组。参数size
指出一条记录的长度,而nmemb
指出要读或写多少条记录,这些记录在ptr
所指的内存空间中连续存放,共占size * nmemb
个字节,fread
从文件stream
中读出size * nmemb
个字节保存到ptr
中,而fwrite
把ptr
中的size * nmemb
个字节写到文件stream
中。
nmemb
是请求读或写的记录数,fread
和fwrite
返回的记录数有可能小于nmemb
指定的记录数。例如当前读写位置距文件末尾只有一条记录的长度,调用fread
时指定nmemb
为2,则返回值为1。如果当前读写位置已经在文件末尾了,或者读文件时出错了,则fread
返回0。如果写文件时出错了,则fwrite
的返回值小于nmemb
指定的值。
格式化I/O函数
#include <stdio.h>int printf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
int sprintf(char *str, const char *format, ...);
int snprintf(char *str, size_t size, const char *format, ...);
返回值:成功返回格式化输出的字节数(不包括字符串的结尾'\0'),出错返回一个负值
printf
格式化打印到标准输出,
fprintf
打印到指定的文件stream
中。
sprintf
并不打印到文件,而是打印到用户提供的缓冲区str
中并在末尾加'\0'
,由于格式化后的字符串长度很难预计,所以很可能造成缓冲区溢出,用snprintf
更好一些,参数size
指定了缓冲区长度,如果格式化后的字符串长度超过缓冲区长度,
snprintf
就把字符串截断到size-1
字节,再加上一个'\0'
写入缓冲区,也就是说snprintf
保证字符串以'\0'
结尾。snprintf
的返回值是格式化后的字符串长度(不包括结尾的'\0'
),如果字符串被截断,返回的是截断之前的长度,把它和实际缓冲区中的字符串长度相比较就可以知道是否发生了截断。
选项 | 描述 | 举例 |
---|---|---|
# | 八进制前面加0(转换字符为o ),十六进制前面加0x(转换字符为x )或0X(转换字符为X )。 | printf(“%#x”, 0xff) 打印0xff ,printf(“%x”, 0xff) 打印ff 。 |
- | 格式化后的内容居左,右边可以留空格。 | 见下面的例子 |
宽度 | 用一个整数指定格式化后的最小长度,如果格式化后的内容没有这么长,可以在左边留空格,如果前面指定了- 号就在右边留空格。宽度有一种特别的形式,不指定整数值而是写成一个``号,表示取一个int 型参数作为宽度。 | printf(“-%10s-“, “hello”) 打印-␣␣␣␣␣hello- ,printf(“-%-s-“, 10, “hello”) 打印-hello␣␣␣␣␣- 。 |
. | 用于分隔上一条提到的最小长度和下一条要讲的精度。 | 见下面的例子 |
精度 | 用一个整数表示精度,对于字符串来说指定了格式化后保留的最大长度,对于浮点数来说指定了格式化后小数点右边的位数,对于整数来说指定了格式化后的最小位数。精度也可以不指定整数值而是写成一个``号,表示取下一个int 型参数作为精度。 | printf(“%.4s”, “hello”) 打印hell ,printf(“-%6.4d-“, 100) 打印-␣␣0100- ,printf(“-%.*f-“, 8, 4, 3.14) 打印-␣␣3.1400- 。 |
字长 | 对于整型参数,hh 、h 、l 、ll 分别表示是char 、short 、long 、long long 型的字长,至于是有符号数还是无符号数则取决于转换字符;对于浮点型参数,L 表示long double 型的字长。 | printf(“%hhd”, 255) 打印-1 。 |
转换字符 | 描述 | 举例 |
---|---|---|
d i | 取int 型参数格式化成有符号十进制表示,如果格式化后的位数小于指定的精度,就在左边补0。 | printf(“%.4d”, 100) 打印0100 。 |
o u x X | 取unsigned int 型参数格式化成无符号八进制(o)、十进制(u)、十六进制(x或X)表示,x表示十六进制数字用小写abcdef,X表示十六进制数字用大写ABCDEF,如果格式化后的位数小于指定的精度,就在左边补0。 | printf(“%#X”, 0xdeadbeef) 打印0XDEADBEEF ,printf(“%hhu”, -1) 打印255 。 |
c | 取int 型参数转换成unsigned char 型,格式化成对应的ASCII码字符。 | printf(“%c”, 256+’A’) 打印A 。 |
s | 取const char 型参数所指向的字符串格式化输出,遇到‘\0’ 结束,或者达到指定的最大长度(精度)结束。 | printf(“%.4s”, “hello”) 打印hell 。 |
p | 取void 型参数格式化成十六进制表示。相当于%#x 。 | printf(“%p”, main) 打印main 函数的首地址0x80483c4 。 |
f | 取double 型参数格式化成[-]ddd.ddd 这样的格式,小数点后的默认精度是6位。 | printf(“%f”, 3.14) 打印3.140000 ,printf(“%f”, 0.00000314) 打印0.000003 。 |
相关文章:
【C】标准IO库函数
fopen/fclose #include <stdio.h>FILE *fopen(const char *path, const char *mode); 返回值:成功返回文件指针,出错返回NULL并设置errnoint fclose(FILE *fp); 返回值:成功返回0,出错返回EOF并设置errnomode参数是一个字符…...

http客户端Feign
Feign替代RestTemplate RestTemplate方式调用存在的缺陷 String url"http://userservice/user/"order.getUserId();User user restTemplate.getForObject(url, User.class); 代码可读性差,变成体验不统一; 参数复杂的时候URL难以维护。 &l…...
如何在Java中使用枚举类:从入门到进阶
枚举类是Java中一种特殊的数据类型,它允许我们将一组有限的值作为一组常量来使用,这些常量在代码中具有固定的名称和类型。在Java中,枚举类通常用于代表状态、选项和类别等具有离散值的变量。本篇博客将深入探讨Java中的枚举类,包…...
操作系统(1.2)--引论
目录 一、操作系统的基本特性 1.并发性 1.1 并行与并发 1.2 引入进程 2.共享性 2.1 互斥共享方式 2.3 同时访问方式 3.虚拟 3.1 时分复用技术 4. 异 步 二、操作系统的主要功能 1.处理机管理功能 1.1 进程控制 1.2 进程同步 1.3 进程通信 1.4 调度 2. 内…...
【Linux】 shell if的[]和[[]]区别
文章目录[]和test[]和[[]]区别总结参考[]和test Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试 test常用于 if ,作为判断条件,if test等价于 if [ ],因此,test和[] 内的内…...
利用flask解析海康摄像头视频
利用flask解析海康摄像头视频利用flask解析海康摄像头和大华摄像头的视频一、安装依赖包二、获取海康摄像头视频流三、将视频流输出到Web页面四、 创建HTML模板文件利用flask解析海康摄像头和大华摄像头的视频 作为AI智能的一种应用场景,视频监控系统已经在各个行业…...
./docker-compose.yml‘ is invalid
文章目录前言提示原因版本太低解决方法更新删除原来不能执行的/usr/local/bin/docker-compose下载安装docker-compose添加权限前言 安装ctfd过程中的一些报错 rootubuntu:/CTFd# docker-compose up -d ERROR: The Compose file ./docker-compose.yml is invalid because: net…...
Java 流程控制
条件/选择结构 if if(条件表达式){// 表达式为 true 时,执行该代码块 }if(true) {System.out.println("hello"); }if else if(条件表达式){// 表达式为 true 时,执行该代码块 } else {// 表达式为 false 时,执行该代码块 }if(1 …...

边界无限入选首届“网络安全高成长性企业”并荣获“勇创之星”
近日,由工业和信息化部、四川省人民政府主办的“2023年中国网络和数据安全产业高峰论坛网络安全产融合作分论坛”在成都举行,论坛上公布了“2022年度网络安全高成长性企业”名单。云原生安全、应用安全“灵动智御”理念创领者北京边界无限科技有限公司&a…...

SpringBoot项目的快速创建方式(包含第一个程序的运行)
目录 一、IDEA所用的版本以及插件 二、操作步骤 一、IDEA所用的版本以及插件 idea的版本: idea2022版本下载安装配置与卸载详细步骤(包含运行第一个java程序教程)_idea2022下载_云边的快乐猫的博客-CSDN博客 如果英文看不懂就点击…...
linux下设置定期执行需要root权限的sh文件
1、准备好一个shell文件 比如我这个叫clean.sh,位于/home/admin/gdhysthj/clean.sh 2、首先将shell文件赋权为可执行文件 chmod 777 clean.sh 3、切换为超级管理员 su 4、设置定时器 crontab -u root -e 5、回车后,进入一个类似vim的界面,…...

认识异或运算
1.什么是异或运算 异或运算是位运算的一种,符号为:^ 运算规则为:相同为0,不同为1 例如 性质: N ^ 0 N N ^ N 0 A ^ B B ^ A (A ^ B) ^ C A ^ (B ^ C)N ^ 0 N public class XorOperation {public static void …...
内容提供者的简单使用
内容提供者的简单使用 最近在复习ContentProvider时遇到了一些问题,几经波折,终于解决了,故写下这篇博客,希望能帮到有相同问题的兄弟。 何时使用 当我们想要一个应用的数据向外部公开时,ContentProvider是一个不错…...

Modelsim 操作结构和流程
用到的命令一般都写到.do文件中,使用脚本语言进行批量处理。Step 1: Map librariesStep 2: Compile the designStep 3: Optimize the design (OPTIONAL)Step 4: Load the design into the simulatorStep 5: Run the simulationStep 6: Debug the design Note: Desig…...
vue和react有什么不同
vue上手难度低,不过react社区活跃度更多一些,一般数据比较多的大型项目会倾向于使用react。在react官网中,官方也建议我们使用React来构建快速响应的大型 Web 应用程序。vue2.0是面向对象编程({data: {}, methods: {}, created() …...
js求解《初级算法》28. 找出字符串中第一个匹配项的下标
一、题目描述 给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。 输入:haystack "sadb…...

VAE--part1
Variational Auto-Encoder, VAE__part1分布变换VAE慢谈VAE 初现分布标准化重参数技巧VAE的本质是什么?VAE的本质结构正态分布?变分在哪里参考博客仅做学习记录,侵删分布变换 VAE和GAN都是生成式模型,它们俩的目标基本一致&#x…...
备战四级!!!
目录 一、替换词 二、作文常见句型 (1)常见开头 (2)阐述观点 (3)结束语 (4)提出建议 (5)表示论证 (6)给出原因 (…...

sizeof与strlen练习
前言 本篇仅仅是为了更加了解sizeof操作符和strlen函数练习. 对于多条sizeof操作符和strlen函数出现,可能很容易造成头脑不清晰,做题时容易混乱. 目录前言一维数组字符数组情况1:情况2情况3二维数组练习之前请牢记下面这段话.这将是头脑清晰地关键. 提示: sizeof(数组名)&#…...

知识图谱的介绍
知识图谱的由来 谷歌在2012年提出了知识图谱的概念,当时目的在于优化搜索引擎的返回结构,为用户提供更精确的结果。 知识图谱的定义 为了理解知识图谱,我们首先要明白信息与知识的概念。首先,信息表示的是外部的客观事实&#…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...

聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...

k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...

uniapp手机号一键登录保姆级教程(包含前端和后端)
目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号(第三种)后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...

【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...