标准IO及相关练习

标准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的值

查看代码中的某个宏的值

  1. cd /usr/include
  2. sudo ctags -R //建立一个索引目录
  3. 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;
}

  • 26
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值