学习记录——day21 IO sprintf snprintf fread fwrite fprintf fscanf fseek

目录

有关系统时间的函数

1、有关时间的函数

sprintf/snprintf  将格式串转换为字符串

fprintf/fscanf  格式化读写函数

fprintf/fscanf  登录注册

fread/fwrite 模块化读写

使用fread、fwrite读写字符串

使用fread、fwrite读写字符串

使用fread、fwrite读写结构体

光标移动函数  fseek

使用标准IO完成对图像的操作

 作业

1、写一个日志文件,将出现启动后,每一秒的时间写入文件中

2、使用fread、fwrite完成两个文件的拷贝

3、实现对bmp图像的读写操作


调试用的宏

有关系统时间的函数

1、有关时间的函数

       #include <time.h>

       time_t time(time_t *tloc);
功能:获取系统时间,从1970年1月1日0时0分0秒,到目前累计的秒数
参数:用于接收的秒数
返回值:秒数
使用方式:
1、time_t  sys_time = time(NULL);
2、time_t  sys_time = 0;
    time(&sys_time);

       struct tm *localtime(const time_t *timep);
功能:将time_t 秒数,转换为时间类型的结构体
参数:time_t 类型的时间秒数
返回值:时间结构体
           struct tm {
               int tm_sec;    /* 秒数 */
               int tm_min;    /* 分钟 (0-59) */
               int tm_hour;   /* 小时 (0-23) */
               int tm_mday;   /* 月中天数 (1-31) */
               int tm_mon;    /* 月份+1 (0-11) */
               int tm_year;   /* 年 + 1900 */
               int tm_wday;   /* 周中天数 (0-6, Sunday = 0) */
               int tm_yday;   /* 年中天数 (0-365, 1 Jan = 0) */
               int tm_isdst;  /* Daylight saving time */
           };
 

sprintf/snprintf  将格式串转换为字符串

       int sprintf(char *str, const char *format, ...);
       功能:将格式串转换为字符串放入字符数组中
       参数1:存放格式串的字符数组
       参数2:格式串,可以包含格式控制符
       参数3:可变参数,根据参数2中的格式控制符个数确定
       返回值:成功返回转换的字符个数,失败返回-1
       int snprintf(char *str, size_t size, const char *format, ...);
        该函数比sprintf更加安全,因为多了一个size的限制

#include<myhead.h>
#include<time.h>
int main(int argc, const char *argv[])
{
    //定义变量存储秒数
    time_t sys_time = time(NULL);

    //将秒数转换为结构体
    struct tm *time_ptr = localtime(&sys_time);

    char buf[128] = "";      //存放转变后的字符串
    sprintf( buf,"%4d-%2d-%2d %2d:%2d:%2d\n",\
            time_ptr->tm_year+1900,\
            time_ptr->tm_mon+1,\
            time_ptr->tm_mday,\
            time_ptr->tm_hour,\
            time_ptr->tm_min,\
            time_ptr->tm_sec);

    printf("buf = %s\n", buf);

    return 0;
}

fprintf/fscanf  格式化读写函数

       int fprintf(FILE *stream, const char *format, ...);
       功能:向指定文件中写入一个格式串
       参数1:文件指针
       参数2:格式串,可以包含格式控制符
       参数3:可变参数,根据参数2而定
       返回值:成功返回写入文件的字符实际个数,失败返回-1
       
      int fscanf(FILE *stream, const char *format, ...);
        功能:将从文件中读取一些数据,放入到程序中来
        参数1:文件指针
        参数2:格式控制串
        参数3:根据参数2而定
        返回值:成功返回读取数据的个数,失败返回EOF并置位错误码

#include<myhead.h>

int main(int argc, const char *argv[])
{
    //定义文件指针
    FILE *fp = NULL;
    if((fp = fopen("./file.txt", "w")) == NULL)
    {
        perror("fopen error");
        return -1;
    }


    //定义要存储的数据
    int num = 18;          //整形数据

    printf("num = %d\n", num);       //向终端输出
    fprintf(fp ,"%d\n", num);       //向fp指向的文件中输出
    //关闭文件
    fclose(fp);

    //以只读的形式打开文件
    if((fp = fopen("./file.txt", "r")) == NULL)
    {
        perror("fopen error");
        return -1;
    }

    int key = 0;

    fscanf(fp, "%d", &key);      //从文件中读取一个数据


    printf("key = %d\n", key);

    //关闭文件
    fclose(fp);

    return 0;
}

fprintf/fscanf  登录注册

#include<myhead.h>
//定义登录函数
int do_login()
{
    //定义变量接受登录账号和密码
    char login_name[20] = "";
    char login_pwd[20] = "";

    printf("请输入登录账号:");
    fgets(login_name, sizeof(login_name), stdin);
    login_name[strlen(login_name)-1] = '\0';    //将换行换成'\0'
    printf("请输入登录密码:");
    fgets(login_pwd, sizeof(login_pwd), stdin);
    login_pwd[strlen(login_pwd)-1] = 0;

    //打开文件读取数据
    FILE *fp = NULL;
    if((fp = fopen("./usr.txt", "r")) == NULL)
    {
        perror("fopen error");
        return -1;
    }

    //定义接收文件中的变量
    char name[20] = "";
    char pwd[20] = "";
    while(1)
    {
        //读取数据
        int res = fscanf(fp, "%s %s", name, pwd);
        if(res != 2)
        {
            break;
        }
        //判断是否登录成功
        if(strcmp(login_name,name)==0 && strcmp(login_pwd,pwd)==0)
        {
            printf("登录成功\n");
            fclose(fp);
            return 0;
        }
    }

    //关闭文件
    fclose(fp);
    return -1;

}





//定义注册函数
void do_regist()
{
    //定义变量接受注册账号和密码
    char regist_name[20] = "";
    char regist_pwd[20] = "";

    printf("请输入注册账号:");
    fgets(regist_name, sizeof(regist_name), stdin);
    regist_name[strlen(regist_name)-1] = '\0';    //将换行换成'\0'
    printf("请输入注册密码:");
    fgets(regist_pwd, sizeof(regist_pwd), stdin);
    regist_pwd[strlen(regist_pwd)-1] = 0;

    //将上述内容写入文件
    FILE *fp = NULL;
    if((fp = fopen("./usr.txt", "a")) == NULL)
    {
        perror("fopen error");
        return;
    }

    //将数据写入文件
    fprintf(fp, "%s %s\n", regist_name, regist_pwd);

    //关闭文件
    fclose(fp);
    printf("注册成功\n");
}




/************************主程序************************/
int main(int argc, const char *argv[])
{
    //制作菜单
    int menu = 0;        //选项
    while(1)
    {
        //调用函数执行shell指令
        system("clear");
        printf("\t\t======XXX 登录系统======\n");
        printf("\t\t======1、 登录======\n");
        printf("\t\t======2、 注册======\n");
        printf("\t\t======0、 退出======\n");
        printf("请输入功能:");
        fscanf(stdin, "%d", &menu);
        while(getchar() !='\n');       //吸收垃圾字符
        
        //对菜单多分支选择
        switch(menu)
        {
        case 1:
            {
                //do_login();
                int res = do_login();
                if(res == 0)
                {
                    //执行相关功能
                }else
                {
                    printf("登录失败\n");
                }
                
            }
            break;

        case 2:
            {
                do_regist();
            }
            break;

        case 0:goto END;
        default:fprintf(stdout, "您输入的功能有误,请重新输入!!\n");
        }

        printf("请输入任意键,按回车结束\n");
        while(getchar() != '\n');
    }

END:

    return 0;
}

fread/fwrite 模块化读写

       #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);
       功能:对文件进行模块化读写操作
       参数1:要写入(存放数据)数据的起始地址
       参数2:每一项的大小
       参数3:总的项数
       参数4:文件指针
       返回值:成返回读取的项数值,失败返回小于项数的值
       注意:fread并不能区分是文件结束了,还是因为出现错误了,需要使用feof或ferror来区分

使用fread、fwrite读写字符串

#include <myhead.h>
int main(int argc, char const *argv[])
{
    FILE *fp = NULL;

    fp = fopen("./usr.txt","w");

    char buf[] = "hello a\n";

    fwrite(buf,1,strlen(buf),fp);  //单字符写入
    fwrite(buf,strlen(buf),1,fp);  //单字串写入

    fclose(fp);

    fp = fopen("./usr.txt","r");
   
    char rbuf[128] = "";
    fread(rbuf,1,strlen(buf),fp);  //strlen(buf)-1  手动预留一个位置放‘\0’
    // printf("rbuf = %s\n",rbuf);   //fread 读取字符串不会预留一个位置放‘\0’,如果字符数组大小 小于等于 读取的大小,用%s输出会出现乱码 
    fwrite(buf,1,strlen(buf),stdout);  //向标准输出写入内容 则不受影响


    fclose(fp);
    return 0;
}

使用fread、fwrite读写字符串

#include <myhead.h>
int main(int argc, char const *argv[])
{
    FILE *fp = NULL;

    fp = fopen("./usr.txt","w");

    int num = 18;

    fwrite(&num,sizeof(num),1,fp);  //整型写入  存储的是十六进制数  
    fclose(fp);                    

    fp = fopen("./usr.txt","r");
    int key = 0;
    fread(&key,sizeof(key),1,fp);

    printf("key = %d\n",key);  //  key = 18

    fclose(fp);
    return 0;
}

 直接打开存储文件

使用fread、fwrite读写结构体

#include <myhead.h>

typedef struct 
{
    int numb;
    char name[20];
    int age;
    double score;
}Stu;


int main(int argc, char const *argv[])
{
    FILE *fp = NULL;

    fp = fopen("./usr.txt","w");

    Stu s[3] = {{1001,"lisi",30,98},{1002,"zs",25,100},{1003,"ww",23,80}};

    fwrite(s,sizeof(Stu),3,fp);
    
    fclose(fp);

    fp = fopen("./usr.txt","r");
    Stu temp;
    fread(&temp,sizeof(temp),1,fp);
    printf("学号%d 姓名%s 年龄%d 成绩%.2lf\n",temp.numb,temp.name,temp.age,temp.score);
    fread(&temp,sizeof(temp),1,fp);
    printf("学号%d 姓名%s 年龄%d 成绩%.2lf\n",temp.numb,temp.name,temp.age,temp.score);

    fclose(fp);
    return 0;
}

光标移动函数  fseek

       #include <stdio.h>

       int fseek(FILE *stream, long offset, int whence);
       功能:对文件光标进行偏移
       参数1:文件指针
       参数2:偏移量
               >0:表示向后偏移
               =0:表示不偏移
               <0:表示向前偏移
        参数3:偏移位置
                SEEK_SET:文件开头
                SEEK_END:文件结束
                SEEK_CUR:当前位置
        返回值:成功返回0,失败返回-1并置位错误码
                                

       long ftell(FILE *stream);
       功能:返回文件当前位置(就是当前位置相对于文件起始位置的偏移字节数)
       参数:文件指针
       返回值:偏移字节数
       常用:fseek(fp, 0, SEEK_END);
             ftell(fp);              //文件大小                           

       void rewind(FILE *stream);
       功能:将光标定位到开头   类似于 fseek(fp, 0, SEEK_SET)
       参数:文件指针
       返回值:无
#include<myhead.h>
//定义结构体类型
typedef struct
{
    int numb;         //学号
    char name[20];       //姓名
    int age;             //年龄
    double score;        //成绩
}Stu;



/**********************主程序*********************/
int main(int argc, const char *argv[])
{
    //定义文件指针
    FILE *fp = NULL;
    if((fp = fopen("./usr.txt", "w")) == NULL)
    {
        perror("fopen error");
        return -1;
    }

    //定义三个学生
    Stu s[3] = {{1001, "大狗", 30, 98}, \
                {1002, "二狗", 25, 100}, \
                {1003, "天明", 23, 80}};

    //将这三名学生信息写入文件中
    fwrite(s, sizeof(Stu), 3, fp);

    //关闭文件
    fclose(fp);


    //以只读的形式打开文件
    if((fp = fopen("./usr.txt", "r")) == NULL)
    {
        perror("fopen error");
        return -1;
    }

    //定义接收取出的学生
    Stu temp;

    fread(&temp, sizeof(temp), 1, fp);
    fread(&temp, sizeof(temp), 1, fp);
    //此时,光标已经定位在第三个学生的开头
    //目的:将光标定位到“大狗”前面
    //fseek(fp, 0, SEEK_SET);
    fseek(fp, -(sizeof(Stu)*2), SEEK_CUR);
    fread(&temp, sizeof(temp), 1, fp);

    printf("学号:%d, 姓名:%s,年龄:%d,成绩%.2lf\n",\
            temp.numb, temp.name, temp.age, temp.score);


    //关闭文件
    fclose(fp);

    return 0;
}

使用标准IO完成对图像的操作

bmp图的资料链接:https://blog.csdn.netXYK0318/article/details/105123197/

./gg.bmp 为对象图片

#include<myhead.h>

int main(int argc, const char *argv[])
{
    //定义文件指针
    FILE *fp = NULL;
    if((fp = fopen("./gg.bmp", "r+")) == NULL)
    {
        perror("fopen error");
        return -1;
    }

    //获取文件大小
    int img_size = 0;

    //将文件光标偏移2个字节
    fseek(fp, 2, SEEK_SET);

    //读取4字节的内容
    fread(&img_size, sizeof(img_size), 1, fp);

    printf("size = %d\n", img_size);        //图像大小

    //从头向后偏移54字节后,就是图像数据
    fseek(fp, 54, SEEK_SET);

    //定义一个像素
    unsigned char color[3] = {0, 0, 255};     //正红色
    for(int i=0; i<960/2; i++)          //外行
    {
        for(int j=0;j<1280; j++)       //内列
        {
            fwrite(color, sizeof(color), 1, fp);
        }
    }
    



    //关闭文件
    fclose(fp);

    return 0;
}

 作业

1、写一个日志文件,将出现启动后,每一秒的时间写入文件中

1、2024- 7-29 10:31:19
2、2024- 7-29 10:31:20
3、2024- 7-29 10:31:21
ctrl+c:停止程序
./a.out
4、2024- 7-29 10:35:06
5、2024- 7-29 10:35:07
6、2024- 7-29 10:35:08

代码

#include <myhead.h>

int main(int argc, char const *argv[])
{
    FILE *fp = fopen("./00.log", "a+");

    fseek(fp,0,SEEK_SET);

    char buf[128] = "";
    char buf1[128] = {"1"};
    char buf2[128] = "";
    int n = 1;
    while (1)
    {
        // printf("n1 = %d\n",n);
        if ((fgets(buf2, sizeof(buf2), fp)) != NULL)
        {
            n++;
            // printf("n2 = %d\n",n);
        }
        else
        {
            break;
        }
    }

    fseek(fp,0,SEEK_END);

    time_t sys_time = time(NULL); // 定义及重置
    struct tm *time_ptr = localtime(&sys_time);

    while (1)
    {
        sys_time = time(NULL); // 定义及重置
        time_ptr = localtime(&sys_time);
        sprintf(buf, "%4d-%2d-%2d %2d:%2d:%2d\n", time_ptr->tm_year + 1900, time_ptr->tm_mon + 1, time_ptr->tm_mday, time_ptr->tm_hour, time_ptr->tm_min, time_ptr->tm_sec);
        if (strcmp(buf, buf1) != 0)
        {
            printf("n = %d\n", n);
            fprintf(fp, "%d %s", n, buf);
            strcpy(buf1, buf);
            fflush(stdin);
            fflush(fp);
            n++;
        }
    }

    return 0;
}

终端执行命令

效果图

2、使用fread、fwrite完成两个文件的拷贝

        不允许只读写一次

代码

#include <myhead.h>

int main(int argc, char const *argv[])
{
    FILE *fp = NULL;
    FILE *fq = NULL;

    fp = fopen("./06.c", "r");
    fq = fopen("./06.txt", "w");

    char temp[10] = "";

    while (fread(temp, sizeof(temp), 1, fp))
    {
        fwrite(temp, sizeof(temp), 1, fq);
        bzero(temp,sizeof(temp));
    }
    fwrite(temp, strlen(temp), 1, fq);
    fclose(fp);
    fclose(fq);
    return 0;
}

 效果图

3、实现对bmp图像的读写操作

原图:

#include <myhead.h>

int main(int argc, const char *argv[])
{
    // 定义文件指针
    FILE *fp = NULL;
    if ((fp = fopen("./gg.bmp", "r+")) == NULL)
    {
        perror("fopen error");
        return -1;
    }

    // 获取文件大小
    int img_size = 0;

    // 将文件光标偏移2个字节
    fseek(fp, 2, SEEK_SET);

    // 读取4字节的内容
    fread(&img_size, sizeof(img_size), 1, fp);

    printf("size = %d\n", img_size); // 图像大小

    // 从头向后偏移54字节后,就是图像数据
    fseek(fp, 54, SEEK_SET);

    //定义一个像素
    unsigned char color[3] = {0, 0, 0}; // bgr
    // unsigned char color[3] = {255, 255, 255}; // bgr
    for (int i = 0; i < 960; i++)       // 外行
    {
        for (int j = 0; j < 1280; j++) // 内列
        {
            if (i > 570 && i < 630 && j>350 && j<620||i > 590 && i < 650 && j>720 && j<1000)
            {
                fwrite(color, sizeof(color), 1, fp);
            }
            else
            {
                fseek(fp, sizeof(color), SEEK_CUR);
            }
        }
    }

    // 关闭文件
    fclose(fp);

    return 0;
}

效果图:

  • 17
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值