【c基础】文件操作

news2024/11/18 6:48:40

1.fopen和fclose函数

函数原型

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

参数解释:

  • 返回值:fopen打开成功,则返回有效file的有效地址,失败返回NULL。
  • path是文件路径,可以相对路径,可以绝对路径
  • mode是模式
mode说明
r或者rtr以只读的方式打开文本文件,该文件必须存在,且是可读的。在一些系统上,r 模式也可以打开二进制文件,但这并不是标准行为。与 r 模式相比,rt 模式明确地指示打开文件为文本模式,但在大多数系统上,它与 r 模式的行为相同。
w或者wt打开只写文件,若文件存在则文件长度清0,即该文件内容会消失,若文件不存在则建 立该文件只写打开或建立一个文本文件,只允许写数据。
a或者at以追加的方式打开只写文件,若文件不存在则建立该文件,若文件存在,写入的内容将 被追加到文件末尾,即文件原先的内容会被保留。(EOF符保留)
rb只读打开一个二进制文件,只允许读数据
wb只写打开或建立一个二进制文件,只允许写数据
ab追加打开一个二进制文件,并在文件末尾写数据
r+或者rt+r+以可读写的方式打开,+号表示该文件必须存在。与 r+模式相比,rt+模式明确地指示打开文件为文本模式。
w+或者wt+打开可读写文件,若文件存在则文件长度清0,即该文件内容会消失,若文件不存在 则建立该文件。
a+或者at+以追加的方式打开可读写文件,若文件不存在则建立该文件,若文件存在,写入的内 容将被追加到文件末尾,即文件原先的内容会被保留。(原来的EOF符不保留)
rb+读写打开一个二进制文件,允许读写数据,文件必须存在
wb+读写打开或建立一个二进制文件,允许读和写
ab+读写打开一个二进制文件,允许读,或在文件末追加数据
rw+读写打开一个文本文件,允许读和写

读写文件出错的一大原因可能是没有权限。


fopen打开读取的文件内容占用的内存在堆里面,用fclose可以释放掉。

fclose关闭fopen打开的文件。只要成功用fopen打开的文件,使用完成后就一定要调用fclose关闭。fclose的参数就是fopen的返回值。

一个程序同时可以打开的文件数是有限的,如果超过系统限制,那么打开文件会失败。

一个fopen会占用一些内存,多个就会对内存消耗很大。

所以记得要fopen使用完文件后及时的fclose。


代码示例:

#include <stdio.h>

int main()
{
    // 1.判断文件是否能打开
    // FILE *p = fopen("./test.txt", "r");
    // char *filepath = "./test.txt";
    char filepath[] = "./test.txt";
    FILE *p = fopen(filepath, "w");
    if (p)
    {
        printf("%p\n", p); // 00007FF98D85FA90
        printf("open success\n");
    }
    else
    {
        printf("open fail\n");
    }

    // 2.关闭文件
    if (p)
    {
        fclose(p);
        printf("close success\n");
    }

    return 0;
}

2.文本文件与二进制文件的区别

基于字符编码vs基于值编码

计算机的存储在物理上是二进制的,所以文本文件与二进制文件的区别并不是物理上的,而是逻辑上的。这两者只是在编码层次上有差异,简单来说,文本文件是基于字符编码的文 件,常见的编码有ASCII编码,UNICODE编码等等。二进制文件是基于值编码的文件,你可以根据具体应用,指定多少个比特代表一个值。

从上面可以看出文本文件基本上是定长编码的(也有非定长的编码如UTF-8)。而二进制文件可看成是变长编码的,因为是值编码嘛,多少个比特代表一个值,完全由你决定。

写入和读取时的区别

文本工具打开一个文件的过程是怎样的呢?拿记事本来说,它首先读取文件物理上所对应的二进 制比特流,然后按照你所选择的解码方式来解释这个流,然后将解释结果显示出来。

一般来说, 你选取的解码方式会是ASCII码形式(ASCII码的一个字符是8个比特),接下来,它8个比特8 个比特地来解释这个文件流。

例如对于这么一个文件流"01000000_01000001_01000010_01000011"(下划线''_'',为了增强可读性手动添加的), 第一个8比特''01000000''按ASCII码来解码的话,所对应的字符是字符''A'',同理其它3个8比特 可分别解码为''BCD'',即这个文件流可解释成“ABCD”,然后记事本就将这个“ABCD”显示在屏 幕上。

再比如文件流''00000000_00000000_00000000_00000001''可能在二进制文件中对应的是一 个四字节的整数int 1,在记事本里解释就变成了"NULL_NULL_NULL_SOH"这四个控制符。

字符数据本身在内存中就经过了编码,所以无论是二进制还是文本形式都是一样的,而对于非字 符数据来说,例如char i=10;如果用二进制来进行存储的话为00001010,但是如果需要用文本形式来 进行存储的话就必须进行格式化编码(对1和0分别编码,即形式为‘1’和‘0’分别对应的码值,即00000001 和 00000000写入文件中)。

  • FILE *writep = fopen("a.dat", "w"); //"w"按文本文件的字符编码写入,比如写入数字 10 (char类型), 则会将字符'1'和'0'对应的ASCII编码,即00000001 和 00000000依次写入 a.dat中
  • FILE *writep = fopen("a.dat", "wb"); //"wb"按二进制文件的二进制编码写入,比如写入 数字 10(char类型), 会将10对应的二进制编码 比如 00001010 写入 a.dat中

文本文件的存储与其读取基本上是个逆过程。而二进制文件的存取显然与文本文件的存取差不 多,只是编/解码方式不同而已。

优缺点比较

  • 一般认为,文本文件编码基于字符定长,译码容易些;二进制文件编码是变长的,所以它灵活, 存储利用率要高些,译码难一些(不同的二进制文件格式,有不同的译码方式)。
  • 文本文件每条数据通常是固定长度的。以ASCII为例,每条数据(每个字符)都是1个字节。二进制 进制文件每条数据不固定。如short占两个字节,int占四个字节,float占8个字节。
  • 文本文件只能存储char型字符变量。二进制文件可以存储char/int/short/long/float/……各种 变量值。
  • 在windows下,文本文件不一定是一ASCII来存贮的,因为ASCII码只能表示128的标识,你打开一个 txt文档,然后另存为,有个选项是编码,可以选择存贮格式,一般来说UTF-8编码格式兼容性要好一 些,而二进制用的计算机原始语言,不存贮兼容性。

3.win和linux文本文件中换行符的区别

windows读写文件时

  • windows所有的文本文件都是\r\n结尾的,而不是\n结尾的,所以这里要占2个字节。
    • 写入时,如果是文本方式写入即用"w"参数时,每遇到一个''\n'',它将其换成''\r \n'', 然后再写入文件;
    • 读取时,当文本读取即用"r"参数时,它每遇到一个''\r\n''将其反变化为''\n'',然后送到 读缓冲区。
  • 对于二进制文件,正常读写,不存在任何转换。

linux读写文件时:

  • linux所有的文本文件,本来就是\n结尾的,前面没有\r,参数b在linux是无效的
  • 二进制文件,正常读写,不存在任何转换

windows和Linux间文本文件格式转换

  • linux转windows:unix2dos -n a.txt b.txt。将a.txt 中的\n变为\r\n,然后另存为b.txt。
  • windows转linux:dos2unix -n b.txt c.txt。将b.txt 中的\r\n变为\n,然后另存为c.txt。

示例代码理解windows下"r"的存在

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>

int main()
{
    // 1.打印每个字符和对应的ASCII码
    FILE *filep = fopen("./add.txt", "r");
    unsigned char a = 0;
    while (1)
    {
        fread(&a, 1, sizeof(char), filep);
        if (feof(filep))
        {
            break;
        }
        printf("(%c,%d)\n", a, a);
    }
    fclose(filep);
    
    // 2.获取文件大小(注意'\r'也占用了一个字节)
    struct stat st = {0};
    stat("./add.txt", &st);
    printf("size=%d\n", st.st_size); // size=12
    // 'h' 'e' 'l' 'l' 'o' '\r' '\n' 'w' 'o' 'r' 'l' 'd'
    return (0);
}
/*
(h,104)
(e,101)
(l,108)
(l,108)
(o,111)
(
,10)
(w,119)
(o,111)
(r,114)
(l,108)
(d,100)
size=12
*/

4.getc和putc函数

getc

已字节为单位读写文件。

函数原型

char getc(FILE *stream);

说明:

  • getc的参数是fopen成功打开文件后返回的指针,getc的返回值是一个char
  • getc的功能是以字节为单位读取文件内容。注意当文本文件中存在汉字内容时,读取会出现乱码,因为一个汉字占2个字节(gbk编码时)或者3个字节(utf-8编码时)。
  • 文本文件的最后结束标示是-1,是一个宏常量EOF
#define EOF -1

示例代码

#include <stdio.h>

int main()
{
    // 1.判断文件是否能打开
    char filepath[] = "./test.txt";
    FILE *p = fopen(filepath, "r");
    if (p)
    {
        printf("open %s success\n", filepath);
        // 2.读取内容
        char c = getc(p); // 读取一个字节内容
        printf("%c\n", c);
        c = getc(p); // 再读取一个字节内容
        printf("%c\n", c); 
    }
    else
    {
        printf("open %s fail\n", filepath);
    }

    // 3.关闭文件
    if (p)
    {
        fclose(p);
        printf("close success\n");
    }
    return 0;
}

用循环打印文件所有内容

#define EOF -1

EOF不是文件的一部分内容,只是文件结束的标识

#include <stdio.h>

int print_file(char *filepath)
{
    char c;
    FILE *p = fopen(filepath, "r");
    if (p)
    {
        printf("open %s success\n", filepath);
        c = getc(p);
        while (c != EOF)
        {
            printf("%c", c);
            c = getc(p);
        }

        fclose(p);
    }
    else
    {
        printf("open %s fail\n", filepath);
        return -1;
    }

    return 0;
}

int main()
{
    // 打开文件
    //char filepath[] = "./test.txt";
    //char filepath[] = "./test.c";
    char filepath[] = "./test.txt";
    int ret = print_file(filepath);
    printf("ret=%d\n", ret);

    return 0;
}

自定义读取文件一行内容的函数

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int read_line(char *filepath, char **file_data)
{
    FILE *filep = fopen(filepath, "r");
    if (!filep)
    {
        perror("fopen");
        return -1;
    }

    int line_size = 1;
    char *content = (char *)malloc(line_size);
    if (content == NULL)
    {
        perror("malloc");
        fclose(filep);
        return -2;
    }

    // 初始化content为空字符串 
    content[0] = '\0';

    int count = 0;
    int is_finish = 0;
    int i = 0;
    while (1)
    {
        char temp[1024] = {0};
        for (i = 0; i < 1023; i++)
        {
            char c = getc(filep);
            if (c == '\n' || c == EOF)
            {
                is_finish = 1;
                break;
            }
            temp[i] = c;
            count++;
        }

        
        if (count > 0) // 只有在读取到字符时才进行内存分配和字符串拼接
        {
            if (count >= line_size)
            {
                char *ret = (char *)realloc(content, count+1);
                if (ret == NULL)
                {
                    perror("realloc");
                    free(content); // 释放之前的内存
                    fclose(filep);
                    return -3;
                }
                content = ret;
                line_size = count + 1;
            }

            strcat(content, temp);

            // 添加空字符,确保字符串正确终止
            content[count] = '\0'; 
        }

        if (is_finish)
        {
            break;
        }
       
       
    }
    
    // printf("(%s)\n", content);   // 文件内容
    // printf("count=%d\n", count); // 字节数

    *file_data = content;

    fclose(filep);

    return 0;
}

int main()
{
    char filepath[100] = "./test.txt";
    char *file_content;

    int ret = read_line(filepath, &file_content);
    printf("ret = %d\n", ret);

    if (ret == 0)
    {
        printf("(%s)\n", file_content);
        printf("content len=%d\n", strlen(file_content));

        free(file_content);  
    }
    else
    {
        printf("Error reading line from file\n");  
    }


    return 0;
}

putc

函数原型

int putc(int c, FILE *stream);

第一个参数是要写入的char, 第二个参数是fopen返回的文件指针

getc参数的文件指针必须是用r模式打开,putc必须是用w模式打开

#include <stdio.h>

int main()
{
    // 打开文件
    char filepath[] = "./test.txt";
    FILE *filep = fopen(filepath, "w");
    if (filep)
    {
        // 写入内容
        putc('a', filep);
        putc('\n', filep);
        putc('b', filep);
        putc('c', filep);
        // 关闭文件
        fclose(filep);
    }
    else
    {
        printf("open fail\n");
    }
    
    return 0;
}

自定义将字符串写入文件的函数

#include <stdio.h>
#include <string.h>

void write_str(char *filepath, const char *s, unsigned int len)
{
    FILE *filep = fopen(filepath, "w");
    if (filep)
    {
        for (int i = 0; i < len; i++)
        {
            printf("%c", s[i]);
            putc(s[i], filep);
        }
        fclose(filep);
    }
    else
    {
        printf("open fail\n");
    }
}

int main()
{
    char filepath[] = "./test.txt";
    char mystr[50] = "hello world";
    int len;
    // len = sizeof(mystr)/sizeof(mystr[0]);
    len = strlen(mystr); //用字符串长度
    write_str(filepath, mystr, len);

    return 0;
}

自定义文件拷贝函数实现命令行命令

使用c语言的main函数还可以自定义命令行的命令

比如可执行文件的名字叫 copyfile,通过设计源代码的main函数可以达到命令行的作用

  1. gcc test.c -o copyfile
  2. copyfile test.txt test_write.txt
  3. 可以实现将test.txt拷贝为test_write.txt

示例代码

#include <stdio.h>

void copyfile(char *srcPath, char *tarPath)
{
    FILE *readp = fopen(srcPath, "r");
    FILE *writep = fopen(tarPath, "w");
    if (readp && writep)
    {
        while (1)
        {
            char c = getc(readp);
            if (c == EOF)
            {
                break;
            }
            putc(c, writep);
        }
    }

    fclose(readp);
    fclose(writep);
}

int test()
{
    char filepath[] = "./test.txt";
    char writePath[] = "./test_write.txt";
    copyfile(filepath, writePath);
    return 0;
}

int main(int argc, char **args)
{
    if (argc < 3)
    {
        printf("params less than 3");
        return -1;
    }

    copyfile(args[1], args[2]);

    return 0;
}


运行

[root@localhost test]# gcc main.c -o main
[root@localhost test]# ./main test.txt test_copy.txt

简单的文件加密和解密

加密:将一份文件拷贝时,给每个字符通过加减乘除或者指定函数等指定规则变为另一个字符再写入另一个文件。

解密:按加密的方式逆向获得原字符。

示例代码:

#include <stdio.h>

void copyfile(char *srcPath, char *tarPath, char isEncode)
{
    FILE *readp = fopen(srcPath, "r");
    FILE *writep = fopen(tarPath, "w");
    if (readp && writep)
    {
        while (1)
        {
            char c = getc(readp);
            if (c == EOF)
            {
                break;
            }

            if (isEncode == '+')
                c++;
            else
                c--;
            
            putc(c, writep);
        }
    }

    fclose(readp);
    fclose(writep);
}

int test()
{
    char filepath[] = "./test.txt";
    char writePath[] = "./test_write.txt";
    copyfile(filepath, writePath, '+');
    return 0;
}

int main(int argc, char *argv[])
{
    if (argc < 4)
    {
        printf("params less than 3");
        return -1;
    }

    copyfile(argv[1], argv[2], argv[3][0]);

    return 0;
}

运行效果

[root@localhost test]# gcc main.c -o main
[root@localhost test]# ./main test.txt test_encode.txt +
[root@localhost test]# cat test.txt
hello world
[root@localhost test]# cat test_encode.txt 
ifmmp!xpsme
           [root@localhost test]# 
[root@localhost test]# ./main test_encode.txt test_decode.txt -
[root@localhost test]# cat test_decode.txt 
hello world
[root@localhost test]# 

5.EOF与feof函数

程序怎么才能知道已经到结尾了呢?文本文件内容的最后一个char是EOF。

EOF不属于文件的内容,只是文件的结尾标识,而且也不要直接用-1来替代EOF。

只有文本文件才可以通过EOF来判断文件的结尾标示,文本文件的结尾标示是EOF,但二进制文件不是,对于二进制文件EOF是无效的,二进制文件就需要用feof这个函数。feof也可以用在文本文件。

函数原型:

int feof(FILE *stream);

参数就是fopen函数返回的指针。

文件指针所在位置:初始在第一行的开头,即第1个字符前面那。后续每次读取了内容,就在已读取内容的最后一个字符和下一个字符之间。读取内容的最后一个字符是当前行的换行符时,读取后,文件指针在下一行的开头。

feof的原理:EOF在最后一行末尾,在最后一行时,feof(filep)不会为True,读文件的函数不仅会把最后一行的文件内容读到,也会把EOF读到。示例代码理解:

#include <stdio.h>

// 1.用feof
int main01()
{
    char filepath[] = "./test.txt";
    FILE *p = fopen(filepath, "r");

    int count = 0;

    if (p)
    {
        while (!feof(p))
        {
            char c = getc(p);
            // if (c == EOF){break;} // 不读取最后一个字符,即文件结尾符EOF

            // 打印字符和对应的ASCII码
            printf("(%c,%d)=>", c, c);
            count++;
        }
        fclose(p);
    }
    else
    {
        printf("open fail\n");
    }

    printf("count = %d\n", count); // count = 8

    return 0;
}



// 2.用EOF
int main02()
{
    char filepath[] = "./test.txt";
    FILE *p = fopen(filepath, "r");

    int count = 0;

    char c = getc(p);
    if (p)
    {
        while (c != EOF)
        {
            // 打印字符和对应的ASCII码
            printf("(%c,%d)=>", c, c);
            count++;
            c = getc(p);
        }
        fclose(p);
    }
    else
    {
        printf("open fail\n");
    }

    printf("count = %d\n", count); // count = 7
    return 0;
}


int main()
{
    main01();
    main02();

    return 0;
}

运行结果

[root@localhost test]# gcc main.c -o main
[root@localhost test]# cat test.txt
hello world
[root@localhost test]# ./main
(h,104)=>(e,101)=>(l,108)=>(l,108)=>(o,111)=>( ,32)=>(w,119)=>(o,111)=>(r,114)=>(l,108)=>(d,100)=>(
,10)=>(�,-1)=>count = 13
(h,104)=>(e,101)=>(l,108)=>(l,108)=>(o,111)=>( ,32)=>(w,119)=>(o,111)=>(r,114)=>(l,108)=>(d,100)=>(
,10)=>count = 12
[root@localhost test]# 

6.fputs和fgets 按照行读写文件

fputs 将字符串写入文件

函数原型

int fputs(const char *str, FILE *stream);

该函数返回一个非负值,如果发生错误则返回 EOF(-1)。

示例代码:

#include <stdio.h>

int main()
{
    FILE *filep = fopen("./fputs.txt", "w");
    if (filep)
    {
        fputs("hello world\n", filep);
        fputs("xxxx\n", filep);

        char info[10] = {0};
        sprintf(info, "work %d%d%d\n", 9, 9, 6);
        fputs(info, filep);

        fclose(filep);
    }
    else
    {
        perror("open file fail");
    }
        
    return 0;
}

fgets 从键盘输入或者文件输入

函数原型

char *fgets(char *s, int size, FILE *stream);

参数:

  • s: 字符型指针,指向存储读入数据的缓冲区的地址
  • size: 从流中读入 size - 1 个字符,放入s的前size-1个位置,然后将第size个位置处放'\0' 字符。
  • stream: 指向读取的流。如果要从键盘输入,则传入stdin即可。如果要将文件作为输入来源,则传入对应的文件指针即可。

返回值:

  • 如果读入错误或遇到文件结尾(EOF),则返回NULL
  • fgets的返回值是 char *,代表函数读到的字符串的首地址,如果fgets到了文件末尾,继续调 用,返回NULL

fgets读取原理:

  • fgets 执行时会从文件流的当前位置读取 size - 1 个字符,然后在读取到的这些字符后面添加 一个 '\0' 字符并将这些字符放入 s 中,也就是第size位置处放'\0' 字符,作为字符串的结尾。
  • 如果 fgets 在执行时发现文件流的当前位置到换行符或文件末尾之间的这些字符不够 size - 1 个字符,则将不够数的字符统统用 '\0' 代替。
  • 换行符也是当前行的内容
#include <stdio.h>
#include <string.h>

int main1()
{
    FILE *filep = fopen("./fputs.txt", "w");
    if (filep)
    {
        while (1)
        {
            // get data from keyboard
            char buf[1024] = {0};
            fgets(buf, sizeof(buf), stdin);
            if (strncmp(buf, "exit", 4) == 0)
                break;
            
            // write data into file
            fputs(buf, filep);
        }

        fclose(filep);
    }
    
    return 0;
}

int main2()
{
    FILE *filep = fopen("./fputs.txt", "r");
    char buff[10] = {0};
    if (filep)
    {
        // read data line by line from file
        while (fgets(buff, sizeof(buff), filep) != NULL)
        {
            printf("(%s)", buff);
        }
        fclose(filep);
    }

    return 0;
}

int main()
{
    main1();

    main2();

    return 0;
}

运行效果

[root@localhost test]# gcc main.c -o main
[root@localhost test]# ./main
hello world
work for life
exit
(hello wor)(ld
)(work for )(life
)[root@localhost test]# 

用fgets和fputs进行文件拷贝

#include <stdio.h>

void copyfile(char *srcPath, char *tarPath)
{
    FILE *readp = fopen(srcPath, "r");
    if (!readp)
    {
        printf("fopen %s fail\n", srcPath);
        return;
    }

    FILE *writep = fopen(tarPath, "w");
    if (readp && writep)
    {
        while (!feof(readp))
        {
            char buff[1024] = {0};
            if (fgets(buff, sizeof(buff), readp) == NULL)
            {
                break;
            }
            // printf("(%s)\n", buff);
            fputs(buff, writep);
        }

        fclose(readp);
        fclose(writep);
    }

}

int main()
{
    char filepath[] = "./test.txt";
    char writePath[] = "./test_write.txt";
    copyfile(filepath, writePath);

    return 0;
}

7.fprintf和fscanf 按指定格式读写文件

fscanf从文件内容中读取指定的内容

fprintf输出指定格式内容到文件中

int fscanf(FILE *stream, const char *format, [argument...])
int fprintf(FILE *stream, const char *format, [ argument ]...)

fscanf函数返回值:

  • 读文件成功,则返回成功读取的项数
  • 读文件失败,则返回EOF

fprintf()函数返回值

  • 写文件成功,则返回写入的总字符数
  • 写文件失败,则返回负值

解析文件内容并追加结果

cal.txt

12+3=
14*6=
5/7=
32-56=

示例代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int myfunc(int a, char b, int c)
{
    switch (b)
    {
    case '+':
        return a + c;
    case '-':
        return a - c;
    case '*':
        return a * c;
    case '/':
        if (c > 0)
            return a / c;
        else
            return 0;
    default:
        printf("error");
        return 0;
    }
}

int main()
{
    FILE *filep = fopen("./cal.txt", "r");
    FILE *writep = fopen("./cal_f.txt", "w");
    if (filep && writep)
    {
        while (1)
        {
            int a, c;
            char b;
            int ret;
            //读取文件一行
            ret = fscanf(filep, "%d%c%d=", &a, &b, &c);
            printf("\nret=%d\n", ret);
            /*
            当前文件最后一行具有内容时,此时EOF在最后一行末尾
            文件指针在最后一行时,feof(filep)会为真,fgets调用buff也会读取到内容,
            在fgets调用后feof(filep)会为假
            因此判断feof(filep)和处理内容谁前谁后很关键
            先处理内容,再判断feof(filep)是否退出
            */

            // 处理内容
            if (ret == 3)
            {
                printf("%d%c%d=%d\n", a, b, c, myfunc(a, b, c));
                fprintf(writep, "%d%c%d=%d\n", a, b, c, myfunc(a, b, c));
            }

            // 判断文件是否结束
            if (feof(filep))
            {
                break;
            }

        }

        fclose(filep);
        fclose(writep);
    }

    return 0;
}

cal_f.txt

12+3=15
14*6=84
5/7=0
32-56=-24

文件内容特定条件查找

文件:name_age.txt

name=liudehua,age=50
name=anbei,age=30
name=zhangxueyou,age=45
name=canglaoshi,age=70

要求:打印年龄第二大的人的姓名

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define NUM 100

int main()
{
    FILE *filep = fopen("./name_age.txt", "r");

    int maxage = 0;
    int max2age = -1;
    char maxname[100] = {0};
    char max2name[100] = {0};

    if (filep)
    {
        while (1)
        {
            printf("------------------\n");
            //读取文件一行
            char buff[1024] = {0};
            fgets(buff, sizeof(buff), filep);
            /*
            当前文件最后一行具有内容时,此时EOF在最后一行末尾
            文件指针在最后一行时,feof(filep)会为真,fgets调用buff也会读取到内容,
            在fgets调用后feof(filep)会为假
            因此判断feof(filep)和处理内容谁前谁后很关键
            先处理内容,再判断feof(filep)是否退出
            */
            printf("(%s)\n", buff);

            if (strncmp(buff, "name", 4) == 0)
            {
                //用,分割得到姓名
                char *s;
                s = strtok(buff, ",");
                printf("%s\n", s);
                char name[100] = {0};
                sscanf(s, "name=%s", name);
                printf("%s\n", name);

                //用,分割得到年龄
                s = strtok(NULL, ",");
                printf("%s", s);
                int age = 0;
                sscanf(s, "age=%d", &age);
                printf("%d\n", age);

                //更新最大值和姓名
                if (age > maxage)
                {
                    strcpy(max2name, maxname);
                    strcpy(maxname, name);
                    max2age = maxage;
                    maxage = age;
                }
                else if ((max2age < age) && (age < maxage))
                {
                    strcpy(max2name, name);
                    max2age = age;
                }
            }

            if (feof(filep))
            {
                break;
            }
            
        }
        fclose(filep);
    }

    printf("------------------\n");
    printf("%s,%d\n", maxname, maxage);
    printf("%s,%d\n", max2name, max2age);

    return 0;
}

8.stat函数

头文件

#include <sys/stat.h>
#include <sys/types.h>

函数原型

int stat(const char * Filename, struct stat *_Stat)

参数:

  • 第一个参数代表文件名
  • 第二个参数是struct stat结构,传出参数
  • 返回值:执行成功返回0,失败返回-1

函数作用:通过传出参数,得到文件的属性,包括文件建立时间,文件大小,最后访问时间,最后修改时间等信息,比如stat.st_size;得到文件大小,单位字节

结构体struct stat的参数说明

struct stat
{
    dev_t st_dev; //device 文件的设备编号
    ino_t st_ino; //inode 文件的索引节点
    mode_t st_mode; //protection 文件的类型和存取的权限
    nlink_t st_nlink; //number of hard links 连到该文件的硬连接数目,
    //刚建立的文件值为1.
    uid_t st_uid; //user ID of owner 文件所有者的用户识别码
    gid_t st_gid; //group ID of owner 文件所有者的组识别码
    dev_t st_rdev; //device type 若此文件为装置设备文件, 则为其设备编号
    off_t st_size; //total size, in bytes 文件大小, 以字节计算
    unsigned long st_blksize;
    //blocksize for filesystem I/O 文件系统的I/O 缓冲区大小.
    unsigned long st_blocks;
    //number of blocks allocated 占用文件区块的个数,
    //每一区块大小为512 个字节.
    time_t st_atime; //time of lastaccess 文件最近一次被存取或被执行的时间,
    //一般只有在用mknod、utime、read、write 与tructate 时改变.
    time_t st_mtime; //time of last modification 文件最后一次被修改的时间,
    // 一般只有在用mknod、utime 和write 时才会改变
    time_t st_ctime; //time of last change i-node 最近一次被更改的时间,
    //此参数会在文件所有者、组、权限被更改时更新
};

示例代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
//#include <unistd.h>
#include <time.h>
#define NUM 100

int main()
{
    struct stat st = {0};
    int ret = stat("test.txt", &st);
    //调用完stat函数后,就得到了文件的各种属性

    printf("%d\n", ret); // 0
    if (ret == 0)
    {
        //文件大小
        int size = st.st_size;
        printf("%d\n", size); // 28

        struct tm *info;
        char buffer[80];

        //最近一次被执行的时间
        time_t atime = st.st_atime;
        printf("%d\n", atime); // 1668269249
        info = localtime(&atime);
        strftime(buffer, 80, "%Y-%m-%d %H:%M:%S", info);
        printf("%s\n", buffer); // 2022-11-13 00:07:29

        //最后一次被修改的时间
        time_t mtime = st.st_mtime;
        printf("%d\n", mtime); // 1668261399
        info = localtime(&mtime);
        strftime(buffer, 80, "%Y-%m-%d %H:%M:%S", info);
        printf("%s\n", buffer); // 2022-11-12 21:56:39
        
        //最近一次被更改的时间,此参数会在文件所有者、组、权限被更改时更新
        time_t ctime = st.st_ctime;
        printf("%d\n", ctime); // 1668252245
        info = localtime(&mtime);
        strftime(buffer, 80, "%Y-%m-%d %H:%M:%S", info);
        printf("%s\n", buffer); // 2022-11-12 21:56:39
    }
    else
    {
        printf("stat error\n");
    }

    return 0;
}

9.fread和fwrite 读写二进制数据

函数说明

fgets fputs fprintf, fscanf这些函数都是针对文本文件读写的,不能对一个二进制文件进行读写。

除了文本文件之外的文件都是二进制,比如图像,可执行程序,音乐,视频这些都是二进制 的(其实文本文件是特殊的二进制文件,只是编码方式不同而已,对于数值类型,文本文件 按字符编码,二进制文件按值编码)

fprintf等都是往文本文件里面写一个字符串,比如将123456写入文件,实际上把‘1’, ‘2’, '3', '4', '5', '6'这6个字符写入文件。如果要把一个int整数写入文件,这个文件就不是文本文件了。

函数原型

size_t fread(void *buffer, size_t size, size_t count, FILE *stream);
size_t fwrite(void *buffer, size_t size, size_t count, FILE *stream);

参数:

  • 第一个参数是buff的内存地址,表示要写什么
  • 第二个参数是每个单位的大小
  • 第三个参数是写 多少个单位(只需要第二个参数和第三个参数的乘积与 第一个参数指定的内存区域一样大即可)
  • 第四个参数是fopen返回的文件指针。

这个函数以二进制形式对文件进行操作,不局限于文本文件

返回值:返回实际写入的数据块数目

示例代码

#include <stdio.h>

int main1()
{
    FILE *filep = fopen("./test.dat", "w");

    int i = 100;
    fwrite(&i, 1, sizeof(int), filep);
    
    short x = 50;
    fwrite(&x, 1, sizeof(short), filep);

    fclose(filep);

    return (0);
}

int main2()
{
    FILE *filep = fopen("./test.dat", "r");

    int a = 0;
    fread(&a, 1, sizeof(int), filep);
    printf("a=(%d)\n", a);

    short b = 0;
    fread(&b, 1, sizeof(short), filep);
    printf("b=(%d)\n", b);

    
    fclose(filep);
    return (0);
}


int main()
{
    // 1.fwrite
    main1();

    // 2.fread
    main2();

    return 0;
}

fread的返回值

  • fread第二个参数代表了一个单位多大,第三个参数一次要读多少单位
  • fread返回值是成功读取到的单位个数。fread的返回值是,实际读到的内容大小/单位大 小,比如函数读的单位是2个字节,实际读了8个字节的内容,则fread返回4。再比如单位是 4个字节,但只读了2个字节的内容,则返回0
  • 当fread的第二个参数是1时,可以认为fread返回的是读取到的字节数
#include <stdio.h>
int main()
{
    FILE *filep = fopen("./test.dat", "r");
    int a = 0;
    while (1)
    {
        int res = fread(&a, 1, sizeof(int), filep);
        printf("%d\n", res); //4
        if (feof(filep))
        {
            break;
        }
        printf("%d\n", a);
    }
    fclose(filep);
    return (0);
}

实现二进制文件的拷贝

比如图像,可执行程序,音乐,视频这些都是二进制的,都可以用程序拷贝

一个字节一个字节的拷贝

下面代码速度较慢,因为是读一个字节,写一个字节

#include <stdio.h>

int main()
{
    FILE *readp = fopen("./test.txt", "rb");
    if (readp)
    {
        printf("open read");
    }

    FILE *writep = fopen("./test2.txt", "wb");
    if (writep)
    {
        printf("open write");
    }

    while (1)
    {
        char a = 0;
        fread(&a, 1, 1, readp);
        if (feof(readp))
        {
            break;
        }
        fwrite(&a, 1, 1, writep);
    }
    
    fclose(readp);
    fclose(writep);

    return 0;
}

用栈每次拷贝多个字节

读1024个字节,写1024个字节,不够1024时,读多少写多少

#include <stdio.h>

int main()
{
    FILE *readp = fopen("./test.txt", "rb");
    FILE *writep = fopen("./test2.txt", "wb");
    if (writep && readp)
    {
        while (!(feof(writep)))
        {
            char a[1024] = {0};
            int res = fread(&a, 1, sizeof(a), readp);
            fwrite(&a, 1, res, writep); //用res读多少,写多少
        }
    }
    fclose(readp);
    fclose(writep);
    return 0;
}

用堆动态分配内存拷贝

可以根据文件大小,动态分配一个堆内存出来

但是如果这个文件的内存很大一下把内存撑爆了

可以得到文件size后,判断size大小决定是否分成几次来写

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>

#define NUM 1024 * 64 //64 k

int main()
{
    FILE *readp = fopen("./test.txt", "rb");
    FILE *writep = fopen("./test3.txt", "wb");
    if (writep && readp)
    {
        struct stat st = {0};
        stat("test.txt", &st);
        int size = st.st_size;
        if (size >= NUM)
        {
            size = NUM;
        }

        char *buff = malloc(size);

        while (!(feof(readp)))
        {
            //char buff[1024] = {0};
            int res = fread(buff, 1, size, readp);
            fwrite(buff, 1, res, writep);
        }

        free(buff);
        fclose(readp);
        fclose(writep);
        printf("success");
    }
    
    return 0;
}

读写结构体数据

将结构体数据写入文件中,读取时直接就拿到这个结构体,方便。

把一个结构变量写入文件的时候,结构变量成员的对齐内存浪费部分同样也会写入文件。

#include <stdio.h>
#include <stdlib.h>

struct man
{
    char name[20];
    int age;
};

int main()
{
    //将结构体等数据写入dat文件
    char filename[] = "xxx.dat";
    FILE *writep = fopen(filename, "wb");

    struct man m = {"tom", 12};
    fwrite(&m, 1, sizeof(struct man), writep);

    int x = 100;
    fwrite(&x, 1, sizeof(x), writep);

    fclose(writep);

    //从dat中读取数据
    FILE *readp = fopen(filename, "rb");

    struct man newm;
    fread(&newm, 1, sizeof(newm), readp);
    printf("%s, %d\n", newm.name, newm.age); // tom, 12

    int j = 0;
    fread(&j, 1, sizeof(int), readp); // j = 100
    printf("j = %d\n", j);

    fclose(readp);

    //读到堆中
    readp = fopen(filename, "rb");
    struct man *datap = malloc(sizeof(struct man));
    fread(datap, 1, sizeof(struct man), readp);
    printf("%s, %d\n", datap->name, datap->age); // tom, 12

    free(datap);

    int *intp = malloc(sizeof(int));
    fread(intp, 1, sizeof(intp), readp);
    printf("%d\n", *intp); // 100
    
    free(intp);
    fclose(readp);

    return 0;
}

10.fseek函数

FILE指针原理

  • FILE结构内部是有一个指针的,每次调用文件读写函数,这些函数就会自动移动这个指针 默认情况下指针只能从前往后移动。
  • c语言文件读写库函数都是自动维护FILE里面的相关成员,包括文件读写当前位置。 每次调用fgets,或者fread,下次再调用的时候,就会自动从已读取内容后面开始。
  • feof为什么能知道是否到了文件结尾了呢?fread或者fgets这些函数如果读完文件所有内容,他们会设置FILE里面相关变量的值。
  • feof只是判断FILE结构里面相关变量的值是否为文件已经结尾状态。
  • fopen成功打开一个文件后,文件指针默认都是在0 SEEK_SET这个位置。

fseek函数使用与技巧

事实上这个指针位置我们可以自己来调,需要用fseek这个函数。

int feek(FILE *_File, long _Offset, int _Origin);
  • 第一个参数是fopen返回的文件指针
  • 第二个参数是偏移量。正数表示向后偏移,负数表示向前偏移。
  • 第三个参数是设置从哪里开始偏 移,可能取值为:SEEK_CUR,SEEK_END或者SEEK_SET。
SEEK_SET: 文件开头
SEEK_CUR:文件当前位置
SEEK_END:文件结尾

函数作用:设置文件的指针stream的位置。如果执行成功,stream将指向以fromwhere为基准,偏移offset个字节的位置,函数返回0。如果执行失败则不改变stream指向的位置,函数返 回一个非0值。

一些小技巧

  • fseek(readp, 0, SEEK_SET); 回到文件开始位置
  • fseek(readp, 0, SEEK_END); 回到文件结尾位置

注意事项

  • 实验得出,超出文件末尾位置,还是返回0,往回偏移超出首位置,还是返回0,请小心使 用。
  • 并且超出文件末尾或者首位置,读到的数据都是0

示例代码理解

#include <stdio.h>
#include <stdlib.h>

int main()
{
    FILE *writep = fopen("a.dat", "w");
    char a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    fwrite(a, 1, sizeof(a), writep);
    fclose(writep);

    FILE *readp = fopen("a.dat", "r");
    fseek(readp, 2, SEEK_SET);
    // while (!feof(readp))
    for (int i = 0; i < 2; i++)
    {
        char a[2];
        fread(a, 1, sizeof(a), readp);
        printf("%d, %d\n", a[0], a[1]);
    }
    fclose(readp);

    /*
    3, 4
    5, 6
    */

    return 0;
}

用fseek快速生成超大文件

快速生成一个超大文件,因为需要经常测试代码的文件读写情况。

原始的慢方法

#include <stdio.h>
#include <stdlib.h>

int main()
{
    FILE *writep = fopen("a.dat", "w");
    for (int i = 0; i < 10000000; i++)
    {
        char a = 0;
        fwrite(&a, 1, sizeof(a), writep);
    }
    fclose(writep);
    return 0;
}

用fseek技巧快速生成(超大空文件)

#include <stdio.h>
#include <stdlib.h>

int main()
{
    FILE *writep = fopen("a.dat", "w");
    fseek(writep, 1000000, SEEK_SET);
    char a = 0;
    fwrite(&a, 1, sizeof(a), writep);
    fclose(writep);
    return 0;
}

11.ftell函数

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

long loc = ftell(fp);

以下代码通过ftell函数和feof函数,可以得出:

  • 文件的EOF在最后一行末尾,无论最后一行是"文件内容+EOF",还是只有"EOF", feof(readp)都为假
  • fread读最后一块内容时:
    • 如果是"文件内容+EOF",则会去掉EOF
    • 如果是只有"EOF",则读不到任何数据,此时用fread函数不会修改传入地址的值

示例代码

#include <stdio.h>
#include <stdlib.h>

int main()
{
    FILE *writep = fopen("a.dat", "w");
    char a[3] = {1, 2, 3};
    fwrite(a, 1, sizeof(a), writep);
    fclose(writep);

    printf("--------------\n");
    FILE *readp = fopen("a.dat", "r");
    //fseek(readp, 0, SEEK_SET);
    long loc = ftell(readp);
    printf("loc = %lu\n", loc); //loc = 0

    printf("--------------\n");
    char b;
    while (!feof(readp))
    {
        fread(&b, 1, 1, readp);
        printf("%d\n",b);
        long loc = ftell(readp);
        printf("loc = %lu\n", loc);
    }

    printf("--------------\n");
    fseek(readp, 0, SEEK_END);
    loc = ftell(readp);
    printf("loc = %lu\n", loc);
    char x = 0;
    fread(&x, 1, 1, readp);
    printf("x = %d\n",x);

    printf("--------------\n");
    fseek(readp, -1, SEEK_END);
    loc = ftell(readp);
    printf("loc = %lu\n", loc);
    char y = 0;
    fread(&y, 1, 1, readp);
    printf("y = %d\n", y);

    fclose(readp);

    return 0;
}

运行结果

--------------
loc = 0
--------------
1
loc = 1
2
loc = 2
3
loc = 3
3
loc = 3
--------------
loc = 3
x = 0
--------------
loc = 2
y = 3

12.fflush函数和文件读写缓冲区

c语言所有的文件操作函数都是缓冲区函数

以下代码只有在fclose(writep);后文件a.txt中才会有内容,说明是缓冲区库函数

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    FILE *writep = fopen("a.txt", "w");
    while (1)
    {
        char a[100] = {0};
        scanf("%s", a);
        if (strcmp(a, "exit") == 0)
        {
            break;
        }
        fprintf(writep, "%s\n", a);
    }
    fclose(writep);
    return 0;
}

用ffush函数跳过内存直接写入磁盘

int fflush(FILE *_File)

由于fflush是实时的将缓冲区的内容写入磁盘,所以不要大量去使用,因为fflush相当于是直接 用磁盘读写而不是通过内存再到磁盘,所以速度慢,而且频繁读写磁盘会降低磁盘寿命,但如果 是重要的数据,可以用fflush写入磁盘。

13.remove 删除文件

删除指定文件

int remove(const char *Filename);

没有该文件时不会报错

#include <stdio.h>

int main()
{
    char filename[] = "xxx.txt";
    FILE *writep = fopen(filename, "w");
    fclose(writep);
    remove(filename);
    return 0;
}

14.rename 文件改名或者剪切

int rename(const char *OldFilename, const char *NewFilename);

示例代码

#include <stdio.h>
int main()
{
    char filename[] = "xxx.txt";
    FILE *writep = fopen(filename, "w");
    fclose(writep);
    char newname[] = "../yyy.txt";
    rename(filename, newname);
    return 0;
}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1610593.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《黑羊效应》一群好人欺负一个好人,其他好人却坐视不管的诡谲现象 - 三余书屋 3ysw.net

黑羊效应&#xff1a;一群好人欺负一个好人&#xff0c;其他好人却坐视不管的诡谲现象 大家好&#xff0c;今天我们要解读的书是《黑羊效应》。黑羊效应是一种心理陷阱&#xff0c;指的是一群好人欺负一个好人&#xff0c;而其他好人却坐视不理。我们每个人或多或少都目睹过或…

理解JMM

JMM 对volatile的理解 volatile 是java虚拟机提供轻量级的同步机制 1、保证可见性 2、不保证原子性 3、禁止指令重排 那么可见性与JMM相关 什么是JMM Java内存模型&#xff0c;不存在的东西&#xff0c;是一个概念&#xff0c;是一个约定 线程加锁前&#xff0c;必须读取…

存储过程的使用(二)

目录 带 OUT 参数的存储过程 输入一个编号&#xff0c;查询数据表 emp中是否有这个编号&#xff0c;如果有返回对应员工姓名&#xff0c;如果没有&#xff0c;则提示没有对应员工 使用 EXEC 命令或者 PRINT执行含有 OUT参数的存储过程 使用 PL/SQL 块编辑程序调用含有 OUT …

centos修改启动项加载不同内核

一.背景&#xff1a; 虚拟机中有时需要编译好几个内核版本&#xff0c;make install后系统存在几个内核版本。需要再哪个内核上开发调试就启动特定的内核版本。这就需要修改启动时的内核版本&#xff0c;再物理机或虚拟机启动时可以上下键选择。但有时是docket云环境中或远程时…

葡萄书--图注意力网络

同质图中的注意力网络 注意力网络 GAT 核心就是对于每个顶点都计算其与邻居节点的注意力系数&#xff0c;通过注意力系数来聚合节点的特征&#xff0c;而非认为每个邻居节点的贡献程度都是相同的 单头注意力机制 为了计算注意力权重 eij​&#xff0c;我们首先将即节点特征…

移动Web学习09-响应式布局bootstrap案例开发

3、综合案例-AlloyTeam移动全端 准备工作 HTML 结构 <title>腾讯全端</title> <link rel"shortcut icon" href"favicon.ico" type"image/x-icon"> <!-- 层叠性&#xff1a;咱们的css 要 层叠 框架的 --> <link rel&…

JAVA 项目<果园之窗>_2

上节主要是理论流程&#xff0c;这次直接用实际例子过一遍整个流程 目标是向数据库添加一个员工 上述是前端页面&#xff0c;点击保存 浏览器向我后端发送http请求 后端这一部分专门接收employee请求 在这里对http post请求进行转换成JAVA数据&#xff0c;并处理数据&#xff…

安装zlmediakit和wvp-pro

通过docker安装zlmediakit&#xff0c;并单独启动wvp-pro.jar - zlmediakit安装 zlmediakit安装比较依赖环境和系统配置&#xff0c;所以这里直接使用docker的方式来安装。 docke pull拉取镜像 docker pull zlmediakit/zlmediakit:master使用下边命令先运行起来 sudo docke…

Linux 下安装MySQL 5.7与 8.0详情

官网资源下载 1、检查 /tmp 临时目录权限&#xff0c;将 /tmp 目录及所有子目录和文件的权限设置为所有用户可读、写和执行 [rootlocalhost ~]# chmod -R 777 /tmp2、安装前检查相关依赖 2.1、查找是否安装了 libaio 包。libaio 是 Linux 下异步 I/O 库的一个实现&#xff0…

华为ensp中rip和ospf路由重分发 原理及配置命令

作者主页&#xff1a;点击&#xff01; ENSP专栏&#xff1a;点击&#xff01; 创作时间&#xff1a;2024年4月20日20点21分 路由重分发&#xff08;Route Redistribution&#xff09;是指路由器将从一种路由协议学习到的路由信息&#xff0c;通过另一种路由协议通告出去的功…

汇舟问卷:国外问卷调查做题完整步骤细节展示

大家好&#xff0c;我是汇舟问卷。想要做国外问卷调查&#xff0c;搭建国外的环境是必不可少的&#xff0c;今天给大家讲解一下搭建国外环境的完整步骤&#xff0c;只要按照步骤一步步操作就一定能把环境搭建出来​。 一、安装辅助软件 需要先下载对应的软件进行安装&#xf…

项目七:学会使用python爬虫解析库(小白大成级)

前期我们学会了怎么使用python爬虫请求库和解析库的简单应用和了解&#xff0c;同时能够对爬虫有一个较为清晰的体系&#xff0c;毕竟简单的爬虫基本上都是请求数据——解析数据——存储数据的大概流程。 那么回忆一下&#xff0c;请求库我们学的是requests模块&#xff0c;解…

【数据结构练习题】二叉树(1)——1.相同的树2.另一颗树的子树3.翻转二叉树4.平衡二叉树5.对称二叉树

♥♥♥♥♥个人主页♥♥♥♥♥ ♥♥♥♥♥数据结构练习题总结专栏♥♥♥♥♥ ♥♥♥♥♥上一章&#xff1a;队——1.用队实现栈2.用栈实现队♥♥♥♥♥ 文章目录 1.相同的树1.1题目描述1.2 思路分析1.3绘图分析1.4代码实现2.另一颗树的子树2.1问题描述2.2思路分析2.3绘图分析2.…

视觉SLAM学习打卡【11】-尾述

到目前为止&#xff0c;视觉SLAM14讲已经到了终章&#xff0c;历时一个半月&#xff0c;时间有限&#xff0c;有些地方挖掘的不够深入&#xff0c;只能在后续的学习中更进一步。接下来&#xff0c;会着手ORB-SLAM2的开源框架&#xff0c;同步学习C。 视觉SLAM学习打卡【11】-尾…

【linux】多路径|Multipath I/O 技术

目录 简略 详细 什么是多路径? Multipath安装与使用 安装 使用 Linux下multipath软件介绍 附录 配置文件说明 其他解 简略 略 详细 什么是多路径? 普通的电脑主机都是一个硬盘挂接到一个总线上&#xff0c;这里是一对一的关系。 而到了分布式环境&#xff0c;主机和存储网络连…

Linux使用Libevent库实现一个网页服务器---C语言程序

Web服务器 这一个库的实现 其他的知识都是这一个专栏里面的文章 实际使用 编译的时候需要有一个libevent库 gcc httpserv.c -o httpserv -levent实际使用的时候需要指定端口以及共享的目录 ./httpserv 80 .这一个函数会吧这一个文件夹下面的所有文件共享出去 实际的效果, 这…

Matlab之空间坐标系绘制平面图形

在空间直角坐标系中&#xff0c;绘制指定平面方程的图形 版本说明&#xff1a; 20240413_V1.01&#xff1a;更正代码错误&#xff0c;并修改输入参数类型&#xff08;测试用例得修改&#xff09; 20240413_V1.00&#xff1a;初始版本 一、平面方程 基本形式为&#xff1a;A…

[阅读笔记29][AgentStudio]A Toolkit for Building General Virtual Agents

这篇论文是24年3月提交的&#xff0c;提出了一个用于agent开发的全流程工具包。 作者提到目前agent开发主要有两个阻碍&#xff0c;一个是缺乏软件基础&#xff0c;另一个是缺乏在真实世界场景中进行评估。针对这两个阻碍&#xff0c;作者涉及了一个开发工具包&#xff0c;包括…

中颖51芯片学习8. ADC模数转换

中颖51芯片学习8. ADC模数转换 一、ADC工作原理简介1. 概念2. ADC实现方式3. 基准电压 二、中颖芯片ADC功能介绍1. 中颖芯片ADC特性2. ADC触发源&#xff08;1&#xff09;**软件触发**&#xff08;2&#xff09;**TIMER4定时器触发**&#xff08;3&#xff09;**外部中断2触发…

2024第八届图像、信号处理和通信国际会议 (ICISPC 2024)即将召开!

2024第八届图像、信号处理和通信国际会议 &#xff08;ICISPC 2024&#xff09;将于2024年7月19-21日在日本福冈举行。启迪思维&#xff0c;引领未来&#xff0c;ICISPC 2024的召开&#xff0c;旨在全球专家学者共襄盛举&#xff0c;聚焦图像信号&#xff0c;在图像中寻找美&am…