• I/O


    学习笔记(一)之I/O

    输入:数据从内核空间-->用户空间 scanf
    输出:数组从用户空间-->内核空间 printf

    linux中文件类型:b:块设备文件,c:字符设备文件,d:目录文件,-:普通文件,l:链接文件,s:套接字文件,p:管道文件

    标准IO 利用文件流指针对文件操作
    1.C库调用(属于用户空间) man 3
    2.移植性强 高级IO
    3.自带缓存
    行缓存 标准输出 stdout
    1k 1024byte
    刷新条件:1.'\n' 2.满了 3.程序正常退出 4.fflush
    fflush
    int fflush(FILE *stream);

     1 #include <stdio.h>
     2 
     3 
     4 
     5 int main(int argc, const char *argv[])
     6 {
     7     printf("hello world");
     8     fflush(NULL);
     9     while(1)
    10     {
    11         ;
    12     }
    13     return 0;
    14 }
    fllush


    功能:按照参数刷新指定流,填NULL时刷新所有打开的输出流
    返回值:成功返回0,失败返回EOF -1 并设置errno号

    全缓存 标准输入 stdin
    4k 4*1024byte
    刷新条件:1.满了 2.程序正常退出 3.fflush 4.关闭流

    无缓存 标准错误 stderr

    流指针:
    FILE * == struct _IO_FILE *
    typedef struct _IO_FILE FILE;

    对文件操作:
    1.打开文件:fopen
    FILE *fopen(const char *path, const char *mode);
    参数:1.文件所在路径(字符串形式) 2.对文件的访问权限(字符串形式)
    mode:
    r:只读打开文件,文件指针指向文件开头,若文件不存在,报错
    r+:读写打开文件,文件指针指向文件开头,若文件不存在,报错
    w:只写打开文件,文件存在,清空文件,文件不存在,创建该文件,文件指针指向文件开头
    w+:读写打开文件,文件存在,清空文件,文件不存在,创建该文件,文件指针指向文件开头
    a:如果文件不存在,创建该文件,文件存在,再文件末尾追加 (文件指针指向文件末尾)
    a+:读和追加模式,如果文件不存在,创建该文件,文件存在,在文件末尾追加 (指针指向文件末尾) 读操作时,从文件开头读

    返回值:成功返回该文件的文件流指针,失败返回NULL,并设置errno
    errno:指定的一些错误 使用时加头文件:#include <errno.h>
    strerror:将errno号对应的错误信息转换成字符串
    char *strerror(int errnum);

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <errno.h>
     4 
     5 
     6 int main(int argc, const char *argv[])
     7 {   
     8     //打开文件
     9     FILE *fp = NULL;
    10     fp = fopen("./444.txt","a+");
    11     if(fp == NULL)
    12     {
    13         fprintf(stderr,"fail to fopen:%s\n",strerror(errno));    
    14         return -1;
    15     }
    16 
    17     //关闭文件
    18     fclose(fp);
    19 
    20     return 0;
    21 }
    strerror

    fprintf
    int fprintf(FILE *stream, const char *format, ...);
    功能:将信息打印到指定的流上
    参数:1.指定流 2.格式控制串 3.输出表
    注:fprintf(stdout,....) == printf(....)

    容错函数:perror
    void perror(const char *s);
    参数:自己书写的报错信息

     1 #include <stdio.h>
     2 #include <string.h>
     3 
     4 
     5 int main(int argc, const char *argv[])
     6 {   
     7     //打开文件
     8     FILE *fp = NULL;
     9     fp = fopen("./111.txt","r");
    10     if(fp == NULL)
    11     {
    12         perror("fail to fopen");
    13         return -1;
    14     }
    15 
    16     //关闭文件
    17     fclose(fp);
    18 
    19     return 0;
    20 }
    perror

    关闭文件:fclose
    int fclose(FILE *fp);
    功能:关闭指定文件

    字符输入输出:
    fgetc:从指定流中获取单个字符
    int fgetc(FILE *stream);
    返回值:成功返回获取到字符的ascii码,失败返回EOF 注:1.error 2.文件末尾判断:feof
    fgetc(stdin) == getchar()

     1 #include <stdio.h>
     2 
     3 
     4 
     5 int main(int argc, const char *argv[])
     6 {
     7     int ret;
     8     ret = fgetc(stdin);
     9     printf("%c\n",ret);
    10     return 0;
    11 }
    fgetc

    int feof(FILE *stream);

    功能:判断是否到达文件末尾
    返回值:到达文件末尾返回非0值

    fputc:将单个字符输出到指定的流中
    int fputc(int c, FILE *stream);
    参数:1.字符的ascii码 2.指定的流
    返回值:成功返回输出字符的ascii码,失败返回EOF
    fputc(..,stdout) == putchar(..)

     1 #include <stdio.h>
     2 
     3 
     4 
     5 int main(int argc, const char *argv[])
     6 {
     7 
     8     if(argc != 2)
     9     {
    10         fprintf(stderr,"fail to input filename\n");
    11         return -1;
    12     }
    13 
    14     FILE * fp = NULL;
    15     int ret = 0;
    16 
    17     fp = fopen(argv[1],"r");
    18     if(fp == NULL)
    19     {
    20         perror("fail to fopen");
    21         return -1;
    22     }
    23 
    24     while(1)
    25     {
    26         ret = fgetc(fp);
    27         if(ret == -1)
    28         {
    29             if(feof(fp))  //判断是否到达文件末尾
    30             {
    31                 break;
    32             }
    33             else
    34             {
    35                 fprintf(stderr,"fail to fgetc\n");
    36                 return -1;
    37             }
    38         }
    39         
    40         fputc(ret,stdout);
    41 
    42     }
    43 
    44     fclose(fp);    
    45     return 0;
    46 }
    mycat_fgetc

    按行输入输出
    fgets
    char *fgets(char *s, int size, FILE *stream);
    参数:1.应用层buf(用于存放fgets获取的一行数据) 2.安全枷锁(sizeof(buf)) 3.指定流
    功能:从指定流中读取一行数据,并在末尾自动加上'\0',并且会将'\n'作为字符读入
    返回值:成功返回获取字符串的首地址,失败返回NULL 注:1.error 2.判断文件末尾 feof
    例如:
    char a[10]
    fgets(a,10,stdin); 除了'\0'做多只能存放9个字符
    注:
    1.fgets(a,sizeof(a),stdin); == gets(a);
    2.fgets不能对图片操作,会损坏图片

    gets :该函数可以淘汰了,没有安全性的检查,很容易造成数组越界导致段错误
    char *gets(char *s);

    fputs
    int fputs(const char *s, FILE *stream);
    参数:1.需要输出的内容 2.指定流
    功能:将字符串输出到指定的流上,fputs末尾不会自动加'\n'
    fputs(s,stdout); == puts(s);

     1 #include <stdio.h>
     2 
     3 
     4 
     5 int main(int argc, const char *argv[])
     6 {
     7     char array[10];
     8     fgets(array,sizeof(array),stdin);
     9 //    gets(array);
    10     fputs(array,stdout);
    11     return 0;
    12 }
    fgets

    清空函数:
    #include <strings.h>
    bzero
    void bzero(void *s, size_t n); size_t == unsigned int
    参数:1.需要被操作的空间的首地址 2.空间大小
    功能:根据首地址将该空间清空

    #include <string.h>
    memset
    void *memset(void *s, int c, size_t n);
    参数:1.需要被操作的空间的首地址 2.想要变成的数值(例如'\0' 'a') 3.空间大小
    功能:根据首地址将空间内的内容变成指定的内容int c
    memset(a,0,sizeof(a)) == bzero(a,szieof(a))

    #include <stdio.h>
    #include <strings.h>
    
    
    int main(int argc, const char *argv[])
    {
    
        if(argc != 2)
        {
            fprintf(stderr,"fail to input filename\n");
            return -1;
        }
    
        FILE * fp = NULL;
        char a[10];
    
        fp = fopen(argv[1],"r");
        if(fp == NULL)
        {
            perror("fail to fopen");
            return -1;
        }
    
        while(1)
        {
            bzero(a,sizeof(a));
            //memset(a,0,sizeof(a));
                
            if(NULL == fgets(a,sizeof(a),fp))
            {
                if(feof(fp))
                {
                    break;
                }
                else
                {
                    fprintf(stderr,"fail to fgets!\n");
                    return -1;
                }            
            }
            fputs(a,stdout);
        }
    
        fclose(fp);    
        return 0;
    }
    mycat_fgets

    按块输入输出

    fread

    size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
    参数:1.应用层准备的buf(用于保存即将读取的数据) 2.单个块的大小
    3.最多一次能搬运的块数sizeof(ptr)/sizeof(size) 4.指定流
    返回值:成功返回读取的块数的个数 失败返回0 注:1.error 2.到达文件末尾feof

    fwrite
    size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
    参数:1.buf 2.单个块的大小 3.最多一次书写的块数(看fread的脸色,参照fread的返回值)(读多少写多少)
    4.指定流

     1 #include <stdio.h>
     2 #include <strings.h>
     3 
     4 
     5 int main(int argc, const char *argv[])
     6 {
     7 
     8     if(argc != 2)
     9     {
    10         fprintf(stderr,"fail to input filename\n");
    11         return -1;
    12     }
    13 
    14     FILE * fp = NULL;
    15     int ret;
    16     char buf[10];
    17 
    18 
    19 
    20     fp = fopen(argv[1],"r");
    21     if(fp == NULL)
    22     {
    23         perror("fail to fopen");
    24         return -1;
    25     }
    26 
    27     while(1)
    28     {
    29         bzero(buf,sizeof(buf));
    30         ret = fread(buf,sizeof(char),sizeof(buf)/sizeof(char),fp);
    31         if(ret < 0)
    32         {
    33             fprintf(stderr,"fail to fread!\n");
    34             return -1;
    35         }
    36         else if(ret == 0)
    37         {
    38             break;
    39         }
    40         else
    41         {
    42             fwrite(buf,sizeof(char),ret,stdout);//读多少写多少
    43         }
    44     }
    45 
    46     fclose(fp);    
    47     return 0;
    48 }
    mycat_fread

    fseek:文件指针偏移
    int fseek(FILE *stream, long offset, int whence);
    参数:1.文件流指针 2.偏移量 +向后偏移 -向前偏移
    3.相对位置 SEEK_SET 文件开头 SEEK_CUR 当前位置 SEEK_END 文件末尾
    返回值:成功返回0,失败返回-1,并设置errno号
    注:文件开头不能像前偏移,文件末尾也最好不要向后偏移(文件空洞)

    ftell:告诉当前文件指针距离文件开头的偏移量
    long ftell(FILE *stream);

    rewind:将文件指针回归文件开头
    void rewind(FILE *stream);

     1 #include <stdio.h>
     2 
     3 
     4 
     5 int main(int argc, const char *argv[])
     6 {
     7     FILE *fp;
     8     int ret;
     9     fp = fopen("./log.txt","r+");
    10     if(fp == NULL)
    11     {
    12         perror("fail to fopen");
    13         return -1;
    14     }
    15 
    16     fseek(fp,10,SEEK_SET);
    17     ret = ftell(fp);
    18     printf("%d\n",ret);
    19 
    20     rewind(fp);
    21     printf("%ld\n",ftell(fp));
    22 
    23     return 0;
    24 }
    fseek

    文件IO 利用文件描述符对文件操作
    1.系统调用 man 2 注:系统调用:内核提供的函数接口
    2.移植性差 低级IO
    3.无缓存(内核缓存)

    文件描述符:本质是一个整型数值 (其实是数组下标,是索引)
    1.在当前操作系统中,一个程序打开的文件描述符取值范围0~1023 共1024
    2.默认打开的三个文件描述符: 0 stdin , 1 stdout , 2 stderr
    3.每当打开新的文件时,分配的文件描述符总是最小且未使用的文件描述符

    打开文件:open
    int open(const char *pathname, int flags); 直接访问文件时使用
    int open(const char *pathname, int flags, mode_t mode); 创建文件时使用
    参数:1.文件路径(字符串形式) 2.旗帜
    3.创建权限mode (在使用O_CREAT时才会使用) 直接书写想要的权限例如 0666 0777
    注:最终真实得到的文件权限 mode & ~umask 当前目录下输入umask就能看到文件权限掩码

    flag: 想要的功能通过 '|' 的方式组合
    访问旗:O_RDONLY只读 O_WRONLY只写 O_RDWR读写 flag必须包含有且一个访问旗
    创建旗:O_CREAT创建 O_EXCL测试是否文件存在(通常情况下与O_CREAT连用) O_TRUNC 清空
    状态旗:后期学习

    返回值:成功返回文件描述符,失败返回-1,并设置errno号

    例子:
    r:O_RDONLY | O_EXCL
    w:O_WRONLY | O_CREAT | O_TRUNC
    a:O_WRONLY | O_APPEND | O_CREAT

    关闭文件:close
    int close(int fd); 

     1 #include <stdio.h>
     2 #include <sys/types.h>
     3 #include <sys/stat.h>
     4 #include <fcntl.h>
     5 #include <unistd.h>
     6 
     7 
     8 
     9 int main(int argc, const char *argv[])
    10 {
    11 #if 0
    12     //直接访问形式的open样例
    13     int fd;
    14     fd = open("./log.txt",O_RDONLY);    
    15     if(fd == -1)
    16     {
    17         perror("fail to open");
    18         return -1;
    19     }
    20 
    21 
    22 #endif
    23     //创建时open样例
    24     int fd;
    25     int flag = O_WRONLY | O_CREAT | O_EXCL; 
    26     fd = open("./1.txt",flag,0666);
    27     if(fd == -1)
    28     {
    29         perror("fail to open");
    30         return -1;
    31     }
    32 
    33 
    34 
    35     close(fd);
    36     return 0;
    37 }
    open

    输入输出函数:
    read
    ssize_t read(int fd, void *buf, size_t count);
    参数:1.文件描述符 2.应用层准备的buf(用于接收数据) 3.buf的大小,一次最多读取的数据大小限制
    返回值:成功时返回真实读取字节的个数 返回0时表示数据读取完毕,到达文件末尾
    返回-1时代表错误,并设置errno号

    write
    ssize_t write(int fd, const void *buf, size_t count);
    参数:1.文件描述符 2.应用层准备的buf(用于输出的数据)
    3.和read连用时,该参数需要参照read的返回值,读多少写多少
    返回值:-1表示出错,并设置errno号

     1 #include <stdio.h>
     2 #include <sys/types.h>
     3 #include <sys/stat.h>
     4 #include <fcntl.h>
     5 #include <unistd.h>
     6 #include <strings.h>
     7 
     8 
     9 int main(int argc, const char *argv[])
    10 {
    11     int fd1,fd2;
    12     char buf[20];
    13     int ret_read;
    14     fd1 = open("./log.txt",O_RDONLY);
    15     if(fd1 == -1)
    16     {
    17         perror("fail to open1");
    18         return -1;
    19     }
    20 
    21     fd2 = open("./2.txt",O_WRONLY | O_CREAT | O_EXCL,0666);
    22     if(fd2 == -1)
    23     {
    24         perror("fail to open2");
    25         return -1;
    26     }
    27 
    28 
    29 
    30     while(1)
    31     {
    32         bzero(buf,sizeof(buf));
    33         ret_read = read(fd1,buf,sizeof(buf));
    34         if(ret_read < 0)
    35         {
    36             perror("fail to read");
    37             return -1;
    38         }
    39         else if(ret_read == 0)
    40         {
    41             break;
    42         }
    43         else
    44         {
    45             write(fd2,buf,ret_read);  //读多少写多少
    46         }
    47     }
    48 
    49     close(fd1);
    50     close(fd2);
    51     return 0;
    52 }
    mycp_read
     1 #include <stdio.h>
     2 #include <sys/types.h>
     3 #include <sys/stat.h>
     4 #include <fcntl.h>
     5 #include <unistd.h>
     6 #include <strings.h>
     7 
     8 
     9 int main(int argc, const char *argv[])
    10 {
    11     int fd;
    12     char buf[20];
    13     int ret_read;
    14     fd = open("./log.txt",O_RDONLY);
    15     if(fd == -1)
    16     {
    17         perror("fail to open");
    18         return -1;
    19     }
    20 
    21     while(1)
    22     {
    23         bzero(buf,sizeof(buf));
    24         ret_read = read(fd,buf,sizeof(buf));
    25         if(ret_read < 0)
    26         {
    27             perror("fail to read");
    28             return -1;
    29         }
    30         else if(ret_read == 0)
    31         {
    32             break;
    33         }
    34         else
    35         {
    36             write(1,buf,ret_read);  //读多少写多少
    37         }
    38     }
    39 
    40     close(fd);
    41     return 0;
    42 }
    mycat_read

    lseek:文件偏移
    off_t lseek(int fd, off_t offset, int whence);
    参数:1.文件描述符 2.偏移量 +向后偏移 -向前偏移 3.相对位置 SEEK_SET SEEK_CUR SEEK_END
    功能:参照相对位置偏移大小
    返回值:成功返回距离文件开头相差的字节数 失败返回-1并设置errno号

     1 #include <stdio.h>
     2 #include <sys/types.h>
     3 #include <sys/stat.h>
     4 #include <fcntl.h>
     5 #include <unistd.h>
     6 
     7 
     8 
     9 int main(int argc, const char *argv[])
    10 {
    11     int fd;
    12     off_t ret;
    13     fd = open("./log.txt",O_RDONLY);
    14     if(fd == -1)
    15     {
    16         perror("fail to open");
    17         return -1;
    18     }
    19 
    20     ret = lseek(fd,10,SEEK_SET);
    21     
    22     printf("%d\n",(int)ret);
    23 
    24 
    25     close(fd);
    26     return 0;
    27 }
    lseek

    练习:
    time

    localtime

     1 #include <stdio.h>
     2 #include <time.h>
     3 #include <unistd.h>
     4 
     5 
     6 int main(int argc, const char *argv[])
     7 {
     8     time_t t;
     9     struct tm *p = NULL;
    10     char * week[] = {"星期日","星期一","星期二","星期三","星期四","星期五","星期六"};
    11     FILE * fp = NULL;
    12 
    13     fp = fopen("./log.txt","a");
    14     if(fp == NULL)
    15     {
    16         perror("fail to fopen");
    17         return -1;
    18     }
    19 
    20     while(1)
    21     {
    22         t = time(NULL);
    23         p = localtime(&t);
    24         fprintf(fp,"%d-%d-%d %d-%d-%d %s\n"
    25                 ,p->tm_year+1900,p->tm_mon+1,p->tm_mday,p->tm_hour,p->tm_min,p->tm_sec,week[p->tm_wday]);
    26         fflush(fp);
    27         sleep(1);
    28     }
    29 
    30 
    31 
    32     fclose(fp);
    33     return 0;
    34 }
    localtime

    ctime

     1 #include <stdio.h>
     2 #include <unistd.h>
     3 #include <time.h>
     4 
     5 
     6 
     7 int main(int argc, const char *argv[])
     8 {
     9     time_t t;
    10     while(1)
    11     {
    12         t = time(NULL);
    13         printf("%s\n",ctime(&t));
    14         sleep(1);
    15     }
    16     return 0;
    17 }
    ctime

    扩展:
    opendir man 3
    DIR *opendir(const char *name);
    功能:打开目录文件
    参数:目录路径
    返回值:成功返回目录流指针,失败返回NULL,1并设置errno号

    closedir
    int closedir(DIR *dirp);
    功能:关闭指定目录

    readdir
    struct dirent *readdir(DIR *dirp);
    参数:目录流指针
    功能:读取目录中的文件信息
    返回值:成功返回记录该目录下文件信息的结构体指针struct dirent* 失败返回NULL,如果errno为0则代表读取到目录末尾如果不为0则error,并设置errno号
    struct dirent {
    ino_t d_ino; /* inode number */
    off_t d_off; /* offset to the next dirent */
    unsigned short d_reclen; /* length of this record */
    unsigned char d_type; /* type of file; not supported
    by all file system types */
    char d_name[256]; /* filename */
    };

     1 #include <stdio.h>
     2 #include <sys/types.h>
     3 #include <dirent.h>
     4 #include <errno.h>
     5 
     6 int main(int argc, const char *argv[])
     7 {
     8     if(argc != 2)
     9     {
    10         fprintf(stderr,"please input dirname!\n");
    11         return -1;
    12     }
    13 
    14     DIR *dp;
    15     struct dirent * p = NULL;
    16     dp = opendir(argv[1]);
    17     if(dp == NULL)
    18     {
    19         perror("fail to opendir");
    20         return -1;
    21     }
    22     
    23     while(1)
    24     {
    25         p = readdir(dp);
    26         if(p == NULL)
    27         {
    28             if(errno == 0)
    29             {
    30                 break;
    31             }
    32             else
    33             {
    34                 perror("fail to readdir");
    35                 return -1;
    36             }
    37         }
    38 
    39 
    40         printf("%s\n",p->d_name);
    41 
    42     }
    43 
    44     closedir(dp);
    45     return 0;
    46 }
    ls

    stat:获取文件详细信息 man 2
    int stat(const char *path, struct stat *buf);
    参数:1.文件路径2.文件信息结构体
    注:(双向传参) 在应用层准备对应数据类型的空间,并将该空间首地址传入函数,函数执行结束后,内核将结果通过地址返回

     1 #include <stdio.h>
     2 #include <sys/types.h>
     3 #include <dirent.h>
     4 #include <errno.h>
     5 #include <sys/stat.h>
     6 #include <unistd.h>
     7 #include <strings.h>
     8 struct stat buf;
     9 
    10 
    11 int fun(char *name);
    12 
    13 
    14 int main(int argc, const char *argv[])
    15 {
    16     if(argc != 2)
    17     {
    18         fprintf(stderr,"please input dirname!\n");
    19         return -1;
    20     }
    21 
    22     DIR *dp;
    23     struct dirent * p = NULL;
    24     //打开目录文件
    25     dp = opendir(argv[1]);
    26     if(dp == NULL)
    27     {
    28         perror("fail to opendir");
    29         return -1;
    30     }
    31     
    32     while(1) //循环读取目录中文件信息
    33     {
    34         p = readdir(dp);
    35         if(p == NULL)
    36         {
    37             if(errno == 0)
    38             {
    39                 break;
    40             }
    41             else
    42             {
    43                 perror("fail to readdir");
    44                 return -1;
    45             }
    46         }
    47         //获取该目录下文件的名字,传递给fun函数执行
    48         fun(p->d_name);
    49 
    50     }
    51 
    52     closedir(dp);
    53     return 0;
    54 }
    55 
    56 //调用stat函数获取文件信息
    57 int fun(char *name)
    58 {
    59     bzero(&buf,sizeof(buf));
    60     stat(name,&buf);
    61     switch(buf.st_mode & S_IFMT)
    62     {
    63         case S_IFSOCK:
    64             printf("s ");
    65             break;
    66         case S_IFLNK:
    67             printf("l ");
    68             break;
    69         case S_IFREG:
    70             printf("- ");
    71             break;
    72         case S_IFBLK:
    73             printf("b ");
    74             break;
    75         case S_IFDIR:
    76             printf("d ");
    77             break;
    78         case S_IFCHR:
    79             printf("c ");
    80             break;
    81         case S_IFIFO:
    82             printf("p ");
    83             break;
    84     }
    85 
    86     printf("%ld %s\n",buf.st_size,name);
    87 
    88     return 0;
    89 }
    stat

    库:


    ELF文件 可执行可链接格式

    静态库 在编译时需求 在运行时不需求
    特点:编译生成的文件会较大,编译完成后运行时可以脱离静态库运行
    静态库的制作:
    1.gcc -c 需要被制作的文件.c -o 需要被制作的文件.o
    例如:gcc -c fun1.c -o fun1.o
    2.ar crs lib库名.a 需要被制作的文件.o
    例如:ar crs libmyhello.a fun1.o
    运行时链接库:
    3.gcc xxx.c -o xxx -L(指定静态库所在路径)路径 -l库名
    例如:gcc main.c -o hello -L. -lmyhello

    动态库 在编译时不需求 在运行时需求
    特点:编译时不需求动态库,生成的文件较小,但是运行时需要加载动态库的代码
    动态库的制作:
    1.gcc -fPIC -Wall -c 需要被制作的文件.c
    例如: gcc -fPIC -Wall -c fun1.c
    2.gcc -shared -o lib库名.so 需要被制作的文件.o
    例如:gcc -shared -o libhqyj.so fun1.o
    3.gcc xxx.c -L. -l库名
    例如:gcc main.c -L. -lhqyj
    4.mv lib库名.so /lib 或者 /usr/lib
    例如:sudo mv libhqyj.so /lib

  • 相关阅读:
    python冲刺(5)列表声称式
    python冲刺(4)切片 等
    python冲刺(3)函数 等
    python冲刺(2)
    python冲刺(1)
    redis初步(1)
    php连接Oracle的时候遇到的编码集问题
    redis初步
    php 命名空间
    指向字符数组的指针与指向整型数组的指针
  • 原文地址:https://www.cnblogs.com/hslixiqian/p/9558933.html
Copyright © 2020-2023  润新知