目录
printf\fprintf\sprintf\snprintf之间的区别?
3.1 将当前的时间写入到time. txt的文件中,如果ctrl+c退出之后,在再次执行支持断点续写
一、标准IO函数
1.1 fscanf \ fprintf
___________________________________
功能:写入文件,可以写入整数,小数,字符,字符串不同的数据类型
格式:
#include <stdio.h>
int printf(const char *format, ...);
printf("hello\n"); 双引号中没有占位符,则后面可以省略不写
printf("%d",11); 双引号由一个占位符,则后面需要写一个参数
printf("%d %f",11,3.14); 双引号里面有两个占位符,则后面需要写两个参数
-----------------回顾printf的使用-----------------------------
int fprintf(FILE *stream, const char *format, ...);
参数:
format: 格式串 由字符 汉字 占位符组成
...:可变参数 个数可变,类型可变,由格式串的占位符决定
stream: 流指针
返回值:
成功返回输出字符的个数,失败返回负数
_________________________________________
功能:从文件流指针读取不同类型的数据,当使用%d %f %s读取的数据以空格 回车表示数据的读取结束
%c可以读取空格,回车
格式:
#include <stdio.h>
int scanf(const char *format, ...);
scanf("%d",&a);
scanf("%d %f",&a,&b);
scanf("a");
int fscanf(FILE *stream, const char *format, ...);
参数:
const char *format:格式串 一般由占位符决定 字符
... : 可变地址列表
stream: 流指针
返回值:
成功返回输入的个数
失败返回EOF
读取到文件结尾返回EOF
fscanf和fprintf代码示例
1.2 fwrite| fread
_________________________________
功能:二进制文件的写入,把不同的数据类型转换为二进制文件,在读取时转换为单字符
int a=100;把a以字节为单位转换为二进制,文件中以单字符的形式显示
格式: #include <stdio.h>
size_t fwrite(const void *ptr, size_t size, size_t nmemb,
FILE *stream);
参数:
void* ptr: 写入数据的地址 (通用类型指针,可以指向任意类型的地址,但是在使用是需要类型强转)
size: 每个数据的字节大小
nmemb: 写入数据的个数
stream: 流指针
返回值:
如果成功则返回项目条的个数nmemb这个参数
如果size==1, 则返回是元素的总字节数
如果遇到文件结尾或失败,则返回小于nmemb的值或者是0
——————————————————————————————————————
eg:
int a=100;
fwrite(&a,sizeof(a),1,fp); ---->返回 1
等价于 fwrite(&a,1,sizeof(a),fp);--->返回4
int arr[]={1,2,3,4};
fwrite(arr,sizeof(int),3,fp) --->把数组全部写入 1 2 3
fwrite(arr,sizeof(int),3,fp) ---》不建议使用,重复写入第一次写入3个,剩一个在写入3个
写入数据有问题,建议一次一个,后面一般不会出问题
———————————————————————————————————————————
功能:读取二进制文件
格式:size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
参数:
void* ptr: 存储读取的数据 (通用类型指针,可以指向任意类型的地址,但是在使用是需要类型强转)
size: 每个数据的字节大小
nmemb: 写入数据的个数
stream: 流指针
返回值:
如果成功则返回项目条的个数nmemb这个参数
如果size==1, 则返回是元素的总字节数
如果遇到文件结尾或失败,则返回小于nmemb的值或者是0
读取失败不清楚是因为什么原因,那么可以调用一下两个函数进行判断
如果feof函数为真,则读取到文件结尾
如果ferror函数为真,则读取失败
int feof(FILE *stream);
int ferror(FILE *stream);
fwrite|fread的代码示例
1.3 sprintf | snprintf
当调用fwrite函数时,把一个整数转换为二进制,在把二进制的字符形式写入到文件中,展示给程序员(看不懂)
把整数,小数转换为字符串,把字符串通过二进制的形式写入到文件中,那么在文件中显示的结果就是本身
sprintf|snprintf 都是把整数,小数等转换为字符串
功能:把不同的数据类型那个转换为字符串存到str指针指向的内存中,可能数组越界
格式:
int sprintf(char *str, const char *format, ...);
参数:
format: 格式串 由字符 汉字 占位符组成
...:可变参数 个数可变,类型可变,由格式串的占位符决定
str: 存储格式串中的内容
返回值:
成功返回输出字符的个数,失败返回负数
int a=100;
char str[128]={0};
sprintf(str,"%d",a); ---->str="100"
———————————————————————————————————————————————————
功能:把不同的数据类型那个转换为字符串存到str指针指向的内存中,解决数据越界
格式:int snprintf(char *str, size_t size, const char *format, ...);
参数:
format: 格式串 由字符 汉字 占位符组成
...:可变参数 个数可变,类型可变,由格式串的占位符决定
str: 存储格式串中的内容
size: str指针指向的内存字节大小 sizeof(str)
返回值:
成功返回输出字符的个数,失败返回负数
printf\fprintf\sprintf\snprintf之间的区别?
1.printf: 格式串输出,会在当前终端打印输出结果
2.fprintf:文件的写入,可以写入不同的数据类型(int,float char char*)
3.sprintf: 把整数,小数等转换为字符串
4.snprintf: 类似sprintf,可以指定字符串的长度,防止在转换时穿线越界
sprintf |snprintf 代码示例
1.4 bzero | memset 不是IO函数
功能:清0
#include <strings.h>
void bzero(void *s, size_t n);
参数:
void *s: 清0的变量地址
n: 字节大小
eg:
int arr[]={1,2,3};
bzero(arr,sizeof(arr));
_____________________________________
功能:实现内存清0 -1 字符
格式:
#include <string.h>
void *memset(void *s, int c, size_t n);
参数:
void*s: 清0的地址
c: 清的值 可以0 -1 任意字符
n: 总字节大小 sizeof()
返回值:
返回s的地址
eg:
int arr={1,2,3};
memset(arr,0,sizeof(arr)); 清0
memset(arr,-1,sizeof(arr)); 请-1
char str[]="hello";
memset(str,'c',sizeof(str)); 清字符c
1.5 缓冲区
只有标准IO函数存在缓冲区
1.5.1 全缓冲
全缓冲的对象:使用fopen函数打开文件后,返回一个流指针,此时这就是全缓冲
全缓冲的大小:4096字节----->4k
全缓冲的刷新机制:
1.缓冲区满
int main(int argc, const char *argv[])
{
FILE* fp=fopen("./one.txt","w");
if(NULL==fp)
{
PRINT_ERROR("fopen error");
}
//全缓冲的大小
for(int i=0;i<4097;i++)
{
if( fputc('a',fp)==EOF)
{
printf("fputc error\n");
return -1;
}
}
while(1);
fclose(fp);
return 0;
}
2. 使用fflush函数进行刷新 常用
功能:刷新缓冲区
格式:
#include <stdio.h>
int fflush(FILE *stream);
参数: stream:流指针
返回值:
成功返回0,失败返回EOF 跟新errno
3.使用fclose函数关闭流指针
4.使用return关闭
5.使用exit退出实现刷新
功能:退出进程,刷新缓冲区
格式:#include <stdlib.h>
void exit(int status);
参数:
status: 退出状态值 写0就行
eg:exit(0)
1.5.2 行缓冲
行缓冲的对象:特殊流指针stdin stdout
行缓冲的大小:1024字节-----》1K
int main(int argc, const char *argv[])
{
fprintf(stdout,"hello");
//行换从的大小
int len=stdout->_IO_buf_end-stdout->_IO_buf_base;
printf("len=%d\n",len);
int a;
fscanf(stdin,"%d",&a);
len=stdin->_IO_buf_end-stdin->_IO_buf_base;
printf("len=%d\n",len);
return 0;
}
行缓冲的刷新机制:
1.行缓冲区满
2.使用fflush函数进行刷新 常用
3.使用fclose函数关闭流指针
4.使用return关闭
5.使用exit退出实现刷新
6.\n可以刷新行缓冲
7.读写转换
1.5.3 无缓冲
无缓冲的对象:stderr
大小:0
无缓冲一般用于打印错误信息,防止错误信息存在缓冲区未被刷新的情况
stderr的时效性比stdou强,但是速度慢,因为没有缓冲区
1.6 标准IO中的特殊流指针
当main函数启动之前,会自动创建三个特殊的流指针stdin stdout stderr
流指针 |
解释 |
等价关系 |
文件描述符 |
stdin |
标准输入流指针,实现输入 |
gets--->fgets( str,sizeof(str),stdin) getchar-->fgetc('a',stdin) scanf--->fscanf(stdin,"%d",&a) |
0 |
stdout |
标准输出流指针,实现输出 |
puts --->fputs(str,stdout) putchar-->fputc printf-->fprintf |
1 |
stderr |
标准错误输出流指针 |
perror-->fprintf(stderr,"error"); |
2 |
二、时间函数
2.1 time
功能:获取此时到1970-1-1 0:0:0 的时间差,单位秒
#include <time.h>
time_t time(time_t *tloc);
参数:
参数:tloc 该指针指向的存储存储秒数差,如果是NULL,则不获取
返回值:
成功返回秒数差,失败返回-1
time的代码示例
2.2 localtime
功能:获取此时到1970-1-1 0:0:0 的秒数差,转换为年月日时分秒
格式 #include <time.h>
struct tm *localtime(const time_t *timep);
参数:
timep: time函数获取的秒数差
返回值: 成功返回一个struct tm的指针,失败返回NULL,跟新错误码
struct tm * 时间结构体
struct tm {
int tm_sec; /* Seconds (0-60) */ 秒
int tm_min; /* Minutes (0-59) */ 分
int tm_hour; /* Hours (0-23) */ 时
int tm_mday; /* Day of the month (1-31) */ 天
int tm_mon; /* Month (0-11) */ 月+1
int tm_year; /* Year - 1900 */ 年+1900
int tm_wday; /* Day of the week (0-6, Sunday = 0) */ 星期
int tm_yday; /* Day in the year (0-365, 1 Jan = 0) */ 一年的第几天
int tm_isdst; /* Daylight saving time */ 夏令时
};
localtime代码示例
三、练习
3.1 将当前的时间写入到time. txt的文件中,如果ctrl+c退出之后,在再次执行支持断点续写
1.2022-04-26 19:10:20
2.2022-04-26 19:10:21
3.2022-04-26 19:10:22
//按下ctrl+c停止,再次执行程序
4.2022-04-26 20:00:00
5.2022-04-26 20:00:01
#include "head.h"
int main(int argc, const char *argv[])
{
FILE *fp=fopen("./time.txt","a+");
if(NULL==fp)
PRINTF_ERROR("fopen error");
int count=0;
rewind(fp);
while(1)
{
char buf[128];
if(fgets(buf,sizeof(buf),fp)!=NULL)
count++;
else
break;
}
while(1)
{
fseek(fp,0,SEEK_END);
count++;
time_t sec;
time(&sec);
struct tm *t=localtime(&sec);
if(NULL==t)
PRINTF_ERROR("localtime error");
fprintf(fp,"%d.%04d-%02d-%02d %02d:%02d:%02d\n",count,t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
printf("%d.%04d-%02d-%02d %02d:%02d:%02d\n",count,t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
sleep(1);
}
fclose(fp);
return 0;
}
3.2 使用fwrite和fread函数实现图片的拷贝
prt sc ---截图
eog 文件名 ----》打开文件
#include "head.h"
int main(int argc, const char *argv[])
{
FILE *fp=fopen("./02_截图.png","r");
if(NULL==fp)
PRINTF_ERROR("fopen error");
FILE *fp2=fopen("./cp_02_截图.png","w+");
if(NULL==fp2)
PRINTF_ERROR("fopen error");
fseek(fp,0,SEEK_END);
int size=ftell(fp);
char str[size+1];
rewind(fp);
fread(str,size+1,1,fp);
fwrite(str,size+1,1,fp2);
fclose(fp);
fclose(fp2);
return 0;
}