标准IO
能够将指定的数据写入指定的文件中的操作(通过文件指针去访问指定的文件:FILE*),标注IO只提供写入或者读取操作,不提供删除文件中的内容,想要删除文件,则需要自己写逻辑来实现。
文件指针如何指向文件
fopen函数
FILE *fopen(const char *pathname, const char *mode);
功能:
让一个文件流指针指向pathname文件,并以mode形式打开该文件,指向文件的文件流指针会以返回值的形式返回。
参数:
pathname:准备被FILE*指针指向的文件的路径名
mode:使用以下提供的几种形式打开
r:文件以只读的形式打开,打开后文件流指针指向文件的开头,文件开头指的是文件的第一个数据的地址,文件结尾指向文件中结束符的地址。(如果文件不存在,则打开失败,FILE*指向NULL)
w:文件以只写的形式打开,如果文件存在,则清空文件内容后打开,如果文件不存在,则创建文件后打开,文件打开后,文件流指针指向文件的开头。(以w形式打开文件,大概率成功,当文件打开数达到上限(1024)时失败,可以用ulimit -a查看)
r+:以读写的形式打开文件,其他和“r”一样(不会清空文件,不会创建文件)。(以读写的形式打开,读光标与写光标独立管理,针对文件的读写操作都会使文件流指针自动向后偏移一位,保持下次读写的使新的数据)
w+:以读写的形式打开文件,其他和“w”一样。(以读写的形式打开,读光标与写光标独立管理,针对文件的读写操作都会使文件流指针自动向后偏移一位,保持下次读写的使新的数据)
a:以追加写的形式打开文件,从文件的末尾开始写,如果文件不存在,则创建文件后打开,如果文件存在则直接打开,文件打开后,文件指针指向文件末尾
a+:以读和追加写的形式打开文件,如果文件不存在,则创建文件后打开,如果文件存在则直接打开(读指针指向文件的开头,写指针总是指向文件的末尾)
fclose函数
功能:
关闭一个文件,只需要传入一个文件流指针,即可关闭该文件
三个特殊的文件流指针
stdin,stdout,stderr:都是FILE*类型的,这三个文件流指针不需要手动打开,每一个程序天生就有
stdin:指向终端输入流(scanf)
stdout:指向终端输出流(printf)
stdout:指向终端的错误流
标准错误流
错误流本质上就是一种输出流,默认的错误流还是输出到终端
存在意义:仅仅为了区分标注输出流,标准输出流输出到终端,标准错误流通过一系列的操作,输出到”错误日志“,将来查看错误信息的时候
标准错误流使用的函数
perror函数
void perror(const char *s);
功能:
使用stderr输出s +“:”+ error对应的错误信息
erron:本质上是一个全局的int变量
大部分函数运行出错时都会修改erron的值
查看代码中的某个宏的值
- cd /usr/include
- sudo ctags -R //建立一个索引目录
- vim -t 想要搜索的代码
读写文件
fputc和fgetc
fputc
int fputs(const char *s, FILE *stream);
功能:
将数据输出到文件流指针所指向的文件中(向文件中输入一个字节的数据之后,文件流指针自动向后偏移一个字节,防止覆盖钱一个字节的内容)
fgetc
int fgetc(FILE *stream);
功能:
从指针指向的文件中,读取一个字节的数据,并且将读取到的数据以返回值的形式返回
返回值:成功读取数据,返回读取到的字符(unsigned char形式),读取到文件末尾返回 EOF (-1),我们使用 fgetc 想要读取文件中所有内容的时候,由于不知道文件中有多少数据,所以只能通过读取到文件结束符的方式来判断文件是否读取结束
fgetc读取到文件结束符返回的就是 EOF 也就是 -1
总结:所有想要读取文件中所有数据的代码,
形式如下
while(1)
{
读取文件的函数
判断文件是否读取完毕{break;}
}
练习:
使用fgetc计算一个文件的行数
使用fgetc与fputc实现文件拷贝功能
fprintf和fscanf
fprintf
int printf(const char *format, ...);
把数据输出到终端
int fprintf(FILE *stream, const char *format, ...);
功能:
将format字符串中的内容,输出到stream文件流指针指向的文件中去,想要将数据以何种形式输出到文件中,只需在format中选择合适的占位符即可。
int sprintf(char *str, const char *format, ...);
功能:
将format字符串中的内容,输出到str所指向的字符数组中。(把任意类型的数据转换为字符串类型数据)
fscanf
int scanf(const char *format, ...);
从终端读取数据,把数据写入到format中格式占位符代表的变量的地址上
int fscanf(FILE *stream, const char *format, ...);
功能:
从stream文件流指针的指向的文件中读取匹配数量的数据(根据文件中数据的类型以及格式占位符的类型进行匹配),遇到不匹配的数据则不吸收,然后将吸收到的数据写入format中格式占位符所代表的地址上去。*%c可以吸收任意数据包括空格,回车等
返回值:成功吸收数据返回成功吸收的数据的项数(其实就是指格式占位符的数量)
*fscanf是格式化读取文件的函数,需要精准的把控文件中的数据是什么格式,然后使用对应的格式去读取,除非用%c一个字节一个字节的读取。
int sscanf(const char *str, const char *format, ...);
功能:
从str所指向的字符串或字符串数组中读取数据,写入format所代表的地址上。(将字符串类型转换成任意类型的数据)
练习
typedef struct student
{
char name[20];
int c;
int m;
int e;
int p;
int ch;
int b;
}stu;
stu str[3]={};
编写两个.c文件:save.c和load.c
save.c负责使用fprintf把三个学生的数据保存到文件中
load.c负责读取文件中的学生信息,将读取到的数据,存到数组中,并输出数组中的内容
练习
有如下结构体:
typedef struct Student{
char name[20];
int chinese;//语文成绩
int math;
int english;
int physical;
int chemical;
int biological;
}stu_t;
使用一张链表保存5个学生的信息,学生信息自己初始化
编写2个.c文件,save.c 和 load.c
save.c负责:
使用fprintf将3个学生的所有信息保存到文件中去
load.c负责:
使用fscanf读取文件中的3个学生的信息,将读取到的数据,保存到一个 stu_t arr[3]数组里面去,并输出arr数组中的内容
最终实现效果:
运行save.c,会将准备的学生信息写入文件中
运行load.c,会将文件中的所有学生信息输出到终端上
save.c文件
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <wait.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/un.h>
typedef struct sockaddr_in addr_in_t;
typedef struct sockaddr addr_t;
typedef struct sockaddr_un addr_un_t;
typedef struct student
{
char name[20];
int c;
int m;
int e;
int p;
int ch;
int b;
}stu;
typedef stu DataType;
typedef struct node
{
union
{
int len; //头节点的数据域
DataType data; //普通节点的数据域
};
struct node *next; //节点的指针域
}linkList,*linkListPtr;
linkListPtr create()
{
linkListPtr l=(linkListPtr)malloc(sizeof(linkList));
if(NULL==l)
{
printf("创建失败\n");
return NULL;
}
l->len=0;
l->next=NULL;
printf("创建成功\n");
return l;
}
linkListPtr create_node(DataType a)
{
linkListPtr p=(linkListPtr)malloc(sizeof(linkList));
if(NULL==p)
{
printf("申请失败\n");
return NULL;
}
p->data=a;
p->next=NULL;
return p;
}
void add(linkListPtr l,DataType a)
{
if(NULL==l)
{
printf("插入失败\n");
return;
}
linkListPtr p=create_node(a);
if(NULL==p)
{
return;
}
linkListPtr q=l;
while(q->next)
{
q=q->next;
}
q->next=p;
l->len++;
}
int main(int argc, const char *argv[])
{
linkListPtr l=create();
stu str[5]={
{"牛二",45,65,57,48,98,15},
{"孙一",45,65,57,48,98,15},
{"张三",45,65,57,48,98,15},
{"李四",15,34,48,57,98,48},
{"王五",54,25,15,67,18,46},
};
add(l,str[0]);
add(l,str[1]);
add(l,str[2]);
add(l,str[3]);
add(l,str[4]);
FILE* fp=fopen("./student","w");
linkListPtr q=l;
for(int i=0;i<l->len;i++)
{
q=q->next;
fprintf(fp,"%s %d %d %d %d %d %d\n",q->data.name,q->data.c,q->data.m,q->data.e,q->data.p,q->data.ch,q->data.b);
}
fclose(fp);
return 0;
}
load.c文件
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <wait.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/un.h>
typedef struct sockaddr_in addr_in_t;
typedef struct sockaddr addr_t;
typedef struct sockaddr_un addr_un_t;
typedef struct student
{
char name[20];
int c;
int m;
int e;
int p;
int ch;
int b;
}stu;
typedef stu DataType;
typedef struct node
{
union
{
int len; //头节点的数据域
DataType data; //普通节点的数据域
};
struct node *next; //节点的指针域
}linkList,*linkListPtr;
linkListPtr create()
{
linkListPtr l=(linkListPtr)malloc(sizeof(linkList));
if(NULL==l)
{
printf("创建失败\n");
return NULL;
}
l->len=0;
l->next=NULL;
printf("创建成功\n");
return l;
}
linkListPtr create_node(DataType a)
{
linkListPtr p=(linkListPtr)malloc(sizeof(linkList));
if(NULL==p)
{
printf("申请失败\n");
return NULL;
}
p->data=a;
p->next=NULL;
return p;
}
void add(linkListPtr l,DataType a)
{
if(NULL==l)
{
printf("插入失败\n");
return;
}
linkListPtr p=create_node(a);
if(NULL==p)
{
return;
}
linkListPtr q=l;
while(q->next)
{
q=q->next;
}
q->next=p;
l->len++;
}
int main(int argc, const char *argv[])
{
FILE* fp=fopen("./student","r");
linkListPtr l=create();
stu str[128]={0};
linkListPtr q=l;
int i=0;
while(1)
{
int v=fscanf(fp,"%s %d %d %d %d %d %d\n",str[i].name,&str[i].c,&str[i].m,&str[i].e,&str[i].p,&str[i].ch,&str[i].b);
if(EOF==v)
break;
i++;
}
add(l,str[0]);
add(l,str[1]);
add(l,str[2]);
add(l,str[3]);
add(l,str[4]);
for(int i=0;i<l->len;i++)
{
q=q->next;
printf("%s %d %d %d %d %d %d\n",q->data.name,q->data.c,q->data.m,q->data.e,q->data.p,q->data.ch,q->data.b);
}
return 0;
}