在学习C语言文件操作时,遇到这样一个题目:
编写示例程序,把数据从文本文件中读取出来,并解析xml,存入struct st_girl结构体中,然后在界面上显示出来。
文本文件的内容如下:
解决此题的大致思路:首先创建一个字符串数组用于存放从文本文件中读取到的数据,随后使用fgets函数逐行读取文件中的数据,读一行解析一行,最后存入相应的结构体数组。
为解析xml字符串,编写了以下核心函数:
/*
*函数功能:从xml字符串中解析出相应的数据(姓名等)
*函数参数:in_XMLBuffer xml字符串首地址
* in_FiledName 标签名
* out_Value 解析结果存放的地址
*/
int GetXMLBuffer_Str(char* in_XMLBuffer,char* in_FiledName,char* out_Value)
{
//如果out_Value是空地址,直接返回
if(out_Value ==0)
return -1;
int m_NameLen = strlen(in_FiledName); //记录字段标签长度,如name标签的长度
char* start = 0; //记录开始标签的位置
char* end = 0; //记录结束标签的位置
char m_SFiledName[51],m_EFiledName[51]; //字段的开始标签和结束标签
//初始化
memset(m_SFiledName,0,sizeof(m_SFiledName));
memset(m_EFiledName,0,sizeof(m_EFiledName));
//函数原型int snprintf(char *str, size_t size, const char *format, ...)
//snprintf函数将可变个参数(...)按照format格式化成字符串,然后将其复制到str中
snprintf(m_SFiledName,50,"<%s>",in_FiledName); //利用snprintf将name写入开始标签中<name>
snprintf(m_EFiledName,50,"</%s>",in_FiledName); //利用snprintf将name写入结束标签中</name>
start = 0,end = 0;
/*
*extern char *strstr(char *str1, const char *str2);
* 语法:
* strstr(str1,str2)
* str1: 被查找目标
* str2: 要查找对象
* 返回值:若str2是str1的子串,则返回str2在str1的首次出现的地址;
* 如果str2不是str1的子串,则返回NULL。
*/
start = (char*)strstr(in_XMLBuffer,m_SFiledName);
if(start!=0)
{
/* 如果start不为0,再根据strstr函数找end位置,这里strstr的第一个参数用start就可以,
*不用再传入in_XMLBuffer从头再找,直接从start位置找更加省时间。
*/
end = (char*)strstr(start,m_EFiledName);
}
//判断start和end的值 若为0直接返回
if((start == 0)||(end == 0))
return -1;
//记录要解析的字段的长度
int m_ValueLen = end - start - m_NameLen - 2;
strncpy(out_Value,start + m_NameLen + 2,m_ValueLen);
out_Value[m_ValueLen] = 0;
return 0;
}
整体代码:
/*
* 解析xml,存入struct st_girl结构体中,然后在界面上显示出来。
*<name>西施</name><age>20</age><height>166</height><sc>一般</sc><yz>漂亮</yz>
*/
#include<stdio.h>
#include<string.h>
#include <stdlib.h>
int GetXMLBuffer_Str(char* in_XMLBuffer,char* in_FiledName,char* out_Value);
int GetXMLBuffer_Int(char *in_XMLBuffer,char *in_FiledName,int *out_Value);
struct st_girl{
char name[50];
int age;
int height;
char sc[30];
char yz[30];
}stgirl[5];
int main()
{
FILE* fp = 0;
char strbuf[301]; //用于存放xml格式字符串
if((fp = fopen("stgirl.txt","rt")) ==0)
{
printf("打开文件失败!\n");
return -1;
}
//fgets函数逐行读取文件中的数据
/*
*读一行解析一行,然后存入结构体数组
*/
int i = 0;
while(1)
{
if(fgets(strbuf,301,fp)==0)
break;
GetXMLBuffer_Str(strbuf,"name",stgirl[i].name); //姓名
GetXMLBuffer_Int(strbuf,"age",&stgirl[i].age); //年龄
GetXMLBuffer_Int(strbuf,"height",&stgirl[i].height); //身高
GetXMLBuffer_Str(strbuf,"sc",stgirl[i].sc); //身材
GetXMLBuffer_Str(strbuf,"yz",stgirl[i].yz); //颜值
printf("第%d位超女信息:\n",i+1);
printf("姓名:%s,年龄:%d,身高:%d,身材:%s,颜值:%s",stgirl[i].name,stgirl[i].age,stgirl[i].height,stgirl[i].sc,stgirl[i].yz);
printf("\n");
i++;
}
fclose(fp);
return 0;
}
int GetXMLBuffer_Str(char* in_XMLBuffer,char* in_FiledName,char* out_Value)
{
//如果out_Value是空地址,直接返回
if(out_Value ==0)
return -1;
int m_NameLen = strlen(in_FiledName); //记录字段标签长度,如name标签的长度
char* start = 0; //记录开始标签的位置
char* end = 0; //记录结束标签的位置
char m_SFiledName[51],m_EFiledName[51]; //字段的开始标签和结束标签
//初始化
memset(m_SFiledName,0,sizeof(m_SFiledName));
memset(m_EFiledName,0,sizeof(m_EFiledName));
//函数原型int snprintf(char *str, size_t size, const char *format, ...)
//snprintf函数将可变个参数(...)按照format格式化成字符串,然后将其复制到str中
snprintf(m_SFiledName,50,"<%s>",in_FiledName); //利用snprintf将name写入开始标签中<name>
snprintf(m_EFiledName,50,"</%s>",in_FiledName); //利用snprintf将name写入结束标签中</name>
start = 0,end = 0;
/*
*extern char *strstr(char *str1, const char *str2);
* 语法:
* strstr(str1,str2)
* str1: 被查找目标
* str2: 要查找对象
* 返回值:若str2是str1的子串,则返回str2在str1的首次出现的地址;
* 如果str2不是str1的子串,则返回NULL。
*/
start = (char*)strstr(in_XMLBuffer,m_SFiledName);
if(start!=0)
{
/* 如果start不为0,再根据strstr函数找end位置,这里strstr的第一个参数用start就可以,
*不用再传入in_XMLBuffer从头再找,直接从start位置找更加省时间。
*/
end = (char*)strstr(start,m_EFiledName);
}
//判断start和end的值 若为0直接返回
if((start == 0)||(end == 0))
return -1;
//记录要解析的字段的长度
int m_ValueLen = end - start - m_NameLen - 2;
strncpy(out_Value,start + m_NameLen + 2,m_ValueLen);
out_Value[m_ValueLen] = 0;
return 0;
}
GetXMLBuffer_Int(char *in_XMLBuffer,char *in_FiledName,int *out_Value)
{
char strvalue[51];
memset(strvalue,0,sizeof(strvalue));
if(GetXMLBuffer_Str(in_XMLBuffer,in_FiledName,strvalue)!=0)
return -1;
/*
*函数原型:int atoi(const char* nptr).
*函数功能:把字符串转换成整型数,ascii to integer
* 函数会扫描参数 nptr字符串,会跳过前面的空白字符(例如空格,tab缩进)等。
* 如果 nptr不能转换成 int 或者 nptr为空字符串,那么将返回 0
*/
(*out_Value) = atoi(strvalue);
return 0;
}
程序运行结果: