苏嵌实训——day13(下)

简介: 苏嵌实训——day13(下)

二、标准IO


2.1 标准IO的定义


标准IO是由标准C库提供的API接口,是在文件IO的基础上封装出来的函数接口,第一个原因是为了增加可移植性。并且,标准IO在文件IO的基础上封装了一个叫缓冲区的东西,用来存放一些不是很着急的数据,等到缓冲区满,调用一次文件IO完成写入工作或者读取工作。有些数据是特别着急的,



比如:下发的命令,实时监控数据,必须要使用文件IO。
伪代码:
fopen(参数)
        if(is win)
        {
            _open(参数);            
        }
        else if(is linux)
        {
            open(参数);
        }


2.1.1 文件流指针


FILE pointer

文件流指针:是一个文件的标志,是在文件描述符上封装出来的一个结构体指针,缓冲区就在这个流指针中。

流:流指针 -----文件流指针 —这个流

追代码:

安装一个索引搜索文件tags(搜索引擎)

第一步:创建目录的引擎文件—tags (想要搜索哪个目录就在哪个目录下创建)

ctags -R //生成一个引擎文件叫tags

第二步:搜索

vi -t 目标字符串 例如: vi -t FILE

第三步:选择准确的目录下的文件

第四步:翻阅文档----》代码跳转

追代码:光标点击想要跳转的字符串 ,ctrl + ]进行跳转搜索

返回上一层:ctrl + t


0a2653c851af460fa595bd959398a8f1.png


2.2 标准IO函数接口


2.2.1 fopen

头文件: #include  

原型:FILE *fopen(const char *pathname, const char *mode);

功能:打开一个文件

参数:pathname:要打开文件的路径及名称

mode:打开文件的方式

r:以只读的方式打开一个文件,文件必须存在

r+:以读写的方式打开一个文件,文件必须存在

w:如果文件存在则清空写入,如果文件不存在则创建写入

w+:如果文件存在则清空读写,如果文件不存在则创建读写

a:如果文件存在则追加写入,如果文件不存在则创建再写入

a+:如果文件不存在则创建文件并追加写入和读取,读取时从文件开头开始读取,写入时从文件的末尾开始写入,lseek偏移后不能进行写入操作

如果进行写入操作,则追加在末尾写入(不管之前如何偏移)

注意:有可能以后会遇到 rb+,b代表执行二进制操作,linux下无区分

返回值:

成功会返回一个文件流指针

失败返回NULL。


2d65d23f6d4748949b924e4057485923.png


#include <stdio.h>
int main(int argc, char const *argv[])
{
    //打开一个文件需要定义一个文件流指针来指向fopen返回的已经封装好的文件流指针
    //FILE *fp = fopen("./1.txt","r");
    FILE *fp = fopen("./1.txt","w");
    if(NULL == fp)
    {
        perror("open");
        return -1;
    }
    printf("打开文件成功!\n");
    return 0;
}


2.2.2 fclose

头文件:

#include  

原型:

int fclose(FILE *stream);

功能:关闭一个文件流指针 //文件流指针里也绑定了一个文件的描述符

参数:目标文件流指针

返回值:

成功:返回 0

失败: -1


2.2.3. fgetc

头文件:

#include  

原型:

int fgetc(FILE *stream);

功能:从指定文件流指针中获取一个字符

参数:目标文件流指针

返回值:

成功:返回获取到的字符转化成int类型的数据

失败: 返回EOF

到达文件末尾: EOF


2.2.4 feof

头文件:

#include  

原型:

int feof(FILE *stream);

功能:判断是否到达了文件末尾

参数:目标文件流指针

返回值:如果到达了文件的末尾返回一个非0值

其它情况返回0

2.2.5 ferror

头文件:

#include  

原型:

int ferror(FILE *stream);

功能:判断文件操作是否出错

参数:目标文件流指针

返回值:如果文件操作失败了,返回一个非0值

其它情况返回0


#include <stdio.h>
int main(int argc, char const *argv[])
{
    FILE *fp = fopen("./1.txt","r");
    if(NULL == fp)
    {
        perror("fopen");
        return -1;
    }
    //开始做循环读取
    while(1)
    {
        int ret = fgetc(fp);
        if(EOF == ret)
        {
            if(feof(fp))
            {
                printf("到达了文件末尾!\n");
                break;
            }
            else
            {
                printf("获取失败!\n");
                return -1;
            }
        }
        printf("获取到的数据为%d---所对应的字符为%c\n",ret,ret);
    }
    if(fclose(fp) == EOF)
    {
        printf("关闭失败\n");
        return -1;
    }
    return 0;
}


2.2.6 fputc

头文件:

#include  

原型:

int fputc(int c, FILE *stream);

功能:向指定的一个文件输出一个字符

参数:c:想要写入的字符,将int转换成 unsigned char类型的数据写入

stream:目标文件流指针

返回值:

成功返回:写入的字符转换成int类型的数据

失败返回:EOF


#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[])
{
    FILE *fp = fopen("./1.txt","w");
    if(NULL == fp)
    {
        perror("fopen");
        return -1;
    }
    //开始向文件中写入数据
    char buf[123] = "hello world";
    int i = 0;
    while(1)
    {
        fputc(buf[i],fp);
        if((strlen(buf) - 1) == i)
        {
            break;
        }
        i++;  //遍历数组使用
    }
    fclose(fp);
    return 0;
}


2.2.7 fgets

头文件:

#include  

原型:

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

功能:行读取

参数:s:读取到的数据存放的地址

size:读取的字节个数

1.当\n之前的字节个数小于size,遇到\n结束读取

但是换行符也会被当做一个字符被读到内存之中,并且会在最后一个字符后添加’\0’.

2.当\n之前的字节个数大于size,会读到size个大小的字节时停止读取,

会在末尾加上一个’\0’,会将最后一个字节的字符给覆盖掉。

机制会在读取完之后读写指针向前偏移一个字节

stream:目标文件流指针

返回值:

成功返回:读到的字符串的首地址

失败返回:NULL

读到文件末尾:返回NULL


#include <stdio.h>
int main(int argc, char const *argv[])
{
    FILE *fp = fopen("./1.txt","r");
    if(NULL == fp)
    {
        perror("fopen");
        return -1;
    }
    //行读取
    while(1)
    {
        char buf[123] = {0};
        if(fgets(buf,11,fp) == NULL)
        {
            //失败或者读到文件末尾
            if(feof(fp))
            {
                printf("读到了文件的末尾\n");
                break;
            }
            else
            {
                perror("fgets");
                return -1;
            }
        }
        printf("buf = %s\n",buf);
    }
    fclose(fp);
    return 0;
}


2.2.8 fputs

头文件:

#include  

原型:

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

功能:向一个文件进行字符串输入

参数:s:想要写入的数据的地址

stream:目标文件流指针

返回值:

成功返回:一个非负数

失败返回:EOF(-1)


#include <stdio.h>
int main(int argc, char const *argv[])
{
    FILE *fp = fopen("./1.txt","w");
    if(NULL == fp)
    {
        perror("fopen");
        return -1;
    }
    //想要写入的数据的地址
    char buf[123] = "hello world";
    if(EOF == fputs(buf,fp))
    {
        perror("fputs");
        return -1;
    }
    fclose(fp);
    return 0;
}


练习:请编写一个代码,用来测试文件的行数

#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[])
{
    FILE *fp = fopen(argv[1],"r");
    if(NULL == fp)
    {
        perror("fopen");
        return -1;
    }
    int count = 0;
    //开始计算
    while(1)
    {
        char buf[123] = {0};
        if(NULL == fgets(buf,sizeof(buf),fp))
        {
            //出错或者到了文件末尾
            if(feof(fp))
            {
                printf("到达了文件的末尾\n");
                break;
            }
            else
            {
                perror("fgets");
                return -1;
            }
        }
        if(buf[strlen(buf) - 1] == '\n')
        {
            printf("buf = %s\n",buf);
            count++;
        }
    }
    count++;
    printf("该文件的行数为:%d\n",count);
    fclose(fp);
    return 0;
}


2.2.9 fread

头文件:

#include  

原型:

size_t fread(void *ptr, size_t size, size_t nmemb, FILE stream);

功能:二进制读取文件

参数:ptr:存放读到的数据的地址

size:对象的大小

nmemb:对象的个数

注意:总的读取的字节个数为对象的大小对象的个数

stream:目标文件流指针

返回值:

成功返回:成功返回读到的对象的个数

失败返回:0


2.2.10 fwrite

头文件:

#include  

原型:

size_t fwrite(const void *ptr, size_t size, size_t nmemb,

FILE *stream);

功能:二进制写入文件

参数:ptr:想要写入的数据的首地址

size:对象的大小

nmemb:对象的个数

stream:目标文件流指针

返回值:

成功返回:成功返回读到的对象的大小

失败返回:返回一个小的对象的个数


#include <stdio.h>
#include <string.h>
struct person
{
    char name[32];
    char sex;
    int age;
    char phone[12];
};
struct person p1;  //定义一个录入使用的结构体
struct person p2;  //定义一个读取时使用的结构体
int main(int argc, char const *argv[])
{
STAT:
    //界面:
    printf("****************************\n");
    printf("1.录入信息 2 读取信息  3.退出\n");
    printf("****************************\n");
    printf("input>> ");
    int input = 0;
    scanf("%d",&input);
    if (input > 3 || input < 0)
    {
        goto STAT;
    }
    if(1 == input)
    {
        printf("请输入姓名\n");
        scanf("%s",p1.name);
        getchar();
        printf("请输入性别\n");
        scanf("%c",&p1.sex);
        getchar();
        printf("请输入年龄\n");
        scanf("%d",&p1.age);
        printf("请输入手机号\n");
        scanf("%s",p1.phone);
        getchar();
        FILE *fp = fopen("./1.txt","a");
        if(NULL == fp)
        {
            perror("fopen");
            return -1;
        }
        if(1 != fwrite(&p1,sizeof(p1),1,fp))
        {
            perror("fwrite");
            return -1;
        }
        fclose(fp);
        printf("写入信息结束,正在跳转菜单");
        goto STAT;
    }
    else if(2 == input)
    {
        char usrname[32] = {0};
        //读取信息
        printf("请输入要查询人的姓名\n");
        scanf("%s",usrname);
        getchar();
        //开始对文件进行读取并匹配
        FILE *fp = fopen("./1.txt","r");
        if(NULL == fp)
        {
            perror("fopen");
            return -1;
        }
        //循环读取
        while(1)
        {
            if(0 == fread(&p2,sizeof(p2),1,fp))
            {
                if(feof(fp))
                {
                    printf("读到文件末尾\n");
                    break;
                }
                else
                {
                    perror("fread");
                    return -1;
                }
            }
            if(strcmp(usrname,p2.name) == 0)
            {
                printf("姓名:%s\n",p2.name);
                printf("性别:%c\n",p2.sex);
                printf("年龄:%d\n",p2.age);
                printf("手机号:%s\n",p2.phone);
            }
        }
    }
    return 0;
}


相关文章
|
6月前
|
SQL 前端开发 数据库
|
6月前
|
算法 前端开发 Java
思途实训-day03-04
思途实训-day03-04
|
消息中间件 Linux
苏嵌实训——day16(下)
苏嵌实训——day16(下)
苏嵌实训——day16(下)
|
网络协议 安全 网络安全
苏嵌实训——day18
苏嵌实训——day18
111 0
苏嵌实训——day18
|
Ubuntu API 数据库
苏嵌实训——day19
苏嵌实训——day19
110 0
苏嵌实训——day19
|
存储 程序员 Linux
苏嵌实训——day14(上)
苏嵌实训——day14(上)
苏嵌实训——day14(上)
|
存储 自然语言处理 C语言
苏嵌实训——day2(上)
苏嵌实训——day2(上)
141 0
苏嵌实训——day2(上)
|
存储
苏嵌实训——day11(上)
苏嵌实训——day11(上)
101 0
苏嵌实训——day11(上)