• 5.1 C/C++ 使用文件与指针


    C/C++语言是一种通用的编程语言,具有高效、灵活和可移植等特点。C语言主要用于系统编程,如操作系统、编译器、数据库等;C语言是C语言的扩展,增加了面向对象编程的特性,适用于大型软件系统、图形用户界面、嵌入式系统等。C/C++语言具有很高的效率和控制能力,但也需要开发人员自行管理内存等底层资源,对于初学者来说可能会有一定的难度。

    读文件并输出内容: 逐个字符读取文件中的数据,直到遇到EOF结束标志是停止输出.

    #include 
    #include 
    
    int Read_File(FILE *fp)
    {
      if (fp == NULL)
        return 0;
    
      char ch;
      // while ((ch = fgetc(fp)) != EOF)
      while (!feof(fp))
      {
        ch = fgetc(fp);
        if (feof(fp))
          break;
        printf("%c", ch);
      }
    }
    
    int main(int argc, char* argv[])
    {
      FILE *fp = fopen("c:/lyshark.log", "r");
    
      Read_File(fp);
    
      system("pause");
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    堆空间读取数据: 首先我们将数据读入到自己分配的堆空间中,然后直接输出堆空间中的字符串.

    #include 
    #include 
    
    int main(int argc, char* argv[])
    {
    
      FILE *fp = fopen("c:/lyshark.log", "r");
    
      char *buffer = malloc(sizeof(char)* 1024);
    
      while (feof(fp) == 0)
      {
        memset(buffer, 0, 1024);
        fgets(buffer, 1024, fp);
        printf("%s", buffer);
      }
    
      system("pause");
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    一种特殊的文件操作: 这里我们举一个批量执行命令的案例,并通过格式化输出到缓冲区中.

    #include 
    
    int main(int argc, char* argv[])
    {
      char buffer[4096];
      FILE *fi = _popen("ipconfig", "r");
      while (fgets(buffer, 4096, fi) != NULL){
        fprintf(stdout, "%s", buffer);
      }
      system("pause");
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    写入字符串到文件: 将一个字符串写入到文件中,每次调用Write_File都可以写入一段字符串.

    #include 
    #include 
    #include 
    
    int Write_File(char *path, char *msg)
    {
      FILE *fp = fopen(path, "a+");
      if(fp== NULL) return -1;
    
      char ch, buffer[1024];
    
      int index = 0;
      while (msg[index] != '\0')
      {
        fputc(msg[index], fp);
        index++;
      }
      fclose(fp);
      return 1;
    }
    
    int main(int argc, char* argv[])
    {
      for (int x = 0; x < 10; x++)
        Write_File("c:/lyshark.log", "hello lyshark\n");
    
      system("pause");
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    实现动态数据存储(VIM): 通过循环实现动态接收用户输入数据,直到用户输入exit()命令后,才会停止程序运行.

    #include 
    
    int main(int argc, char* argv[])
    {
      FILE * fp = fopen("c:/lyshark.log", "w");
      if (fp == NULL)
        return -1;
    
      char buf[1024];
      while (1)
      {
        memset(buf, 0, 1024);
        fgets(buf, 1024, stdin);
        if (strncmp("exit()", buf, 6) == 0)
          break;
    
        int index = 0;
        while (buf[index] != '\0')
          fputc(buf[index++], fp);
      }
    
      fclose(fp);
      system("pause");
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    创建临时文件: 通过调用tmpfile()命令就可以实现创建临时文件,该文件在程序结束后会自动释放.

    #include 
    
    int main(int argc, char *argv[])
    {
      FILE *temp;
      char c;
      if ((temp = tmpfile()) != NULL)
      {
        fputs("hello lyshark\n", temp); // 向临时文件中写入要求内容
      }
      rewind(temp);                       // 文件指针返回文件首
      while ((c = fgetc(temp)) != EOF)    // 读取临时文件中内容
        printf("%c", c);
      fclose(temp);
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    重命名文件: 重命名文件则可以调用rename()这条命令,但需要提前打开文件后才能操作.

    #include 
    
    int Rename_File(char *src_name, char *dst_name)
    {
      FILE *fp = fopen(src_name, "r");
      if (fp != NULL)
      {
        rename(src_name, dst_name);
        fclose(fp);
      }
      return 0;
    }
    
    int main(int argc, char* argv[])
    {
      Rename_File("c:/test.log", "c:/lyshark.log");
    
      system("pause");
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    删除特定文件: 时拿出文件则使用remove()函数即可,删除成功返回1,失败返回0.

    #include 
    
    int Delete_File(char *file_name)
    {
      FILE *fp;
    
      if ((fp = fopen(file_name, "r")) != NULL)
        fclose(fp);
      remove(file_name);
    
      if ((fp = fopen(file_name, "r")) == NULL)
        return 1;
      return 0;
    }
    
    int main(int argc, char* argv[])
    {
      Delete_File("c:/lyshark.log");
    
      system("pause");
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    实现小文件拷贝: 小文件的拷贝我们可以使用逐个字节的方式拷贝,这种方式拷贝较慢,且拷贝资源时大量占用栈空间.

    #include 
    
    int Copy_File(const char *src,const char *dst)
    {
      FILE *src_file = fopen(src, "rb");
      FILE *dst_file = fopen(dst, "wb");
    
      if (src_file == NULL || dst_file == NULL)
        return - 1;
    
      char buffer;
    
      while (fread(&buffer,sizeof(char),1,src_file) != 0)
      {
        fwrite(&buffer, sizeof(char), 1, dst_file);
      }
    
      fcloseall();
      return 1;
    }
    
    int main(int argc, char * argv[])
    {
      Copy_File("c:/test.exe", "c:/lyshark.exe");
    
      system("pause");
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    实现大文件拷贝: 如果是大文件的拷贝,我们将不能使用栈来传递数据,我们需要开辟堆空间,来实现拷贝.

    #include 
    #include 
    
    int Copy_File(const char *src, const char *dst)
    {
      FILE *src_file = fopen(src, "rb");
      FILE *dst_file = fopen(dst, "wb");
    
      if (src_file == NULL || dst_file == NULL)
        return -1;
    
      char *buffer;
    
      buffer = (char *)malloc(sizeof(char)* 1024);   // 开辟一段堆空间
      memset(buffer, 0, 1024);                       // 对该空间进行初始化
    
      while (fread(buffer, sizeof(char), 1024, src_file) != 0)
      {
        fwrite(buffer, sizeof(char), 1024, dst_file);
        memset(buffer, 0, 1024);
      }
    
      free(buffer);
      fcloseall();
      return 1;
    }
    
    int main(int argc, char * argv[])
    {
      Copy_File("c:/test.exe", "c:/lyshark.exe");
      system("pause");
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    实现两个文件的合并: 将两个文本文件中的内容aaa.log合并到bbb.log中.

    #include 
    
    int Merge_File(const char *src, const char *dst)
    {
      FILE *src_file = fopen(src, "r");
      FILE *dst_file = fopen(dst, "a+");
    
      if (src_file == NULL || dst_file == NULL)
        return -1;
    
      char buffer;
      fseek(dst_file, 0, SEEK_END);
    
      buffer = fgetc(src_file);
      while (!feof(src_file))
      {
        fputc(buffer, dst_file);
        buffer = fgetc(src_file);
      }
      fcloseall();
      return 1;
    }
    
    int main(int argc, char * argv[])
    {
      Merge_File("c:/aaa.log", "c:/bbb.log");
      system("pause");
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    读取文件总行数: 使用该方法可实现统计指定文件中文件的存在行数,该函数并未过滤特殊字符.

    #include 
    #include 
    
    int Get_File_Line(FILE *fp)
    {
      if (fp == NULL) return -1;
    
      char buffer[4096] = { 0 };
      int line = 0;
    
      while (fgets(buffer, 4096, fp) != NULL)
        ++line;
      // 恢复指针起始位置
      fseek(fp, 0, SEEK_SET);
      return line + 1;
    }
    
    int main(int argc, char* argv[])
    {
      FILE *fp = fopen("c:/lyshark.log", "r");
    
      int line = Get_File_Line(fp);
      printf("文件总行数: %d \n", line);
    
      system("pause");
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    读取文件有效行数: 这个案例我们在上面的代码上稍加修改就能实现,我们主要筛选出符合规范的行.

    #include 
    #include 
    
    // 该方法用于逐行验证是否符合规范
    // 规范: 开头不能是#以及空白行,字符中必须存在:冒号.
    int Verification(const char *buf)
    {
      if (buf[0] == '#' || buf[0] == '\n' || strchr(buf, ':') == NULL)
        return 0;
      return 1;
    }
    
    // 实现获取文件中符合要求的行数量
    int Get_File_Line(FILE *fp)
    {
      char buffer[1024] = { 0 };
      int index = 0;
    
      while (fgets(buffer, 1024, fp) != NULL)
      {
        if (!Verification(buffer))    // 验证是否符合要求
          continue;                 // 不符合则跳过本次循环
        memset(buffer, 0, 1024);      // 符合则先来初始化内存
        index++;
      }
      fseek(fp, 0, SEEK_SET);
      return index;
    }
    
    int main(int argc, char * argv[])
    {
      FILE *fp = fopen("c:/conf.ini", "r");
      int line = Get_File_Line(fp);           // 获取文件有效行
      printf("有效行: %d \n", line);          // 输出符合要求的行数
    
      system("pause");
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    实现获取文件大小: 此处的文件大小指的是文件在磁盘中所占用的物理存储单位.

    #include 
    
    int Get_File_Size(const char *file_name)
    {
      FILE *fp;
      long file_size;
    
      if (fp = fopen(file_name, "r"))
      {
        fseek(fp, 0, SEEK_END);
        file_size = ftell(fp);
        fcloseall();
        return file_size;
      }
      return 0;
    }
    
    int main(int argc, char * argv[])
    {
      long ret = Get_File_Size("c:/lyshark.exe");
      printf("文件大小是: %d 字节 \n", ret/1024);
    
      system("pause");
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    获取文本中每行字符数: 统计指定的文本中,每行数据的字符数量.

    #include 
    #include 
    #include 
    
    // 获取文件总行数
    int Get_File_Line(FILE *fp)
    {
      if (fp == NULL) return -1;
    
      char buf[1024] = { 0 };
      int line = 0;
      while (fgets(buf, 1024, fp) != NULL)
      {
        ++line;
      }
      fseek(fp, 0, SEEK_SET);
      return line;
    }
    
    // 输出每行中字符数量
    void MyPrint(FILE *fp,char **ptr,int len)
    {
      char buffer[2048] = { 0 };
      int index = 0;
    
      while (fgets(buffer, 2048, fp) != NULL)
      {
        int cur_len = strlen(buffer) + 1; // 获取每行数据长度
    
        printf("文件行: %d --> 该行字符数: %d \n", index + 1, cur_len);
        index++;
        memset(buffer, 0, 2048);
      }
    }
    
    int main(int argc, char * argv[])
    {
      FILE *fp = fopen("c:/conf.ini", "r");
      int len = Get_File_Line(fp);
    
      char **ptr = malloc(sizeof(char *)* len);   // 分配行数取决于文件行数
    
      MyPrint(fp, ptr, len);                      // 输出每行中的字符数量
    
      system("pause");
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    实现文件加解密: 此处对二进制字符进行异或操作得到,第一次调用函数可加密,第二次调用函数实现解密.

    #include 
    #include 
    
    int encrypt(char *src_file, char *dst_file, char *passwd)
    {
      FILE *fp_src = fopen(src_file, "rb");
      FILE *fp_dst = fopen(dst_file, "wb");
    
      if (fp_src == NULL || fp_dst == NULL)
        return - 1;
      char ch;
    
      while (!feof(fp_src))
      {
        ch = fgetc(fp_src);
        if (feof(fp_src))
          break;
    
        ch = ch ^ *(passwd); // 使用密码对目标进行异或操作
        fputc(ch, fp_dst);   // 将字符串写入到目标文件中
      }
    
      fclose(fp_src);
      fclose(fp_dst);
      return 1;
    }
    
    int main(int argc, char* argv[])
    {
      int encode_ret = encrypt("c:/lyshark.log", "c:/encode.log", "1233");
      if (encode_ret == 1)
        printf("加密完成 \n");
    
      int decode_ret = encrypt("c:/encode.log", "c:/decode.log", "1233");
      if (decode_ret == 1)
        printf("解密完成 \n");
    
      system("pause");
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    实现格式化读写: 两个函数fprintf()/fscanf()分别实现对数据的格式化读取与格式化写入.

    #include 
    
    struct Student
    {
      int uid;
      char name[20];
      int age;
    };
    
    void write()
    {
      FILE *fp = fopen("c://lyshark.log", "wt+");
    
      struct Student stu[3] = {
        { 1001, "admin", 22 },
        { 1002, "guest", 33 },
        { 1003, "uroot", 12 },
      };
    
      // 将数据格式化输出到文本中保存
      for (int x = 0; x < 3; x++)
        fprintf(fp, "%d %s %d \n", stu[x].uid, stu[x].name, stu[x].age);
      fclose(fp);
    }
    
    void read()
    {
      struct Student stu;
    
      FILE *fp = fopen("c://lyshark.log", "r");
    
      while (fscanf(fp, "%d %s %d \n", &stu.uid, &stu.name, &stu.age) != EOF)
      {
        printf("UID: %d --> Name: %s --> Age: %d \n", stu.uid, stu.name, stu.age);
      }
    
      /* 此处的方法也可以实现
      while (fgets(buffer, 1024, fp) != NULL)
      {
      sscanf(buffer,"%d %s %d \n", stu.uid, stu.name, stu.age);
      index++;
      }
      */
    }
    
    int main(int argc, char* argv[])
    {
      write();
      read();
    
      system("pause");
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    实现结构随机读写: 我们可以通过文件操作将结果数据写入文件,然后通过fseek()移动指针来遍历结构数据.

    #include 
    
    struct Student
    {
      int uid;
      char name[20];
      int age;
    };
    
    void Write()
    {
      struct Student stu[3] = {
        { 1001, "admin", 22 },
        { 1002, "guest", 33 },
        { 1003, "uroot", 12 },
      };
    
      FILE *fp = fopen("c://lyshark.log", "wb+");
    
      /* 第一种写入文本的方式
      for (int x = 0; x < 3; x++)
      fprintf(fp, "%d %s %d \n", stu[x].uid, stu[x].name, stu[x].age);
      fclose(fp);
      */
    
      // 随机读写
      fwrite(stu, sizeof(struct Student), 3, fp);   // 写入三条数据
      fclose(fp);
    }
    
    int main(int argc, char* argv[])
    {
      Write();    // 调用函数,写入测试数据
    
      struct Student p;
      FILE *fp = fopen("c://lyshark.log", "rb+");
    
      fseek(fp, sizeof(struct Student), SEEK_SET);        // 移动文件指针,到下一个结构
      fread(&p, sizeof(struct Student), 1, fp);           // 读取数据
      printf("UID: %d ---> Name: %s \n", p.uid, p.name);  // 输出读取到的数据
    
      fread(&p, sizeof(struct Student), 1, fp++);         // 读取下一个数据
      printf("UID: %d ---> Name: %s \n", p.uid, p.name);  // 输出读取到的数据
    
      system("pause");
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    实现数组块读写: 将数组通过文件写入到磁盘中保存,然后再从磁盘中将其取出来.

    #define _CRT_SECURE_NO_WARNINGS
    #include 
    
    int main(int argc, char* argv[])
    {
      int Array[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    
      // 将数组写入到文件中保存
      FILE *write = fopen("c://list.log", "wb");
      fwrite(Array, sizeof(int), 10, write);
      fclose(write);
    
      // -----------------------------------------------
      // 从文件中读取数组元素
      FILE *read = fopen("c://list.log", "rb");
    
      int NewArray[10] = { 0 };
      int index = 0;
    
      while (!feof(read))
      {   // 将数据逐个读取到数组中存储.
        fread(&NewArray[index], sizeof(int), 1, read);
        index++;
      }
      fclose(read);
    
      // 循环打印出数组元素
      for (int x = 0; x < 10; x++)
        printf("%d \n", NewArray[x]);
    
      system("pause");
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    实现结构块读写: 在定义结构块的时候,不应使用指针变量,因为指正无法被转储到文件中.

    #include 
    #include 
    
    struct Student
    {
      int uid;
      char name[30];
      int age;
    };
    
    // 保存结构到文件中
    int Save_Struct(struct Student *ptr, int len)
    {
      FILE *fp = fopen("c:/save.log", "wb");
      if (fp == NULL)
        return -1;
    
      for (int x = 0; x < len; x++)
      {
        fwrite(&ptr[x], sizeof(struct Student), 1, fp);
      }
      fclose(fp);
      return 0;
    }
    
    // 从文件中加载结构
    int Load_Struct(struct Student *ptr)
    {
      FILE *fp = fopen("c:/save.log", "rb");
      if (fp == NULL)
        return -1;
      int index = 0;
    
      while (!feof(fp))
      {
        fread(&ptr[index], sizeof(struct Student), 1, fp);
        index++;
      }
      fclose(fp);
      return 0;
    }
    
    int main(int argc, char* argv[])
    {
      struct Student stu[3] = {
        { 1001, "admin", 22 },
        { 1002, "guest", 33 },
        { 1003, "root", 12 },
      };
    
      Save_Struct(&stu, 3);  // 保存文件
    
      // 将输入读取到read_stu结构中
      struct Student read_stu[3];
      Load_Struct(&read_stu);
    
      for (int x = 0; x < 3; x++)
        printf("UID: %d --> Name: %s --> Age: %d \n", read_stu[x].uid, read_stu[x].name, read_stu[x].age);
    
      system("pause");
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    针对文件内容的排序: 首先将文件格式化读取到堆中,然后排序,排序完成以后再次会写到文件中.

    #include 
    #include 
    #include 
    
    // 先来生成一些测试数据
    void Random()
    {
      srand((unsigned int)time(NULL));
      FILE *fp = fopen("c:/lyshark.log", "w");
      if (!fp)
        return -1;
    
      for (int x = 0; x < 10000; x++)
      {
        fprintf(fp, "%d\n", rand() % 1000 + 1);
      }
      fcloseall();
    }
    
    int main(int argc, char * argv[])
    {
      FILE *fp = fopen("c:/lyshark.log", "r");
      if (!fp)
        return -1;
    
      // 动态的分配堆空间,此处分配10000个int空间
      int *ptr = (int *)malloc(sizeof(int)* 10000);
    
      // 读取数据,并动态放入堆空间中.
      for (int x = 0; x < 10000; x++)
        fscanf(fp, "%d\n", &ptr[x]);
    
      // 使用冒泡排序,对堆空间进行排序
      for (int x = 0; x < 10000; x++)
      {
        for (int y = 0; y < 10000 - x - 1; y++)
        {
          if (ptr[y] > ptr[y + 1])
          {
            int tmp = ptr[y];
            ptr[y] = ptr[y + 1];
            ptr[y + 1] = tmp;
          }
        }
      }
    
      fcloseall();
    
      // 排序完成后,开始写入数据
      FILE *fp1 = fopen("c:/lyshark.log", "w");
      if (!fp1)
        return -1;
    
      for (int x = 0; x < 10000; x++)
        fprintf(fp1, "%d\n", ptr[x]);
    
      fcloseall();
      free(ptr);
    
      system("pause");
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    实现配置文件解析: 这里我们定义一个配置文件,格式为username:root,然后通过编程实现遍历指定的key=value键值对.

    #include 
    #include 
    
    // 配置文件数组
    struct ConfigInfo
    {
      char key[64];
      char val[128];
    };
    
    // 判断数据是否符合规则
    int isvald(const char *buf)
    {
      if (buf[0] == '#' || buf[0] == '\n' || strchr(buf, ':') == NULL)
        return 0;
      return 1;
    }
    
    // 获取有效行
    int get_line(FILE *fp)
    {
      char buffer[1024] = { 0 };
      int index = 0;
    
      while (fgets(buffer, 1024, fp) != NULL)
      {
        if (!isvald(buffer))
          continue;
        memset(buffer, 0, 1024);
        index++;
      }
      fseek(fp, 0, SEEK_SET);
      return index;
    }
    
    // 加载有效行,到内存栈地址
    void load(const char *path, char **data, int *len)
    {
      FILE *fp = fopen(path, "r");
    
      int line = get_line(fp);      // 获取有效行
      char **tmp = malloc(sizeof(char *)* line);   // 给每行开辟空间
    
      char buf[1024] = { 0 };
      int index = 0;
    
      while (fgets(buf, 1024, fp) != NULL)
      {
        if (!isvald(buf))
          continue;
    
        tmp[index] = malloc(strlen(buf) + 1);
        strcpy(tmp[index], buf);
        memset(buf, 0, 1024);
        ++index;
      }
    
      *data = tmp;  // 返回结构数据
      *len = line;  // 返回有效行数
      fcloseall();
    }
    
    // 解析配置文件,data = 结构数据 len = 结构数量 key = 待查找字符串
    char * parser(char **data, int len, struct ConfigInfo **info, char *key)
    {
      struct ConfigInfo *tmp = malloc(sizeof(struct ConfigInfo) * len);
      memset(tmp, 0, sizeof(struct ConfigInfo) * len);
    
      for (int x = 0; x < len; x++)
      {
        char *pos = strchr(data[x], ':');
    
        strncpy(tmp[x].key, data[x], pos - data[x]);     // 拷贝key
        strncpy(tmp[x].val, pos + 1, strlen(pos + 1) - 1);   // 拷贝val
    
        printf("key: %s --> val: %s \n", tmp[x].key, tmp[x].val);
        // 判断如果我们要找的key = my[x].key 则找到了,直接返回
        if (strcmp(key, tmp[x].key) == 0)
          return tmp[x].val;
      }
    
      // 释放文件
      for (int y = 0; y < len; ++y)
      {
        if (data[y] != NULL)
          free(data[y]);
      }
    }
    
    int main(int argc, char * argv[])
    {
      char *data = NULL;
      struct ConfigInfo *info = NULL;
      int lines = 0;
    
      load("c:/conf.ini", &data, &lines);
    
      char * username = parser(data, lines, &info, "username");
      printf("读取到 username 变量中的值: %s \n", username);
    
      char * password = parser(data, lines, &info, "password");
      printf("读取到 password 变量中的值: %s \n", password);
    
      system("pause");
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
  • 相关阅读:
    集合原理简记
    iview label-in-value 和 @on-change 的使用
    vscode 阅读 android以及kernel 源码
    【校招VIP】排序算法之高级排序
    设计模式之观察者(发布订阅)模式
    python爬虫入门详细教程-采集云南招聘网数据保存为csv文件
    Docker下载、安装、卸载
    Redis02-持久化策略
    1.2 无处不在的进程和线程
    超分辨率论文阅读
  • 原文地址:https://blog.csdn.net/lyshark_csdn/article/details/133741930