文章目录

  • 1.标准IO
    • 1.1什么是FILE
    • 1.2fopen的使用
    • 1.3fclose的使用
    • 1.4关于错误码的问题
      • 1.4.1strerror函数的使用
      • 1.4.2perror函数的使用
    • 1.5fgetc/fputc函数使用
      • 1.5.1fputc函数的使用
      • 1.5.2fgetc函数的使用
      • 1.5.3请使用fgetc统计文件的行数
      • 1.5.4请使用fgets/fputc拷贝一个文件
    • 1.6fgets/fputs函数使用
      • 1.6.1使用fgets从stdin中读取字符串
      • 1.6.2fputs函数的使用
      • 1.6.3使用fgets统计文件的行号
      • 1.6.4使用fgets和fputs实现文件的拷贝
  • 2.格式化控制相关的函数
    • 2.1sprintf函数使用(将字符串格式化到数组中)
    • 2.2snprintf函数使用(将字符串格式化到数组中)
    • 2.3fprintf的使用(将格式化后的字符串向对应的文件指针中输出)
  • 3.fread/fwrite函数的使用
    • 3.1fwrite/fread函数的使用
      • 3.1.1fwrite/fread整数读写
      • 3.1.2fwrite/fread字符串读写
      • 3.1.3fwrite/fread结构体读写
      • 3.1.4feof/ferror函数的使用
      • 3.1.5使用fread/fwrite实现拷贝文件的功能
  • 4.关于光标位置的相关函数(fseek/ftell/rewind)
  • 作业1
    • 获取系统时间的函数
    • sprintf函数的使用
    • 作业:向文件中打印系统时间
  • 作业2
    • 使用标准IO对文件打马赛克
    • 使用标准IO对图片操作
    • bmp的图片格式详解
    • bmp文件操作实例
    • 给图片打马赛克
  • 作业3:
    • 使用文件IO实现,将当前的时间写入到tim.txt的文件中
    • 使用文件IO写入时间

1.标准IO

1.1什么是FILE

在使用fopen打开文件的时候,会返回一个FILE*的指针(文件指针),FILE的本质是一个结构体,在这个结构体中记录所有的关于文件的信息,以后对文件的操作通过FILE*来完成。

/usr/include/

ctags -R //创建索引

vi -t FILE //查找FILE实现的位置

typedef struct _IO_FILE FILE;  struct _IO_FILE {    char* _IO_buf_base;   //缓冲区的首地址char* _IO_buf_end;    //缓冲区的结束地址...
};

在一个正在执行的程序中,已经创建了三个FILE的指针,如下:

stdin: 标准输入 (scanf)

stdout 标准输出 (printf)

stderr: 标准出错

1.2fopen的使用

 man 后跟的数字的含义2   系统调用(内核提供的函数)3   库调用(程序库中的函数)
#include <stdio.h>
FILE *fopen(const char *pathname, const char *mode);
功能:使用标准IO打开文件
参数:@pathname: 路径/文件名 "./hello.txt"@mode:打开文件的方式 "r" "r+"r:以只读的方式打开文件,将文件中的光标定位在文件的开头r+:以读写的方式打开文件,将文件中的光标定位在文件的开头w:以只写的方式打开文件,如果文件不存在就创建文件,如果文件存在就清空,将光标定位在开头 w+:以读写的方式打开文件,如果文件不存在就创建文件,如果文件存在就清空,将光标定位在开头  a:以追加(结尾写)的方式打开文件,如果文件不存在就创建文件,将光标定位在文件的结尾a+:以读和追加(结尾写)的方式打开文件,如果文件不存在就创建文件,如果读从开头读,写在文件的结尾写
返回值:成功返回文件指针,失败返回NULL,置位错误码

fopen的实例:

#include <stdio.h>int main(int argc,const char * argv[])
{//定义文件指针FILE *fp;//以只写的方式打开文件// fp = fopen("./hello.txt","w");// if(fp == NULL){//     printf("create file error\n");//     return -1;// }//以只读的方式打开文件,文件不存在会报错// fp = fopen("./hello.txt","r");// if(fp == NULL){//     printf("create file error\n");//     return -1;// }//以追加的方式打开文件,如果文件存在,不会清空(追加)fp = fopen("./hello.txt","a");if(fp == NULL){printf("create file error\n");return -1;}return 0;
}

1.3fclose的使用

int fclose(FILE *stream);
功能:关闭文件
参数:@stream:文件指针
返回值:成功返回0,失败返回EOF(end of file),并置位错误码#define EOF (-1)

fclose的使用:

#include <stdio.h>int main(int argc,const char * argv[])
{FILE *fp;//以只写的方式打开文件fp = fopen("./hello.txt","w");if(fp == NULL){printf("create file error\n");return -1;}//关闭文件if(fclose(fp)<0){printf("close file error\n");return -1;}if(fclose(stdin)<0){printf("close file error\n");return -1;}if(fclose(stdout)<0){printf("close file error\n");return -1;}if(fclose(stderr)<0){printf("close file error\n");return -1;}return 0;
}

1.4关于错误码的问题

在文件IO或标准IO相关接口被调用的时候,如果出错了,操作系统会给应用程序返回错误码。过程如下:

#include <string.h>
char *strerror(int errnum);
功能:根据错误码转换错误信息
参数:@errnum:这个是错误码,包含#include <errno.h>extern int errno;
返回值:错误信息字符串void perror(const char *s);
功能:打印错误码对应的信息
参数:@s:用户附加的信息
返回值:无

1.4.1strerror函数的使用

#include <stdio.h>
#include <errno.h>
#include <string.h>
//extern int errno;int main(int argc,const char * argv[])
{//定义文件指针FILE *fp;//以只读的方式打开文件,文件不存在会报错fp = fopen("./hello.txt","r");if(fp == NULL){printf("%s\n",strerror(errno));return -1;}fclose(fp);return 0;
}

1.4.2perror函数的使用

#include <stdio.h>int main(int argc,const char * argv[])
{//定义文件指针FILE *fp;//以只读的方式打开文件,文件不存在会报错fp = fopen("./hello.txt","r");if(fp == NULL){perror("open hello.txt");return -1;}fclose(fp);return 0;
}

1.5fgetc/fputc函数使用

int fgetc(FILE *stream);
功能:从文件中读取一个字符
参数:@stream:文件指针
返回值:成功返回字符的ascii,读取文件的结尾EOF,失败返回errorint fputc(int c, FILE *stream);
功能:向文件中写一个字符
参数:@c:被写字符的ascii@stream:文件指针
返回值:成功返回ascii,失败返回EOF

1.5.1fputc函数的使用

#include <stdio.h>int main(int argc, const char *argv[])
{FILE *fp;fp = fopen("./test.txt", "w");if (fp == NULL){perror("fopen error");return -1;}fputc('h', fp);fputc('e', fp);fputc('l', fp);fputc('l', fp);fputc('o', fp);fclose(fp);return 0;
}

1.5.2fgetc函数的使用

#include <stdio.h>int main(int argc,const char * argv[])
{FILE *fp;fp = fopen("./01fopen.c","r");if(fp == NULL){perror("fopen error");return -1;}int i=0;while(i++<30){printf("%c",fgetc(fp));}puts("");fclose(fp);return 0;
}

1.5.3请使用fgetc统计文件的行数

#include <stdio.h>int main(int argc,const char * argv[])
{FILE * fp;char ch;int count=0;//1.通过命令行输入可执行程序和文件名,否则就出错if(argc != 2){printf("input error,try agian\n");printf("usage:./a.out filename\n");return -1;}//2.以只读的方式打开文件if((fp = fopen(argv[1],"r"))==NULL){perror("fopen error");return -1;}//3.只要没有到文件结尾,循环就一直执行(EOF)while((ch = fgetc(fp)) != EOF){if(ch == '\n'){   //如果文件中有'\n'就让行号+1count++;}}printf("file line number = %d\n",count+1);//关闭文件fclose(fp);return 0;
}

1.5.4请使用fgets/fputc拷贝一个文件

#include <stdio.h>int main(int argc, const char *argv[])
{FILE *sfp, *dfp;char ch;if (argc != 3){printf("input error,try agian\n");printf("usage:./a.out srcfile destfile\n");return -1;}if ((sfp = fopen(argv[1], "r")) == NULL){perror("fopen src file error");return -1;}if ((dfp = fopen(argv[2], "w")) == NULL){perror("fopen dest file error");return -1;}while ((ch = fgetc(sfp)) != EOF){fputc(ch,dfp);}fclose(sfp);fclose(dfp);return 0;
}

1.6fgets/fputs函数使用

char *fgets(char *s, int size, FILE *stream);
功能:从文件指针中读取一个字符串注:遇到换行或者EOF的停止读取,换行符也会被读取到s的缓冲区中,并且在换行符之后存储一个'\0'结束符
参数:@s:用来存储读取到字符的首地址@size:读取的大小(最多读取size-1)@stream:文件指针
返回值:成功返回s,失败返回NULL

int fputs(const char *s, FILE *stream);
功能:将s字符串中的内容写入到文件中
参数:@s:首地址@stream:文件指针
返回值:成功返回写入的字符的个数,失败返回EOF

1.6.1使用fgets从stdin中读取字符串

#include <stdio.h>
#include <string.h>int main(int argc,const char * argv[])
{char buffer[1024];printf("input string > ");fgets(buffer,sizeof(buffer),stdin);//将读取到的换行符设置为'\0'//hello\n//buffer=hello'\n''\0'//strlen(buffer)=6//buffer[5]='\0'buffer[strlen(buffer)-1]='\0';printf("%s\n",buffer);return 0;
}

1.6.2fputs函数的使用

#include <stdio.h>int main(int argc,const char * argv[])
{FILE*fp;//向标准输出中写入字符串fputs("helloworld",stdout);//向标准出错中写入字符串fputs("helloworld",stderr);if ((fp = fopen("hello.txt", "w")) == NULL){perror("fopen file error");return -1;}fputs("i love china",fp);fclose(fp);return 0;
}

1.6.3使用fgets统计文件的行号

#include <stdio.h>
#include <string.h>int main(int argc,const char * argv[])
{FILE *fp;char s[10];int line=0;if(argc != 2){fputs("input error,try again\n",stderr);fputs("usage:./a.out file\n",stderr);}if((fp = fopen(argv[1],"r"))== NULL){perror("fopen error");return -1;}while(fgets(s,sizeof(s),fp)!=NULL){if(strlen(s)==sizeof(s)-1){if(s[sizeof(s)-2]!='\n'){continue;}}line++;}printf("line = %d\n",line);fclose(fp);return 0;
}

1.6.4使用fgets和fputs实现文件的拷贝

#include <stdio.h>int main(int argc, const char *argv[])
{FILE *sfp, *dfp;char s[40];if (argc != 3){printf("input error,try agian\n");printf("usage:./a.out srcfile destfile\n");return -1;}if ((sfp = fopen(argv[1], "r")) == NULL){perror("fopen src file error");return -1;}if ((dfp = fopen(argv[2], "w")) == NULL){perror("fopen dest file error");return -1;}while(fgets(s,sizeof(s),sfp)!=NULL){fputs(s,dfp);}fclose(sfp);fclose(dfp);return 0;
}

2.格式化控制相关的函数

2.1sprintf函数使用(将字符串格式化到数组中)

int sprintf(char *str, const char *format, ...);
功能:向str中进行字符串的格式化
参数:@str:首地址@format:控制格式
返回值:成功格式化字符的个数,失败返回负数char s[50];
sprintf(s,"%4d-%02d-%02d %02d:%02d:%02d\n",tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec);
把双引号中的字符串存放在s的数组中s="2022-4-26 17:30:20"fputs(s,fp); //将s中的字符串写入到文件中

注:当使用sprintf往数组中写入字符的时候,如果出现越界,虽然编译的时候会提示警告,但是在程序运行的时候有多少字符就格式化多少字符,这个内存越界的错误

2.2snprintf函数使用(将字符串格式化到数组中)

int snprintf(char *str, size_t size, const char *format, ...);
功能:将字符串格式化到str的数组中
参数:@str:存放格式化后的字符串的内存首地址@size:大小(字符size-1)@format:格式化的控制格式
返回值:成功返回字符的个数,失败返回负数
#include <stdio.h>int main(int argc,const char * argv[])
{char s[10];snprintf(s,sizeof(s),"%s","helloworld1234");printf("s = %s\n",s);//上输入的字符个数大于s的大小的时候,最多格式化sizeof(s)-1个字符,在s最后一个字符的//位置补上'\0'return 0;
}

2.3fprintf的使用(将格式化后的字符串向对应的文件指针中输出)

int fprintf(FILE *stream, const char *format, ...);
功能:将格式化后的字符串向对应的文件指针中输出
参数:@stream:文件指针@format:控制格式
返回值:成功返回>0,失败返回<0
#include <stdio.h>
#include <time.h>
#include <string.h>
int getLineNum(FILE*fp)
{char s[10];int line=0;while (fgets(s, sizeof(s), fp) != NULL){if (strlen(s) == sizeof(s) - 1){if (s[sizeof(s) - 2] != '\n'){continue;}}line++;}return line;
}
int main(int argc, const char *argv[])
{FILE *fp;time_t time_new, time_old;struct tm *tm;char s[50];int line = 0;if ((fp = fopen("tim.txt", "a+")) == NULL){perror("fopen src file error");return -1;}line=getLineNum(fp);printf("line = %d\n",line);while (1){time(&time_new);tm = localtime(&time_new);if (tm == NULL){perror("change time error");return -1;}if (time_new != time_old){time_old = time_new;fprintf(fp,"%3d.%4d-%02d-%02d %02d:%02d:%02d\n", ++line, tm->tm_year + 1900,tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);fflush(fp);}}fclose(fp);return 0;
}

3.fread/fwrite函数的使用

#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:从文件中读取数据到ptr中
参数:@ptr:保存读取到数据的首地址@size:每一项的大小@nmemb:项的个数@stream:文件指针
返回值:成功返回读取到的项目的个数,如果是失败或者读取到的文件的结尾返回值是要小于nnemb或者0错误还是读取到文件的结尾需要通过feof(fp)或者ferror(fp)来判断size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
功能:将ptr中的数据写入到文件中
参数:@ptr:数据的首地址@size:每一项的大小@nmemb:项的个数@stream:文件指针
返回值:成功返回写的项目的个数,如果是失败返回值是要小于nnemb或者0

3.1fwrite/fread函数的使用

3.1.1fwrite/fread整数读写

#include <stdio.h>#define PRINT_ERR(msg) do{perror(msg);return -1;}while(0)
int main(int argc,const char * argv[])
{FILE *fp;int num=1234;if((fp = fopen("test.txt","w"))==NULL)PRINT_ERR("fopen error");fwrite(&num,4,1,fp);//写入的整数,虽然在文本编辑器中看到的是乱码,但是可以通过fread正确读取到fclose(fp);return 0;
}
#include <stdio.h>#define PRINT_ERR(msg) do{perror(msg);return -1;}while(0)
int main(int argc,const char * argv[])
{FILE *fp;int num;if((fp = fopen("test.txt","r"))==NULL)PRINT_ERR("fopen error");fread(&num,4,1,fp);printf("read num = %d\n",num);fclose(fp);return 0;
}

3.1.2fwrite/fread字符串读写

#include <stdio.h>
#include <string.h>
#define PRINT_ERR(msg) do{perror(msg);return -1;}while(0)
int main(int argc,const char * argv[])
{FILE *fp;char str[] = "this is test for fwrite string";if((fp = fopen("test.txt","w"))==NULL)PRINT_ERR("fopen error");fwrite(str,1,strlen(str),fp);fclose(fp);return 0;
}
#include <stdio.h>#define PRINT_ERR(msg) do{perror(msg);return -1;}while(0)
int main(int argc,const char * argv[])
{FILE *fp;char str[50] ;if((fp = fopen("test.txt","r"))==NULL)PRINT_ERR("fopen error");fread(str,1,sizeof(str),fp);printf("read str = %s\n",str);fclose(fp);return 0;
}

3.1.3fwrite/fread结构体读写

typedef struct{char name[20];char sex;int score;
}stu_t;
#include <stdio.h>
#include <string.h>
#define PRINT_ERR(msg) do{perror(msg);return -1;}while(0)typedef struct{char name[20];char sex;int score;
}stu_t;int main(int argc,const char * argv[])
{FILE *fp;stu_t stu = {"zhangsan",'m',99,};if((fp = fopen("test.txt","w"))==NULL)PRINT_ERR("fopen error");fwrite(&stu,sizeof(stu),1,fp);fclose(fp);return 0;
}
#include <stdio.h>#define PRINT_ERR(msg) do{perror(msg);return -1;}while(0)
typedef struct{char name[20];char sex;int score;
}stu_t;
int main(int argc,const char * argv[])
{FILE *fp;stu_t stu;if((fp = fopen("test.txt","r"))==NULL)PRINT_ERR("fopen error");fread(&stu,sizeof(stu),1,fp);printf("name = %s,sex = %c,score = %d\n",stu.name,stu.sex,stu.score);fclose(fp);return 0;
}

3.1.4feof/ferror函数的使用

#include <stdio.h>
#include <string.h>
#define PRINT_ERR(msg) do{perror(msg);return -1;}while(0)int main(int argc,const char * argv[])
{FILE *fp;char buf[10] = {0};if((fp = fopen("test.txt","r"))==NULL)PRINT_ERR("fopen error");while(1){//memset将buf中的内容全部写为0,大小是是sizeof(buf)memset(buf,0,sizeof(buf));fread(buf,1,sizeof(buf),fp);printf("%s",buf);if(feof(fp)){fprintf(stderr,"读取到文件的结尾了\n");break;}else if(ferror(fp)){fprintf(stderr,"读取到文件出错了\n");break;}}fclose(fp);return 0;
}

3.1.5使用fread/fwrite实现拷贝文件的功能

#include <stdio.h>
#include <string.h>
#define PRINT_ERR(msg) \do                 \{                  \perror(msg);   \return -1;     \} while (0)int main(int argc, const char *argv[])
{FILE *sfp, *dfp;char buf[10];int ret;if(argc != 3){fprintf(stderr,"input error, tryagain\n");fprintf(stderr,"usage:./a.out srcfile destfile");return -1;}if ((sfp = fopen(argv[1], "r")) == NULL)PRINT_ERR("fopen error");if ((dfp = fopen(argv[2], "w")) == NULL)PRINT_ERR("fopen error");//如果没有到文件的结尾并且没有出错,就执行循环//如果读取到结尾或者出错,就退出循环while (!(feof(sfp) || ferror(sfp))){// memset将buf中的内容全部写为0,大小是是sizeof(buf)//memset(buf, 0, sizeof(buf));//上述的memset可以不写,原因是通过ret来决定写入字符的个数//即使buf中没有'\0'的结束符,也是可以正常执行的ret = fread(buf, 1, sizeof(buf), sfp);fwrite(buf,1,ret,dfp);}fclose(sfp);fclose(dfp);return 0;
}

4.关于光标位置的相关函数(fseek/ftell/rewind)

int fseek(FILE *stream, long offset, int whence);
功能:修改光标的位置
参数:@stream:文件指针@offset:偏移>0 向后偏移=0  不偏移<0  向前偏移@whence:SEEK_SET,开头SEEK_CUR,当前位置SEEK_END,结尾
返回值:成功返回0,失败返回-1置位错误码
eg:fseek(fp,0,SEEK_SET);将光标定位在文件的开头fseek(fp,10,SEEK_SET);从文件的开头向后偏移10个字节fseek(fp,10,SEEK_CUR);从光标当前位置向后偏移10个字节fseek(fp,-10,SEEK_END);从文件结尾向前偏移10个字节fseek(fp,0,SEEK_END);将光标定位在文件结尾          long ftell(FILE *stream)
功能:获取光标当前的位置
参数:@stream:文件指针
返回值:成功返回光标的位置,失败返回-1,置位错误码
eg:
fseek(fp,0,SEEK_END);
ftell(fp);   ===>功能统计文件所占用的字符的个数(大小)void rewind(FILE *stream);
功能:恢复光标的位置到文件的开头
参数:@stream:文件指针
返回值:无
eg:rewind(fp) == fseek(fp,0,SEEK_SET)  等价
#include <stdio.h>
#define PRINT_ERR(msg) \do                 \{                  \perror(msg);   \return -1;     \} while (0)int main(int argc,const char * argv[])
{FILE * fp;char s[50];if ((fp = fopen("./test.txt", "r")) == NULL)PRINT_ERR("fopen error");fseek(fp,6,SEEK_SET);fgets(s,sizeof(s),fp);printf("s = %s\n",s);fclose(fp);return 0;
}

思考:如果通过追加的方式打开文件,修改光标的位置是否能影响读写?

答:如果是以"a"打开文件,修改不了光标的位置,在想文件中写数据的时候总是在结尾写

如果是以"a+"打开文件,修改光标影响不了写的光标的位置,但是可以影响读的光标的位置

#include <stdio.h>
#define PRINT_ERR(msg) \do                 \{                  \perror(msg);   \return -1;     \} while (0)int main(int argc,const char * argv[])
{FILE * fp;char s[50];if ((fp = fopen("./test.txt", "a")) == NULL)PRINT_ERR("fopen error");fseek(fp,0,SEEK_SET);  //将追加是结尾的光标修改到文件的开头,在向文件中写//数据的时候依然是在结尾写,影响不了写的光标的位置fprintf(fp,"i am test fseek func append");fclose(fp);return 0;
}
#include <stdio.h>
#define PRINT_ERR(msg) \do                 \{                  \perror(msg);   \return -1;     \} while (0)int main(int argc,const char * argv[])
{FILE * fp;char s[50];if ((fp = fopen("./test.txt", "a+")) == NULL)PRINT_ERR("fopen error");fseek(fp,6,SEEK_SET);   //可以影响读的光标的位置fgets(s,sizeof(s),fp);printf("s = %s\n",s);fclose(fp);return 0;
}

作业1

将当前的时间写入到tim.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 <time.h>
time_t time(time_t *tloc);
功能:获取系统当前时间的秒钟数
参数:@tloc:如果是NULL,通过返回值返回秒钟数如果不是NULL,通过参数得到秒钟数
返回值:成功返回time_t的地址,失败返回(time_t*)-1,并置位错误码
struct tm *localtime(const time_t *timep);
功能:将秒钟转化为年月日时分秒的格式
参数:@timep:秒钟数
返回值:成功返回tm的结构体指针,失败返回NULL,置位错误码struct tm {int tm_sec;   //秒钟int tm_min;   //分钟int tm_hour;  //小时int tm_mday;  //天int tm_mon;   //月+1int tm_year;  //年+1900int tm_wday;   /* 周几 (0-6, Sunday = 0) */int tm_yday;   //一年内的第几天int tm_isdst;  //夏令时,已经被废弃了};
#include <stdio.h>
#include <time.h>
int main(int argc,const char * argv[])
{time_t time_v;struct tm *tm;time(&time_v);tm = localtime(&time_v);if(tm == NULL){perror("change time error");return -1;}printf("%4d-%02d-%02d %02d:%02d:%02d\n",tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec);return 0;
}

sprintf函数的使用

int sprintf(char *str, const char *format, ...);
功能:向str中进行字符串的格式化
参数:@str:首地址@format:控制格式
返回值:成功格式化字符的个数,失败返回负数char s[50];
sprintf(s,"%4d-%02d-%02d %02d:%02d:%02d\n",tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec);
把双引号中的字符串存放在s的数组中s="2022-4-26 17:30:20"fputs(s,fp); //将s中的字符串写入到文件中
#include <stdio.h>
#include <time.h>
int main(int argc,const char * argv[])
{FILE *fp;time_t time_v;struct tm *tm;char s[50];if ((fp = fopen("hello.txt", "a")) == NULL){perror("fopen src file error");return -1;}time(&time_v);tm = localtime(&time_v);if(tm == NULL){perror("change time error");return -1;}sprintf(s,"%4d-%02d-%02d %02d:%02d:%02d\n",tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec);fputs(s,fp);fclose(fp);return 0;
}
#include <stdio.h>
#include <time.h>
int main(int argc,const char * argv[])
{FILE *fp;time_t time_v;struct tm *tm;char s[50];if ((fp = fopen("hello.txt", "a")) == NULL){perror("fopen src file error");return -1;}time(&time_v);tm = localtime(&time_v);if(tm == NULL){perror("change time error");return -1;}sprintf(s,"%4d-%02d-%02d %02d:%02d:%02d\n",tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec);fputs(s,fp);fclose(fp);return 0;
}

作业:向文件中打印系统时间

#include <stdio.h>
#include <time.h>
#include <string.h>
int getLineNum(FILE*fp)
{char s[10];int line=0;while (fgets(s, sizeof(s), fp) != NULL){if (strlen(s) == sizeof(s) - 1){if (s[sizeof(s) - 2] != '\n'){continue;}}line++;}return line;
}
int main(int argc, const char *argv[])
{FILE *fp;time_t time_new, time_old;struct tm *tm;char s[50];int line = 0;if ((fp = fopen("tim.txt", "a+")) == NULL){perror("fopen src file error");return -1;}line=getLineNum(fp);printf("line = %d\n",line);while (1){time(&time_new);tm = localtime(&time_new);if (tm == NULL){perror("change time error");return -1;}if (time_new != time_old){time_old = time_new;sprintf(s, "%3d.%4d-%02d-%02d %02d:%02d:%02d\n", ++line, tm->tm_year + 1900,tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);fputs(s, fp);fflush(fp);}}fclose(fp);return 0;
}

作业2

使用标准IO对文件打马赛克

使用标准IO对图片操作

自己编写一个head.h的头文件,将它放在/usr/include/目录下,以后包含这个头文件,就可以使用打印的宏

#ifndef __HEAD_H__
#define __HEAD_H__#include <stdio.h>
#include <string.h>#define PRINT_ERR(msg) do{ \perror(msg);\return -1;\}while(0)#endif

bmp的图片格式详解

参看这篇文章:https://www.ivu4e.com/blog/image/2019-09-04/183.html

在ubuntu终端上可以通过eog xxx.bmp打开一张图片

bmp文件操作实例

#include <head.h>int main(int argc, const char *argv[])
{FILE *fp;int img_size;unsigned char color[3] = {0x0, //蓝0x0,//绿0xff};  //红if (argc != 2){fprintf(stderr, "input error,try again\n");fprintf(stderr, "usage:./a.out picture.bmp\n");return -1;}if ((fp = fopen(argv[1], "r+")) == NULL)PRINT_ERR("fopen error");fseek(fp, 2, SEEK_SET);fread(&img_size, 4, 1, fp);printf("img_size = %d\n", img_size);fseek(fp, 54, SEEK_SET); //跳过图片的头for (int j = 0; j < 100; j++) //写多少行{for (int i = 0; i < 2560; i++) //每一行内的像素点{fwrite(color, 3, 1, fp); //每一个点占3个字节}}fclose(fp);return 0;
}

给图片打马赛克

#include <head.h>
#include <stdlib.h>typedef struct{unsigned int img_size; //图片的大小unsigned int img_width;//图片的宽unsigned int img_high; //图片的高unsigned short img_bitcount; //一个像素点占用的bit(24bit)
}image_info_t;typedef struct{unsigned char b;unsigned char g;unsigned char r;
}point_t;void show_image_info(image_info_t *info)
{printf("size = %d,width = %d,high = %d,bitcount = %d\n",info->img_size,info->img_width,info->img_high,info->img_bitcount);
}void get_image_info(FILE*fp,image_info_t *info)
{fseek(fp,2,SEEK_SET);fread(&info->img_size,1,4,fp); //图片的大小fseek(fp,18,SEEK_SET);fread(&info->img_width,1,4,fp); //图片的宽fread(&info->img_high,1,4,fp); //读取图片的高fseek(fp,2,SEEK_CUR);fread(&info->img_bitcount,1,2,fp); //像素点占用的bit
}void copy_image_file(FILE*sfp,FILE*dfp)
{int ret;char buf[1024] = {0};while(!(feof(sfp)||ferror(sfp))){ret = fread(buf,1,sizeof(buf),sfp);fwrite(buf,1,ret,dfp);}return;
}
void set_image_mosaic(FILE *fp,image_info_t *info,int x,int y)
{int i,j,k,w;point_t color = {0,0,0xff};char *buffer = (char *)malloc((info->img_width)*(info->img_high)*3);//point_t arr[612][440];//1.将图像读取回来fseek(fp,54,SEEK_SET);fread(buffer,1,(info->img_size-54),fp);//2.修改//i:整体的高/10//j:整体的宽除以10//k:块的高//w:块的宽for(i=0;i<info->img_high/y;i++){for(j=0;j<info->img_width/x;j++){//读取小方块中最左上角的像素点color = *(point_t *)(buffer+(j*3*x)+(i*y*info->img_width*3));for(k=0;k<y;k++){for(w=0;w<x;w++){*(point_t*)(buffer+w*3+(k*info->img_width*3)+(j*3*x)+(i*y*info->img_width*3)) = color;}}}}//3.重新将图像写回去fseek(fp,54,SEEK_SET);fwrite(buffer,1,(info->img_size-54),fp);
}
int main(int argc, char const *argv[])
{FILE *sfp,*dfp;int size;image_info_t info;char new_name[20] = {0};if(argc != 2){fprintf(stderr,"input error,try again\n");fprintf(stderr,"usage:./a.out xxxx.bmp\n");return -1;}//1.打开文件并拷贝文件 milaoshu.bmpif((sfp = fopen(argv[1],"r"))==NULL)PRINT_ERR("open error");//构造一个新图片的字符串  new_milaoshu.bmpsnprintf(new_name,sizeof(new_name),"new_%s",argv[1]);//打开新图片,如果不存在就创建,如果存在就清空if((dfp = fopen(new_name,"w+"))==NULL)PRINT_ERR("open error");//图片的拷贝,将milaoshu.bmp-->new_milaoshu.bmp    copy_image_file(sfp,dfp);//2.获取图片前54个字节中有用的信息get_image_info(dfp,&info);show_image_info(&info);//3.尝试打马赛克//10,10:代表的是打马赛克每个小方块的大小//10*3= 30//10  = 10行set_image_mosaic(dfp,&info,10,10);//4.关闭源文件和目标文件fclose(sfp);   fclose(dfp); return 0;
}

作业3:

使用文件IO实现,将当前的时间写入到tim.txt的文件中

2022-04-26 19:10:20

2022-04-26 19:10:21

2022-04-26 19:10:22

使用文件IO写入时间

#include <head.h>
#include <time.h>int main(int argc, const char *argv[])
{int fd;time_t time_new, time_old;struct tm *tm;char s[50] = {0};if ((fd = open("tim.txt",O_RDWR|O_APPEND|O_CREAT,0664)) == -1)PRINT_ERR("open error");while (1){time(&time_new);tm = localtime(&time_new);if (tm == NULL){perror("change time error");return -1;}if (time_new != time_old){time_old = time_new;sprintf(s, "%4d-%02d-%02d %02d:%02d:%02d\n",tm->tm_year + 1900,tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);write(fd,s,strlen(s));}}close(fd);return 0;
}

Linux_标准IO相关推荐

  1. APUE(第五章)标准IO

    本章介绍的标准IO库,不仅是UNIX,多其他操作系统都实现了标准io库,比如windows,由ISO C标准说明 缓冲的重要性 流和FILE对象 标准IO库的操作是围绕流(stream)进行的. 标准 ...

  2. C++ Primer 第八章 标准IO库

    学习本章内容之前有必要对缓冲区的概念做一个基本了解,我引用了网上一片文章<C++编程对缓冲区的理解>,内容如下: 什么是缓冲区    缓冲区又称为缓存,它是内存空间的一部分.也就是说,在内 ...

  3. step4 . day1标准IO和文件IO

    标准IO:ANSI C中定义的一系列用于对IO操作的函数,(只能访问普通文件) 知识点:流指针:文件的操作,标准IO通常通过一个FILE的结构体,称这个结构体为流,他的指针称为流指针(系统自动打开的流 ...

  4. linux 流函数,标准IO函数库 - 二进制文件IO,流定位,创建临时文件和内存流

    1 二进制IO(Binary IO) 在前一篇我们了解了逐字符读写和逐行读写函数. 如果我们在读写二进制文件,希望以此读写整个文件内容,这两个函数虽然可以实现,但是明显会很麻烦且多次循环明显效率很低. ...

  5. 编程语言对比 标准io

    C++ 标准IO java 标准IO python标准IO

  6. 标准IO库--unix环境高级编程读书笔记

    标准IO库是C语言提供的一个库,不光存在于linux中,在windows中也是有的.标准IO库和文件IO的不同是,标准IO库是对文件IO(即系统调用)的封装,并且在用户层添加了一些缓冲区. 文件IO的 ...

  7. C++ Primer 第八章 标准IO库(转载)

    学习本章内容之前有必要对缓冲区的概念做一个基本了解,我引用了网上一片文章<C++编程对缓冲区的理解>,内容如下: 什么是缓冲区    缓冲区又称为缓存,它是内存空间的一部分.也就是说,在内 ...

  8. LinuxC语言简单实现图片加马赛克-标准IO实现

    1. 基于C语言实现,标准IO练习 2. 图片格式bmp BMP图片格式详解(获取图片前54个字节中有用的信息链接) 3. 代码实现 //标准IO实现 #include <stdio.h> ...

  9. 在标准IO库中,rewind函数作用?

    在标准IO库中,rewind函数作用? 将文件内部的位置指针重新指向一个流(数据流/文件)的开头 一个完整的信号生命周期包含4个重要的事件,这4个重要事件分别是? 信号诞生:信号在进程中注册完毕:信号 ...

最新文章

  1. 相对熵/KL散度(Kullback–Leibler divergence,KLD)
  2. 转代码判断邮箱是否合法
  3. Vue笔记(五):Vuex
  4. Python学习之路-基础知识1
  5. 赢者通吃自编码器(WTA-AE)
  6. 给.Net程序员和WEB程序员建议 (转自CSDN)
  7. (转)区块链:为什么说finchain是下一代金融应用平台
  8. 芒果数据库备份与还原
  9. 数据可视化实战案例分享
  10. 计算机类专业及行业认识,我对于计算机行业的看法
  11. 求齐次线性方程组的基础解系matlab,MATLAB学习笔记:齐次线性方程组的基础解系...
  12. 搭建sql注入平台及DVWA漏洞环境
  13. 计算机应用技术专业是属于文科生,计算机应用技术专业是文科还是理科
  14. AT32看门狗WDT使用方法
  15. CDN的基本概念与原理
  16. 抽象类和接口不能直接实例?
  17. 删除MySQL表的SQL语句-DROP-TABLE-简介
  18. 模拟股票涨跌功能(jquery应用4)
  19. 51单片机四位数码管的使用方法
  20. 科研中常用的计算机应用软件,研究生的日常软件(文献类软件使用介绍及心得)...

热门文章

  1. 人脸扫描建模_黑科技 | 3D人脸建模可以多简单?一张照片就搞定!
  2. c++详解缺省参数,缺省参数简介以及实际开发使用。
  3. 地球形状与重力场模型
  4. 5G SCMA MPA算法
  5. 计算机键盘怎么换键,电脑修改键盘按键的方法
  6. MVP、EMC、CRM、IoT、边缘计算盒子、系统群控、数字化赋能、EMS、冷媒
  7. 企业微信---第三方应用开发 笔记
  8. go语言negroni包介绍
  9. EndNote安装与使用
  10. 寻找真实IP-子域名查找