• c语言基础学习10_文件操作02


    =============================================================================
    =============================================================================
    涉及到的知识点有:
    六、stat函数
    七、fread 和 fwrite函数
    八、fopen的a模式说明
    九、fopen的b模式说明
    十、sftp传输文件时的说明
    十一、fopen的其他模式简要说明
    十二、实现二进制文件的拷贝
    十三、fseek函数
    十四、ftell函数
    十五、fflush函数
    十六、remove函数 和 rename函数 (文件删除函数和文件改名函数)
    十七、通过fwrite将结构体保存到二进制文件中
    课堂练习
    =============================================================================
    =============================================================================
    六、stat函数

    需要包含头文件有:
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>

    功能:得到文件的各种属性(包括文件的属性、文件的建立时间、文件的大小等信息)。和文件的内容并没有关系。

    int stat(const char *pathname, struct stat *buf);
    函数的第一个参数:代表文件名。
    函数的第二个参数:是struct stat结构。

    一般头文件在"cd /usr/include"下面,这里是标准C程序头文件,如果你的头文件前加了 <sys/*>,那说明这是系统调用函数头文件,其在"cd /usr/include/sys"下面。
    函数都是获取文件(普通文件、目录、管道、socket、字符、块)的属性。函数原型#include <sys/stat.h>。
    --------------------------------------
    linux下示例代码如下:

     1 #include <stdio.h>
     2 #include <sys/types.h>
     3 #include <sys/stat.h>
     4 #include <unistd.h>
     5 
     6 int main()
     7 {
     8     struct stat st = { 0 }; //该结构在头文件#include <sys/stat.h>里面已经定义过了,只需要去使用它就行了。
     9     stat("a.txt", &st);     //调用完stat函数后,st里面就得到了该文件的属性。
    10 
    11     int size = st.st_size;  //得到文件的大小。单位是:字节。
    12     printf("%d
    ", size);    //78
    13 
    14     return 0;
    15 }
    文件对应的属性:
    struct stat 
    {
        mode_t     st_mode;      //文件对应的模式,文件,目录等。
        ino_t      st_ino;      //inode节点号。
        dev_t      st_dev;      //设备号码。
        dev_t      st_rdev;     //特殊设备号码。
        nlink_t    st_nlink;    //文件的连接数。
        uid_t      st_uid;      //文件所有者。
        gid_t      st_gid;      //文件所有者对应的组。
        off_t      st_size;     //普通文件,对应的文件字节数。
        time_t     st_atime;    //文件最后被访问的时间。
        time_t     st_mtime;    //文件内容最后被修改的时间。
        time_t     st_ctime;    //文件状态改变时间。
        blksize_t  st_blksize;  //文件内容对应的块大小。
        blkcnt_t   st_blocks;   //伟建内容对应的块数量。
    };

    =============================================================================
    七、fread 和 fwrite函数

    文本文件:就是我们能看的懂的文件。
    二进制文件:就是我们看不懂的文件。

    之前学的:fgets、fputs、fprintf、fscanf这些函数都是针对文本文件读写的,不能对一个二进制文件进行读写。
    除了文本文件之外的文件都是二进制文件,比如图像、视频、音乐、可执行程序这些都是二进制的。
    (其实文本文件也是二进制文件,文本文件是一种特殊的二进制文件,文本文件里面都是ASCII码。)

    之前学习的内容都是往文件里面写一个字符串。
    如果要把一个int整数直接写入文件,这个文件就不是文本文件了。
    --------------------------------------
    #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);

    第一个参数是buf的内存地址;
    第二个参数是每个单位的大小;
    第三个参数是写多少个单位;
    第四个参数是fopen返回的文件指针。
    返回值:返回的是实际写入的数据块数目。

    fread的返回值是成功读取到的单位个数。
    fread第二个参数代表了一个单位多大,第三个参数代表一次要读多少个单位。

    功能:这两个函数以二进制形式对文件进行操作,不局限于文本文件。
    --------------------------------------
    linux下示例代码如下:

     1 #include <stdio.h>
     2 
     3 int main01()
     4 {
     5     FILE *p = fopen("a.dat", "w");
     6 
     7     int a = 100;
     8     fwrite(&a, 1, sizeof(int), p);  //要往文件里面写4个字节的内容。
     9     //fwrite(&a, sizeof(int), 1, p);  //二者等价。
    10     a = 123456789;                  //再往文件里面写4个字节的内容。
    11     fwrite(&a, 1, sizeof(int), p); 
    12 
    13     fclose(p);
    14 
    15     return 0;
    16 }
    17 
    18 int main()
    19 {
    20     FILE *p = fopen("a.dat", "r");
    21     
    22     while (1) 
    23     {   
    24         //int a = 0;    //以int的方式打开。
    25         //fread(&a, 1, sizeof(int), p);
    26         unsigned char a = 0;    //以每个字节的方式打开。
    27         fread(&a, 1, sizeof(char), p); 
    28         if (feof(p))
    29             break;
    30         //printf("%d
    ", a);
    31         printf("%x
    ", a);  //以16进制的方式显示,小端对齐。
    32     }   
    33     fclose(p);
    34 
    35     return 0;
    36 }
    37 输出结果为:
    38 64
    39 0
    40 0
    41 0
    42 15
    43 cd
    44 5b
    45 7

    -----------------------------------------------------------------------------
    通过fread读取文件的每个字节。

    linux下示例代码如下:

    int main(int argc, char **args)
    {
        if (argc < 2)
            return 0;
    
        FILE *p = fopen(args[1], "r");
        
        while (1) 
        {   
            //int a = 0;    //以int的方式打开。
            //fread(&a, 1, sizeof(int), p);
            unsigned char a = 0;    //以每个字节的方式打开。
            fread(&a, 1, sizeof(char), p); 
            if (feof(p))
                break;
            //printf("%d
    ", a);
            printf("%x
    ", a);  //小端对齐。
        }   
        fclose(p);
    
        return 0;
    }

    =============================================================================
    八、fopen的a模式说明

    FILE *fopen(const char *path, const char *mode);

      a       以附加的方式打开只写文件。若文件不存在,则会建立该文件。
            如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。(EOF符保留)
      a+    以附加的方式打开可读写文件。若文件不存在,则会建立该文件。
           如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。(原来的EOF符不保留)

      即:a的作用是:如果文件不存在,那么a和w是一样的;如果文件存在,那么不覆盖这个文件,而是往文件后面追加内容。
    =============================================================================
    九、fopen的b模式说明

      r     以只读方式打开文件,该文件必须存在,且文件必须是可读的。
      r+     以可读写方式打开文件,该文件必须存在。
      rb+   读写打开一个二进制文件,允许读写数据,文件必须存在。

      注意:b模式也只能在windows下去演示,在linux、unix和Android下无效。

    windows所有的文本文件的每一行都是以 结尾的,而不是以 结尾的。
    (即windows系统下的文本文件以 来进行换行的。)
    在windows下,如果读文件的时候,只加"r"参数,那么系统会自动把 前面的 吃掉,而一旦添加了参数b,那么系统就不会自动吃掉 前面的 了。
    在windows下,如果写文件的时候,只加"w"参数,那么系统会自动在 前面添加一个 ,而一旦添加了b参数,那么系统就不会自动在 前面动添加 了。

    linux下所有的文本文件,每一行本来就是以 结尾的,前面没有 ,参数b在linux下是无效的。

    小规律:
    在windows读写是一个二进制文件的时候,一般要加b,防止系统添加无谓的 。
    但如果读写的是一个文本文件,那么不要加b,这样可以不用单独处理这个 了。

    小结:
    所以windows的文本文件要比linux的文本文件要大一些,因为windows的每一行会比linux的每一行多一个 (即多1个字节)。
    并没有为什么,这是当年微软在设计的时候,是从DOS过来的,那个时候DOS就是这样的。
    所以有时候,把linux的文本文件拿到windows下打开的情况下,会发现不换行了。

    即:windows和linux(unix)的文本文件是不一样的。
    =============================================================================
    十、sftp传输文件时的说明

    如果是要用sftp去下载一个文本文件的时候:操作如下:
    sftp> ascii
    Using ascii mode to transfer files.
    sftp> get file11.c
    Downloading file11.c from /home/chen/001/01/文件操作day01/file11.c
    100% 779 bytes 779 bytes/s 00:00:00
    /home/chen/001/01/文件操作day01/file11.c: 779 bytes transferred in 0 seconds (779 bytes/s)
    sftp>
    --------------------------------------
    如果是要用sftp去下载一个二进制文件的时候:操作如下:
    sftp> binary
    Using binary mode to transfer files.
    sftp> get file11.c
    Downloading file11.c from /home/chen/001/01/文件操作day01/file11.c
    100% 779 bytes 779 bytes/s 00:00:00
    /home/chen/001/01/文件操作day01/file11.c: 779 bytes transferred in 0 seconds (779 bytes/s)
    sftp>

    如下图所示:

    =============================================================================
    十一、fopen的其他模式简要说明
    =============================================================================
    十二、实现二进制文件的拷贝

    windows下示例代码:

     1 #include <stdio.h>
     2 #include <sys/stat.h>
     3 #include <stdlib.h>
     4 
     5 #define NUM 1024 * 64        //设置文件大小阈值为64K。
     6 
     7 int main(int argc, char **args)
     8 {
     9     if (argc < 3)
    10         return 0;
    11     
    12     FILE *p = fopen(args[1], "rb");
    13     if (p == NULL)
    14         return 0;
    15     
    16     FILE *p1 = fopen(args[2], "wb");
    17     if (p1 == NULL)
    18         return 0;
    19 
    20     //先得到文件的大小。
    21     struct stat st = { 0 };
    22     stat(args[1], &st);
    23     int size = st.st_size;
    24     
    25     //判断阈值。
    26     if (size >= NUM)
    27         size = NUM;
    28     
    29     //再根据文件的大小,动态分配一个堆内存出来。
    30     char *buf = malloc(size);
    31 
    32     while(!feof(p))
    33     {
    34         //char a = 0;                    
    35         //fread(&a, 1, 1, p);                //一次读一个char。
    36         //char a[1024] = { 0 };                //一次读一个1024个字节。
    37         //fread(a, 1, sizeof(a), p);
    38         //fwrite(a, 1, 1, p1);                //一次写一个char。
    39         //fwrite(a, 1, sizeof(a), p1);        //一次写一个1024个字节。
    40 
    41         int res = fread(buf, 1, size, p);    //把读的返回值传给要写的参数里面。
    42         fwrite(buf, 1, res, p1);
    43     }
    44     fclose(p);
    45     fclose(p1);
    46     free(buf);
    47 
    48     return 0;
    49 }

    =============================================================================
    十三、fseek函数

      int fseek(FILE *stream, long offset, int whence);
      函数功能:设置文件指针stream的位置。
      如果执行成功,stream将指向以whence为基准,偏移offset(指针偏移量)个字节的位置,函数返回0。
      如果执行失败,则不改变stream指向的位置,函数返回一个非0值。

      第一个参数:stream为文件指针。
      第二个参数:offset为偏移量,整数表示正向偏移,负数表示负向偏移。
      第三个参数:whence为设定文件从哪里开始偏移,可能取值为:SEEK_SET、SEEK_CUR或SEEK_END。
        SEEK_SET:文件开头。
        SEEK_CUR:当前位置。
        SEEK_END:文件结尾。
      例如:fseek(fp, 3, SEEK_SET);

      实验得出:
      往前偏移超出文件末尾位置,还是返回0;
      往回偏移超出文件首位置,还是返回0。
      所以需要小心使用。

      其实FILE结构内部是有一个指针的,每次调用文件读写函数时,这些函数就会自动移动这个指针。
      默认情况下该指针只能从前往后移动。

    windows下示例代码:

     1 #include <stdio.h>
     2 
     3 int main01()
     4 {
     5     FILE *p = fopen("a.dat", "w");
     6 
     7     char a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
     8     fwrite(a, 1, sizeof(a), p); 
     9     fclose(p);
    10 
    11     return 0;
    12 }
    13 
    14 int main()
    15 {
    16     FILE *p = fopen("a.dat", "r");
    17     
    18     fseek(p, 2, SEEK_SET);  //将文件指针从文件开始处位移2个字节。
    19 
    20     int i;
    21     for (i =0; i < 2; i++)
    22     {   
    23         //char a = 0;
    24         //fread(&a, 1, sizeof(a), p);
    25         
    26         char a[2] = { 0 };
    27         fread(a, 1, sizeof(a), p); 
    28         
    29         //fseek(p, -2, SEEK_CUR);      //将指针从当前位置回去2个字节。
    30         //fseek(p, 0, SEEK_SET);      //将指针指向文件开始。
    31         fseek(p, 0, SEEK_END);      //将指针指向文件结尾。
    32         printf("%d, %d
    ", a[0], a[1]);
    33     }   
    34     fclose(p);
    35 
    36     return 0;
    37 }
    38 输出结果为:
    39 2, 3
    40 0, 0

    windows下示例代码:

     1 #include <stdio.h>
     2 
     3 //慢速生成超大文件的方法。
     4 int main01()
     5 {
     6     FILE *p = fopen("a.dat", "w");
     7 
     8     int i;
     9     for (i = 0; i < 10000000; i++)
    10     {   
    11         char a = 0;
    12         fwrite(&a, 1, sizeof(a), p); 
    13     }   
    14     fclose(p);
    15 
    16     return 0;
    17 }
    18 
    19 //利用fseek函数瞬间生成超大文件的方法。
    20 int main()
    21 {
    22     FILE *p = fopen("a.dat", "w");
    23     
    24     fseek(p, 10000000, SEEK_SET);   //将文件指针从文件开始处位移10000000个字节。
    25     
    26     char a = 0;
    27     fwrite(&a, 1, sizeof(a), p); 
    28     fclose(p);
    29 
    30     return 0;
    31 }

    =============================================================================
    十四、ftell函数

      ftell函数用于得到文件位置指针当前位置相对于文件首的偏移字节。
      但是在随机方式存取文件时,由于文件位置频繁的前后移动,程序不容易确定文件的当前位置。

      long ftell(FILE *stream);
      例如:long len = ftell(fp);

    可以通过fseek和ftell得到文件大小:
    fseek(fp, 0, SEEK_END);
    long len = ftell(fp);
    --------------------------------------
    windows下示例代码:

     1 #include <stdio.h>
     2 
     3 int main(int argc, char **args)
     4 {
     5     if (argc < 2)
     6         return 0;
     7 
     8     FILE *p = fopen(args[1], "r");
     9     if (p == NULL)
    10         return 0;
    11 
    12     fseek(p, 0, SEEK_END);
    13     long size = ftell(p);
    14     printf("%ld
    ", size);
    15     fclose(p);
    16 
    17     return 0;
    18 }

    =============================================================================
    十五、fflush函数

      文本的读可以用:fgets和fscanf。
      文本的写可以用:fputs和fprintf。
      二进制文件读可以用:fread。
      二进制文件写可以用:fwrite。

    其实c语言所有的文件操作函数都是缓冲区函数。 即都是针对缓冲区进行操作的。

    文件读写缓冲区的说明如下图所示:


    --------------------------------------
    那么我们现在想绕过缓冲区,想直接将缓冲区的内容写入文件中(即磁盘)。该如何办呢?答:使用fflush函数。

      fflush函数可以将缓冲区中任何未写入的数据直接写入文件(即磁盘)中。
      函数执行成功则返回0,失败则返回EOF。

    int fflush(FILE *stream);
      由于fflush是实时的将缓冲区的内容写入磁盘,所以不要大量的去使用该函数;(因为会使程序执行效率降低,而且会影响磁盘寿命。)
      但如果是特别敏感的数据,可以通过fflush写入磁盘(比如密码),防止由于电脑的各种故障,内存数据的丢失。
      (因为内存一断电就没有数据了,而磁盘断电数据还在,不会丢失。)
    --------------------------------------
    windows下示例代码:

     1 //在缓冲区里面的代码:
     2 #include <stdio.h>
     3 
     4 int main()
     5 {
     6     FILE *p = fopen("a.txt", "w");
     7 
     8     while (1)
     9     {
    10         char a[100] = { 0 };
    11         scanf("%s", a);
    12         if (strcmp(a, "exit") == 0)
    13             break;
    14         fprintf(p, "%s
    ", a);
    15     }
    16     fclose(p);
    17     return 0;
    18 }
    19 --------------------------------------
    20 //绕过缓冲区里面的代码:
    21 #include <stdio.h>
    22 
    23 int main()
    24 {
    25     FILE *p = fopen("a.txt", "w");
    26 
    27     while (1)
    28     {
    29         char a[100] = { 0 };
    30         scanf("%s", a);
    31         if (strcmp(a, "exit") == 0)
    32             break;
    33         fprintf(p, "%s
    ", a);
    34         fflush(p);    //把缓冲区的数据直接同步到磁盘。
    35     }
    36     fclose(p);
    37     return 0;
    38 }

    =============================================================================
    十六、remove函数 和 rename函数 (文件删除函数和文件改名函数)

      remove函数删除指定的文件。
      int remove(const char *pathname);
      参数pathname为指定要删除的文件名,如果是windows下文件名与路径可以用反斜杠分隔,也可以用斜杠/分隔。

      rename函数将指定的文件改名。
      int rename(const char *OldFilename, const char *NewFilename);
    =============================================================================
    十七、通过fwrite将结构体保存到二进制文件中

    linux下示例代码:

     1 #include <stdio.h>
     2 #include <string.h>
     3 
     4 struct man 
     5 {
     6     char name[20];
     7     int age;
     8 };
     9 //向文件中写一个结构体。
    10 int insert()
    11 {
    12     //struct man m = {"苍老师", 40};
    13     //struct man m[3] = { {"苍老师", 40}, {"饭岛老师", 30}, {"陈冠希", 50} };
    14     struct man m = { 0 };
    15 
    16     FILE *p = fopen("a.dat", "a");  //a  以附加的方式打开只写文件。若文件不存在,则会建立该文件。
    17                                     //如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。(EOF符保留)
    18     if (p == NULL)
    19         return 0;
    20     //fwrite(&m, 1, sizeof(struct man), p);
    21     //fwrite(m, 3, sizeof(struct man), p);
    22     
    23     while (1) 
    24     {   
    25         printf("请输入名字:");
    26         scanf("%s", m.name);
    27         if (strcmp(m.name, "exit") == 0)
    28             break;
    29         printf("请输入年龄:");
    30         scanf("%d", &m.age);
    31         fwrite(&m, 1, sizeof(struct man), p); 
    32     }   
    33     fclose(p);
    34     return 0;
    35 }
    36 //向文件中读一个结构体。
    37 int select()
    38 {
    39     //struct man m = { 0 };
    40     //struct man m[3] = { 0 };
    41     struct man m = { 0 };
    42 
    43     FILE *p = fopen("a.dat", "r");
    44     if (p ==NULL)
    45         return 0;
    46     //fread(&m, 1, sizeof(struct man), p);
    47     //fread(m, 3, sizeof(struct man), p);
    48 
    49     while (1)
    50     {
    51         fread(&m, 1, sizeof(struct man), p);
    52         if (feof(p))
    53             break;
    54         printf("%s, %d
    ", m.name, m.age);
    55     }
    56     /*
    57     int i;
    58     for (i = 0; i < 3; i++)
    59     {
    60         //printf("%s, %d
    ", m.name, m.age);
    61         printf("%s, %d
    ", m[i].name, m[i].age);
    62     }
    63     */
    64     fclose(p);
    65     return 0;
    66 }
    67 //参数1代表写入,参数2代表读出。
    68 int main(int argc, int **args)
    69 {
    70     if (argc < 2)
    71         return 0;
    72     char c = args[1][0];
    73     if (c == '1')
    74         insert();
    75     if (c == '2')
    76         select();
    77     return 0;
    78 }

    =============================================================================
    课堂练习:
    上面的代码功能是:只能添加姓名和年龄,显示的时候只能全部显示出来。
    需要显示的时候,如果输入all,就全部显示,如果具体输入某一个人的名字,那么只显示这个人的名字和年龄。
    如果输入一个不存在的人名,那么就显示not found。

    linux下示例代码:

     1 #include <stdio.h>
     2 #include <string.h>
     3 
     4 struct man
     5 {
     6     char name[20];
     7     int age;
     8 };
     9 //向文件中写一个结构体。
    10 int myinsert()
    11 {
    12     //struct man m = {"苍老师", 40};
    13     //struct man m[3] = { {"苍老师", 40}, {"饭岛老师", 30}, {"陈冠希", 50} };
    14     struct man m = { 0 };
    15 
    16     FILE *p = fopen("a.dat", "a");  //a   以附加的方式打开只写文件。若文件不存在,则会建立该文件。
    17                                     //如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。(EOF符保留)
    18     if (p == NULL)
    19         return 0;
    20     //fwrite(&m, 1, sizeof(struct man), p);
    21     //fwrite(m, 3, sizeof(struct man), p);
    22 
    23     while (1)
    24     {
    25         printf("请输入名字:");
    26         scanf("%s", m.name);
    27         if (strcmp(m.name, "exit") == 0)
    28             break;
    29         printf("请输入年龄:");
    30         scanf("%d", &m.age);
    31         fwrite(&m, 1, sizeof(struct man), p);
    32     }
    33     fclose(p);
    34     return 0;
    35 }
    36 //向文件中读一个结构体。
    37 int myselect()
    38 {
    39     //struct man m = { 0 };
    40     //struct man m[3] = { 0 };
    41     struct man m = { 0 };
    42 
    43     char name[30] = { 0 };
    44     printf("请输入名字:");
    45     scanf("%s", name);
    46 
    47     FILE *p = fopen("a.dat", "r");
    48     if (p ==NULL)
    49         return 0;
    50     //fread(&m, 1, sizeof(struct man), p);
    51     //fread(m, 3, sizeof(struct man), p);
    52 
    53     int status = 0;
    54     while (1)
    55     {
    56         fread(&m, 1, sizeof(struct man), p);
    57         if (feof(p))
    58             break;
    59 
    60         if (strcmp(name, "all") == 0)
    61         {
    62             printf("%s, %d
    ", m.name, m.age);
    63             status = 1;
    64         }
    65         else
    66         {
    67             if (strcmp(name, m.name) == 0)
    68             {
    69                 printf("%s, %d
    ", m.name, m.age);
    70                 status = 1;
    71             }
    72         }
    73     }
    74     /*
    75     int i;
    76     for (i = 0; i < 3; i++)
    77     {
    78         //printf("%s, %d
    ", m.name, m.age);
    79         printf("%s, %d
    ", m[i].name, m[i].age);
    80     }
    81     */
    82     fclose(p);
    83     if (status == 0)
    84         printf("没有找到!
    ");
    85     return 0;
    86 }
    87 //参数1代表写入,参数2代表读出。
    88 int main(int argc, int **args)
    89 {
    90     if (argc < 2)
    91         return 0;
    92     char c = args[1][0];
    93     if (c == '1')
    94         myinsert();
    95     if (c == '2')
    96         myselect();
    97     return 0;
    98 }

    =============================================================================
    继续课堂练习:
    可以删除一个指定的人名和对应的年龄,如果输入一个没有的名字,那么什么也不做,不能增加新的文件。

    linux下示例代码:

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <stdlib.h>
      4 
      5 struct man
      6 {
      7     char name[20];
      8     int age;
      9 };
     10 //向文件中写一个结构体。
     11 int myinsert()
     12 {
     13     //struct man m = {"苍老师", 40};
     14     //struct man m[3] = { {"苍老师", 40}, {"饭岛老师", 30}, {"陈冠希", 50} };
     15     struct man m = { 0 };
     16 
     17     FILE *p = fopen("a.dat", "a");  //a   以附加的方式打开只写文件。若文件不存在,则会建立该文件。
     18                     //如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。(EOF符保留)
     19     if (p == NULL)
     20         return 0;
     21 
     22     //fwrite(&m, 1, sizeof(struct man), p);
     23     //fwrite(m, 3, sizeof(struct man), p);
     24     
     25     while (1)
     26     {
     27         printf("请输入名字:");
     28         scanf("%s", m.name);
     29         if (strcmp(m.name, "exit") == 0)
     30             break;
     31         printf("请输入年龄:");
     32         scanf("%d", &m.age);
     33         fwrite(&m, 1, sizeof(struct man), p);
     34     }
     35     fclose(p);
     36     return 0;
     37 }
     38 //向文件中读一个结构体。
     39 int myselect()
     40 {
     41     //struct man m = { 0 };
     42     //struct man m[3] = { 0 };
     43     struct man m = { 0 };
     44     
     45     char name[30] = { 0 };
     46     printf("请输入名字:");
     47     scanf("%s", name);
     48 
     49     FILE *p = fopen("a.dat", "r");
     50     if (p ==NULL)
     51         return 0;
     52 
     53     //fread(&m, 1, sizeof(struct man), p);
     54     //fread(m, 3, sizeof(struct man), p);
     55 
     56     int status = 0;
     57     while (1)
     58     {
     59         fread(&m, 1, sizeof(struct man), p);
     60         if (feof(p))
     61             break;
     62 
     63         if (strcmp(name, "all") == 0)
     64         {    
     65             printf("%s, %d
    ", m.name, m.age);
     66             status = 1;
     67         }
     68         else
     69         {
     70             if (strcmp(name, m.name) == 0)
     71             {
     72                 printf("%s, %d
    ", m.name, m.age);
     73                 status = 1;
     74             }
     75         }
     76     }
     77     /*
     78     int i;
     79     for (i = 0; i < 3; i++)
     80     {
     81         //printf("%s, %d
    ", m.name, m.age);
     82         printf("%s, %d
    ", m[i].name, m[i].age);
     83     }
     84     */
     85     fclose(p);
     86     if (status == 0)
     87         printf("没有找到!
    ");
     88     return 0;
     89 }
     90 //删除函数。
     91 int mydelete()
     92 {
     93     FILE *p = fopen("a.dat", "r");
     94     if (p == NULL)
     95         return 0;
     96 
     97     //得到文件的大小。
     98     fseek(p, 0, SEEK_END);
     99     int size = ftell(p);
    100     //文件多大就设置一个多大的堆空间。
    101     struct man *m = malloc(size);
    102     //一下子就把文件的所有内容读入堆内容。
    103     fseek(p, 0, SEEK_SET);
    104     fread(m, 1, size, p);
    105     fclose(p);
    106     //输入要删除的人的名字。
    107     printf("请输入要删除人的名字:");
    108     char name[30] = { 0 };
    109     scanf("%s", name);
    110 
    111     //得到有多少条记录。
    112     int n = size / sizeof(struct man);
    113     p = fopen("a.dat", "w");
    114     int i;
    115     for (i = 0; i < n; i++)
    116     {
    117         if (strcmp(m[i].name, name) != 0)
    118         fwrite(&m[i], 1, sizeof(struct man), p);
    119     }
    120     fclose(p);
    121     free(m);
    122     /*
    123     //把所有的记录打印出来看一下。
    124     int i;
    125     for (i = 0; i < n; i++)
    126     {
    127         printf("%s, %d
    ", m[i].name, m[i].age);
    128     }
    129     */
    130     return 0;
    131 }
    132 //参数1代表写入,参数2代表读出。参数3代表删除。
    133 int main(int argc, int **args)
    134 {
    135     if (argc < 2)
    136         return 0;
    137     char c = args[1][0];
    138     if (c == '1')
    139         myinsert();
    140     if (c == '2')
    141         myselect();
    142     if (c == '3')
    143         mydelete();
    144     return 0;
    145 }

    =============================================================================

  • 相关阅读:
    网络基础相关知识内容
    json模块的转义dump 和反转义 loap
    常用模块--time,sys,os,json
    正则表达式
    day_24 模块和包
    day23_内置函数(__del__ item系列 ,模块)
    LuoguP3806 【模板】点分治1 (点分治)
    BZOJ1305/Luogu3153 [CQOI2009]dance跳舞 (network flow)
    LuoguP2217 [HAOI2007]分割矩阵 (DP + memorized search)
    BZOJ3224/LuoguP3369 普通平衡树 (splay)
  • 原文地址:https://www.cnblogs.com/chenmingjun/p/8370838.html
Copyright © 2020-2023  润新知