C语言随笔(七)文件操作

通过程序实现文件的读取操作

1.头文件声明

为了方便函数的调用,.c文件之间调用函数通常使用.h文件进行声明
,将需要用到的函数声明在.h文件中。
首先我们要读取的文件内容为

#这是我的的ip地址
ip:127.0.0.1
#这是我的端口
port:8080
#这是用户名
username:root
#这是密码
password:root
aaa:bbbb
cccc:dddd

其中#号开头的内容为注释内容为无效行,不需要读取,有效行格式为

key(关键字):value(有效值)

将要使用到的函数声明在config.h文件中,代码如下

//防止头文件重复包含
#pragma once

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

struct configInfo
{
	char key[64];
	char value[128];
};

//C++无法直接调用c的函数因此要写如下声明,使得编译器知道下面的内容是c语言函数
#ifdef _cplusplus
	extern "c"{
#endif
		//获得文件有效行数
		int getLines_configFile(FILE *file);
		//判断有效行
		int validlines(const char * buf);
		//加载文件
		void loadfile_configfile(const char * filepath,char ***fileData,int * lines);
		//解析文件
		void parsefile_configfile(char **fileData,int  lines,struct configInfo **info);
		//获得指定文件信息
		char * getinfo_configfile(const char * key,struct configInfo *info,int line);
		//释放内存
		void freeconfig(struct configInfo * info);
#ifdef _cplusplus
}
#endif

2.将函数实现

#include"configfile.h"
//判断有效行
int validlines(const char * buf)
{
	/*由于有效行的格式为key(关键字):value(有效值)
	因此判断有效行的条件为行首位置是否有# \n换行 内容中是否有':'
	*/
	if (buf[0]=='#' || buf[0]=='\n' || strchr(buf,':')==NULL )
	{
		return 0;//非有效行返回0
	}
	return 1;//有效行返回1
//获得文件有效行数
int getLines_configFile(FILE *file)
{
	char buf[1024]={0};
	int lines = 0;
	while(fgets(buf,1024,file) != NULL)
	{
		if (!validlines(buf))
			continue;
		lines++;
		memset(buf,0,1024);
	}
	fseek(file,0,SEEK_SET);//档获得有效行时,文件指针在文本末尾,需要返回到文件开头
	return lines;
}
//加载配置文件参数为(文件路径,返回的文件内容,返回的有效行数)
void loadfile_configfile(const char * filepath,char ***fileData,int * line)
{
	FILE *file =fopen(filepath,"r");
	if (NULL == file)
	{
		return;
	}
	int lines = getLines_configFile(file);//获取有效行后,指针重定向到文件开头
	char ** temp =(char **)malloc(sizeof(char *)* lines);//开辟空间接收文件内容
	char buf[1024] = {0};//接收文件一行的内容
	int index =0;//计数器
	while (fgets(buf,1024,file) !=NULL)//判断接收的行是否为空
	{
		if(!validlines(buf))//判断是否是有效行无效进入下一次内容
			continue;
		temp[index]=(char *)malloc(strlen(buf)+1);
		strcpy(temp[index],buf);//将有效信息导入到空间中
		index++;
		memset(buf,0,1024);//重置buf空间
	}
	* fileData = temp;//返回有效内容
	* line =lines;//返回有效的行数
	fclose(file);//关闭文件
}
//解析配置文件传递参数(有效的文件内容,有效行数,要传入的结构体)
void parsefile_configfile(char **fileData,int  lines,struct configInfo **info)
{
	struct configInfo * myinfo = (struct configInfo *)malloc(sizeof(struct configInfo)*lines);//开辟空间接收关键字和有效值
	memset(myinfo,0,sizeof(struct configInfo)*lines);//重置空间
	for(int i =0;i<lines;i++)
	{
		char * pos = strchr(fileData[i],':');//定位在行中':'的位置
		strncpy(myinfo[i].key,fileData[i],pos-fileData[i]);//将key的内容传入结构体中的key值
		if(strchr(fileData[i],'\n'))//由于配置信息中最后一行没有换行'\n'
			strncpy(myinfo[i].value,pos+1,strlen(pos+1)-1);//有\n换行的
		else
			strncpy(myinfo[i].value,pos+1,strlen(pos+1));//没有\n换行的
	}
	*info = myinfo;//将整理好的结构体返回
	for (int i = 0; i < lines; i++)//释放空间
	{
		if (fileData[i] != NULL)
		{
			free(fileData[i]);
		}
	}
}
//获得指定配置信息传递参数(查询值,结构体,有效行数)
char * getinfo_configfile(const char * key,struct configInfo *info,int line)
{
	for (int i = 0; i < line; i++)
	{
		if (strcmp(key,info[i].key)==0)//判断查询值和文件中的有效值相同
		{
			return info[i].value;
		}
	}
	return NULL;
	
}
//释放内存
void freeconfig(struct configInfo * info)//释放结构体内存
{
	if ( NULL==info)
	{
		return;
	}
	free(info);
	info =NULL;
}
}

3 调用函数实现查询功能

#include"configfile.h"
void test(char *str)
{
	char **filedata;
	int line;
	struct configInfo *output=NULL;
	//加载配置文件将有效内容返回filedata、line
	loadfile_configfile("./config.ini",&filedata,&line);
	//解析配置文件将有效内容依次传递到结构体output
	parsefile_configfile(filedata,line,&output);
	//打印要查看的配置信息
	printf("%s: %s\n",str,getinfo_configfile(str,output,line));
	//释放配置信息
	freeconfig(output);
}
void main()
{
	char str[1024]={0};
	while (true)
	{
		printf("请输入要查看的配置信息:");
		scanf("%s",str);
		if(strcmp(str,"exit")==0)
		{
			break;
		}	
		test(str);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值