I/O day2 作业(接第一天)

六、关于缓冲区问题

6.1 缓冲区的大小

1> 全缓存:跟自定义文件指针有关的缓冲区,其大小为4096字节

2> 行缓存:跟终端相关的操作使用的是行缓存(stdin、stdout),其大小为1024字节

3> 不缓存:跟标准出错有关的操作是不缓存(stderr),其大小为0

#include
#include
#include

int main(int argc, const char *argv[])
{
    //航缓存的大小为1024字节
    //如果没有使用行缓存,则默认大小为0
    printf("行缓存:%ld\n", stdin->_IO_buf_end - stdin->_IO_buf_base);

    //只有完成一次输入时,才能求出行缓存区的大小
    int num;
    scanf("%d", &num);
    printf("stdin行缓存:%ld\n", stdin->_IO_buf_end - stdin->_IO_buf_base);

    printf("stdout行缓存:%ld\n", stdout->_IO_buf_end - stdout->_IO_buf_base);



    fputs("hello world\n", stderr);
    fputs("hello world\n", stderr);
    //不缓存的大小为0
    printf("不缓存:%ld\n", stderr->_IO_buf_end - stderr->_IO_buf_base);


    //全缓存,大小为4096
    FILE *fp;
    if((fp = fopen("./08file.txt", "w")) == NULL)
    {
        perror("open file");
        return -1;
    }

    fputc('H', fp);


    printf("全缓存:%ld\n", fp->_IO_buf_end - fp->_IO_buf_base);
    fclose(fp);


    return 0;
}

6.2 缓冲区的刷新时间

1> 行缓存的刷新时机

1、遇到‘\n’会刷新行行缓存

2、程序结束后,自动刷新行缓存

3、当输入输出发生切换时,会刷新行缓存

4、当关闭文件指针时,也会刷新行缓存

5、手动刷新缓存区时,行缓存会进行刷新

6、当缓存区满了后,会自动刷新缓存区

#include
#include
#include

int main(int argc, const char *argv[])
{
    /*
    printf("hello world");          //没有'\n'不会刷新缓存区
    //1、当遇到'\n'时会刷新缓冲器
    printf("hello world\n");
    while(1);
    */

    //2、当程序结束后,会自动刷新行缓存
    //printf("hello world");
    

    /*
    //3、当输入输出发生切换时,会刷新行缓存
    printf("hello world");
    int num;
    scanf("%d", &num);
    while(1);
    */

    /*
    //4、当关闭文件指针时,也会刷新行缓存
    printf("hello world");
    fclose(stdout);           //关闭文件指针
    while(1);
    */

    /*
    //5、手动刷新缓存区时,行缓存会进行刷新
    printf("hello world");
    fflush(stdout);            //手动刷新缓存区
    while(1);
    */

    //6、当缓存区满了后,会自动刷新缓存区
    for(int i=0; i<1025; i++)
    {
        printf("%c", 'a');
    }
    while(1);


    return 0;
}

2> 全缓存的刷新时机

1、遇到‘\n’不会刷新全缓存

2、程序结束后,自动刷新全缓存

3、当输入输出发生切换时,会刷新全缓存

4、当关闭文件指针时,也会刷新全缓存

5、手动刷新缓存区时,会刷新全缓存

6、当缓存区满了后,会自动刷新缓存区

#include
#include
#include

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

    if((fp = fopen("./10file.txt", "w")) == NULL)
    {
        perror("open file");
        return -1;
    }

    /*
    //1、全缓存遇到'\n'不会刷新缓冲区
    fputc('A', fp);
    fputc('\n', fp);
    while(1);
    */

    //2、程序运行结束后,会刷新全缓存
    //fputc('A', fp);
    
    /*
    //3、当你输入输出发生切换时, 会刷新全缓存
    fputc('A', fp);
    fgetc(fp);
    while(1);
    */

    /*
    //4、当关闭文件时,会刷新全缓存
    fputc('A', fp);
    fclose(fp);
    while(1);
    */

    /*
    //5、手动刷新缓存区时,也会刷新缓存区
    fputc('A', fp);
    fflush(fp);
    while(1);
    */

    //6、缓存区满了,会刷新全缓存
    for(int i=0; i<4097; i++)
    {
        fputc('a', fp);
    }

    while(1);
    
    
    

    return 0;
}

6.3 关于时间的操作

1> 函数原型

       #include 

       time_t time(time_t *tloc);
功能:获取系统当前时间的毫秒数
参数:如果是NULL,则通过返回值返回毫秒数
      如果参数不是NULL,则可以通过参数得到毫秒数
返回值:成功返回毫秒数,失败返回time_t类型的-1,并置位错误码

    struct tm *localtime(const time_t *timep);
功能:通过给定的毫秒数,转变成时间
参数:毫秒数
返回值: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) */
               int tm_year;   /* Year - 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 */
           };
#include
#include
#include
#include

int main(int argc, const char *argv[])
{
    time_t sys_time  = time(NULL);       //获取系统时间的毫秒数

    //将毫秒数转变成时间结构体
    struct tm *fomattime = localtime(&sys_time);   

    printf("%4d-%2d-%2d %2d:%2d:%2d\n", fomattime->tm_year+1900\
            ,fomattime->tm_mon+1,\
            fomattime->tm_mday,\
            fomattime->tm_hour,\
            fomattime->tm_min,\
            fomattime->tm_sec);

    
    
    return 0;
}

七、格式化控制相关的函数

7.1 sprintf函数

       #include 
 int sprintf(char *str, const char *format, ...);
功能:向给定的字符数组中,存放进行了格式化后的字符串
参数1:字符数组首地址
参数2:格式串
参数3:格式串对应的可变参数
返回值:成功返回格式串的长度,失败返回负数

注意:当进行格式串时,格式串的长度比字符数组的长度大时,编译时会给出voerflow的警告,运行时会报段错误,保险起见,我们可以使用snprintf
#include
#include
#include
#include

int main(int argc, const char *argv[])
{
    char str[50];
    time_t sys_time  = time(NULL);       //获取系统时间的毫秒数

    //将毫秒数转变成时间结构体
    struct tm *fomattime = localtime(&sys_time);   

    //使用sprintf将格式串转换为字符串
    sprintf(str,"%4d-%2d-%2d %2d:%2d:%2d", fomattime->tm_year+1900\
            ,fomattime->tm_mon+1,\
            fomattime->tm_mday,\
            fomattime->tm_hour,\
            fomattime->tm_min,\
            fomattime->tm_sec);

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

    
    
    return 0;
}

7.2 snprintf函数

 int snprintf(char *str, size_t size, const char *format, ...);
功能:将格式串转成字符串,但是有长度size控制,并在后面自动不上'\0'
参数1:存放格式化串的数组
参数2:格式化的长度
参数3:格式控制串
参数4:可变参数
返回值:成功返回格式化的字符格式, 失败返回负数
#include
#include
#include

int main(int argc, const char *argv[])
{
    char s[10];

    //使用snprintf将格式串转换为字符串
    snprintf(s, sizeof(s), "hello world ni hao");

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



    return 0;
}

7.3 fprintf函数

       #include 

       int printf(const char *format, ...);
       int fprintf(FILE *stream, const char *format, ...);
功能:向给定文件中写入一个格式串
参数1:文件指针
参数2:格式化串
参数3:不定参数,根据格式化串中的格式控制符来确定个数
返回:成功返回输出的个数, 失败返回负数
#include
#include
#include

int main(int argc, const char *argv[])
{
    
    int m = 23041;
    char name[20] = "班:张鹏鹏";

    fprintf(stdout, "%d%s\n", m, name);      //向标准输出文件中输出数据

    //向文件中输出数据
    FILE *fp;

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

    //将格式化串写入文件
    fprintf(fp, "%s %s\n", "zhangsan", "123456");
    fprintf(fp, "%s %s\n", "lisi", "111111");

    //关闭文件
    fclose(fp);

    return 0;
}

在上述已经写入文件中,进行读取数据I/O day2 作业(接第一天)_第1张图片

 7.3 fscanf函数

       #include 

       int scanf(const char *format, ...);
       int fscanf(FILE *stream, const char *format, ...);
功能:从给定文件中,以格式化控制符从文件中摘取数据放入到程序中
参数1:文件指针
参数2:格式控制串
参数3:地址列表
返回值:成功返回读取字符个数,失败返回EOF并置位错误码
#include
#include
#include

int main(int argc, const char *argv[])
{
    char userName[20];         //存储账号
    char pwd[20];              //存储密码
    char loginName[20] = "lisi";
    char loginPwd[20] = "111111";

    //打开文件读取数据
    FILE *fp;

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

    while(1)
    {
        //从文件中读取数据放入到程序中
        int ret = fscanf(fp, "%s%s", userName, pwd);
        if(ret == EOF)
        {
            printf("登录失败\n");
            break;
        }

        //账号和密码匹配
        if(strcmp(userName,loginName)==0 && strcmp(pwd, loginPwd)==0)
        {
            printf("登录成功\n");
            break;
        }

    }

    //关闭文件
    fclose(fp);


    

    return 0;
}

八、fread、fwrite函数的使用

       #include 

       size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
 功能: 从给定文件中,读取nmemb项数据,每项数据大小为size,将数据放入ptr中
 参数1:存放数据的指针,是一个万能指针,可以接收任意类型数据
 参数2:读取数据每一项的大小
 参数3:读取的项数
 参数4:文件指针
 返回值:成功返回读取的项数,当size为1时,就是成功读取的字节数,失败返回小于项数的值或者0
         注意:该函数不能区分是读取失败还是读取到文件结尾,需要使用ferror和feof来区分         

       size_t fwrite(const void *ptr, size_t size, size_t nmemb,
FILE *stream);       
功能:将ptr指向的数据,每项数据的大小为size,一共有nmemb项,写入到stream文件中
参数1:存放数据的指针,是一个万能指针,可以接收任意类型数据
 参数2:读取数据每一项的大小
 参数3:读取的项数
 参数4:文件指针
 返回值:成功返回读取的项数,当size为1时,就是成功读取的字节数,失败返回小于项数的值或者0

1> 整形数据的读写

/*******************************写入文件数据****************************/
#include
#include
#include

int main(int argc, const char *argv[])
{
    //定义文件指针
    FILE *fp;
    //以只写的形式打开文件
    if((fp = fopen("./Test.txt", "w")) == NULL)
    {
        perror("open file");
        return -1;
    }


    //使用fwrite将数据写入到文件中

    int num = 520;
    fwrite(&num, 4, 1, fp);

    //关闭文件
    fclose(fp);

    return 0;
}

/*******************************从文件中读取数据****************************/
#include
#include
#include

int main(int argc, const char *argv[])
{
    //定义文件指针
    FILE *fp;
    //以只写的形式打开文件
    if((fp = fopen("./Test.txt", "r")) == NULL)
    {
        perror("open file");
        return -1;
    }


    //使用fwrite将数据写入到文件中

    int num;
    fread(&num, 4, 1, fp);

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

    //关闭文件
    fclose(fp);

    return 0;
}

I/O day2 作业(接第一天)_第2张图片

 I/O day2 作业(接第一天)_第3张图片

 2> 字符串的读写

#include
#include
#include

int main(int argc, const char *argv[])
{

    char buf[] = "this is a string";
    //定义文件指针
    FILE *fp;
    //以只写的形式打开文件
    if((fp = fopen("./Test.txt", "w")) == NULL)
    {
        perror("open file");
        return -1;
    }

    //将数据写入文件中
    fwrite(buf, 1, sizeof(buf), fp);

    //关闭文件
    fclose(fp);


    //读取数据
    char str[50];
    //以只读的模式打开文件
    if((fp = fopen("./Test.txt", "r")) == NULL)
    {
        perror("open file");
        return -1;
    }

    //从文件中读取数据到str中
    fread(str, sizeof(str), 1, fp);

    //关闭文件
    fclose(fp);

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

    return 0;
}

I/O day2 作业(接第一天)_第4张图片

 3> 结构体的读写

#include
#include
#include

//定义学生结构体类型
typedef struct
{
    char name[20];      //姓名
    int age;            //年龄
    double score;         //分数
}Stu;




int main(int argc, const char *argv[])
{
    Stu s[2] = {{"张三", 18, 99},{"lisi", 30, 100}};

    //定义文件指针
    FILE *fp;
    //以只写的形式打开文件
    if((fp = fopen("./Test.txt", "w")) == NULL)
    {
        perror("open file");
        return -1;
    }

    //将两个数据全部写入文件中去
    fwrite(s, sizeof(Stu), 2, fp);

    //关闭文件指针
    fclose(fp);

    //定义变量接收读取的数据
    Stu stu;
    //打开文件
    if((fp = fopen("./Test.txt", "r")) == NULL)
    {
        perror("open file");
        return -1;    
    }

    //从文件中读取一项数据到stu中
    fread(&stu, sizeof(Stu), 1, fp);

    //关闭文件指针
    fclose(fp);

    //输出获取的信息
    printf("stu.name = %s, age = %d, score = %.2lf\n", stu.name, stu.age, stu.score);
    
    return 0;
}

 

 九、feof、ferror的使用

       #include 



       int feof(FILE *stream);
       功能:判断文件是否已经读取到结尾
       参数:文件指针
       返回值:成功返回非0数字,失败返回0

       int ferror(FILE *stream);
       功能:判断文件是否读取错误
       参数:文件指针
       返回值:成功返回非负整数,失败返回0       
#include
#include
#include

int main(int argc, const char *argv[])
{
    char buf[10] = "";

    FILE *fp;             //定义文件指针
    //以只读的形式打开文件
    if((fp= fopen("./Test.txt", "r")) == NULL)
    {
        perror("open file");
        return -1;
    }

    //循环读取数据
    while(1)
    {
        fread(buf, 1, sizeof(buf), fp);

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

        //判断当前文件是否结束
        if(feof(fp))
        {
            printf("已经读到文件结尾了\n");
            break;
        }else if(ferror(fp))
        {
            printf("文件读取失败\n");
            break;
        }

    }

    //关闭文件
    fclose(fp);

    return 0;
}

作业

作业1、获取系统时间,并将系统时间写入文件中,实现现象

1、2023-5-25 14:32:50

2、2023-5-25 14:32:51

3、2023-5-25 14:32:52

//按下ctrl+c,再重新运行程序后

4、2023-5-25 14:33:20

5、2023-5-25 14:33:21

。。。

作业2:使用fread和fwrite完成两个文件的拷贝

1.

#include 
#include 

int main()
{
    // 打开文件
    FILE* file = fopen("time.txt", "w+");
    if (file == NULL)
    {
        printf("Failed to open file.\n");
        return 1;
    }

    // 获取系统时间
    time_t current_time = time(NULL);
    struct tm* local_time = localtime(¤t_time);

    // 写入文件
    fprintf(file, "%04d-%02d-%02d %02d:%02d:%02d\n",
        local_time->tm_year + 1900, local_time->tm_mon + 1, local_time->tm_mday,
        local_time->tm_hour, local_time->tm_min, local_time->tm_sec);
    fflush(file);

    // 关闭文件
    fclose(file);

    // 延续上次运行的代码
    file = fopen("time.txt", "r");
    if (file == NULL)
    {
        printf("Failed to open file.\n");
        return 1;
    }

    time_t last_time;
    int year, month, day, hour, minute, second;
    if (fscanf(file, "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &minute, &second) == 6)
    {
        struct tm last_local_time = {0};
        last_local_time.tm_year = year - 1900;
        last_local_time.tm_mon = month - 1;
        last_local_time.tm_mday = day;
        last_local_time.tm_hour = hour;
        last_local_time.tm_min = minute;
        last_local_time.tm_sec = second;
        last_time = mktime(&last_local_time);

        // 计算时间间隔
        time_t elapsed_time = difftime(current_time, last_time);
        printf("Elapsed time: %ld seconds.\n", elapsed_time);
    }

    fclose(file);

    return 0;
}

2.

#include 
#define BUFFER_SIZE 1024
int main() 
{    
 FILE *src_file = fopen("src_file.txt", "rb");   
 FILE *dst_file = fopen("dst_file.txt", "wb");   
 if (src_file == NULL || dst_file == NULL) 
{       
     perror("open file");      
     
     return 1;    
}   
 char buffer[BUFFER_SIZE];   
 size_t bytes_read;   
 while ((bytes_read = fread(buffer, 1, BUFFER_SIZE, src_file)) > 0)
 {       
     fwrite(buffer, 1, bytes_read, dst_file);   
 }    
fclose(src_file);   
 fclose(dst_file);   
 return 0;
}

你可能感兴趣的:(缓存)