c函数strstr和sscanf组合高级技巧
需求
上一章我们解析完了upnp协议中的http头部获取了xml文件的地址,使用http协议我们再次获取xml文件后需要解析xml,我们最害怕的就是引入一个又一个库,事实上,libupnp就引入了很多库,造成了程序臃肿,打印频繁,我们使用c语言的strstr和sscanf来手动解析xml,获取特定字符串。
1、分解url
upnp协议中的LOCATION是从http头部获取而来,要知道如何获取,请看这一片文章
解析http头部
接下来就是使用sscanf函数来获取http 的host 端口和路由信息,如
http://192.168.1.144:1551/description.xml
我们要分解成为 http://192.168.1.144:1551/ 和路由 /description,使用一个非常绚丽的技巧,如下所示:
const char *pos = ss["LOCATION"].c_str();//const char *url = "http://192.168.1.144:1551/description.xml";char http[256] = {"http://" };char route[256] = { 0 };if (*(pos + 4) == ':')pos += 7;sscanf(pos, "%[^/]%s", &http[7],route);
以上先把http://填入缓冲中,然后让sscanf 中缓冲的指针指向第7个字节,开始往里放解析值,sscanf函数跳过http://,找到我们字符串的下一个"/"位置。 ok,我们使用http协议下载xml文件,下载结束,得到xml body
1、下载下来后xml body
我们使用http协议在程序中拿到了xml body体
<?xml version ="1.0"?>
<root xmlns = "urn:schemas-upnp-org:device-1-0" xmlns:dlna = "urn:schemas-dlna-org:device-1-0">
<specVersion>
<major>1</major >
<minor>0</minor >
</specVersion>
<device>
<UDN>uuid:bb5e-21ce-1111-11b2-f918-ec9c-3235-709a-</UDN>
<friendlyName>Living Room 1_5336_HiDMR</friendlyName>
<deviceType>urn:schemas-upnp-org:device:MediaRenderer:1</deviceType >
<manufacturer>Hisilicon Technologies Co., Ltd</manufacturer>
<manufacturerURL>http://www.Hisilicon.com</manufacturerURL><modelName>Hisilicon MediaRenderer</modelName><modelNumber>1.1</modelNumber><modelURL>http://www.Hisilicon.com</modelURL><serialNumber></serialNumber><dlna:X_DLNADOC xmlns:dlna="urn:schemas-dlna-org:device-1-0">DMR-1.50</dlna:X_DLNADOC><dlna:X_DLNACAP xmlns:dlna="urn:schemas-dlna-org:device-1-0"></dlna:X_DLNACAP><serviceList><service><serviceType>urn:schemas-upnp-org:service:ConnectionManager:1</serviceType ><serviceId>urn:upnp-org:serviceId:ConnectionManager</serviceId>//需要获得下面这个controlURL<controlURL>/upnp/service/ConnectionManager/Control</controlURL><eventSubURL>/upnp/service/ConnectionManager/Event</eventSubURL><SCPDURL>/upnp/service/cms.xml</SCPDURL></service><service><serviceType>urn:schemas-upnp-org:service:AVTransport:1</serviceType ><serviceId>urn:upnp-org:serviceId:AVTransport</serviceId>//需要获得下面这个controlURL<controlURL>/upnp/service/AVTransport/Control</controlURL><eventSubURL>/upnp/service/AVTransport/Event</eventSubURL><SCPDURL>/upnp/service/avt.xml</SCPDURL></service><service><serviceType>urn:schemas-upnp-org:service:RenderingControl:1</serviceType ><serviceId>urn:upnp-org:serviceId:RenderingControl</serviceId>//需要获得下面这个controlURL<controlURL>/upnp/service/RenderingControl/Control</controlURL><eventSubURL>/upnp/service/RenderingControl/Event</eventSubURL><SCPDURL>/upnp/service/rcs.xml< / SCPDURL></service></serviceList></device></root>
这是一份upnp协议中的设备xml 描述,里面包含了几个关键信息,需要我们获取 我们需要的是:
1 设备名称
2 AVTransport 传输点的控制url
3 RenderingControl 点的控制url
熟悉upnp协议的同志们知道这个非常关键,下面我们来制定解决方案
2、定义数据结构
typedef struct s_xmlanalyse_c
{char friendlyName[64];char url_AVTransport[256];char url_RenderingControl[256];char url_ConnectionManager[256];
}s_xmlanalyse_c;
定义得到单个节点的内容函数,使用strstr函数来得到xml 字符串中的位置,将字符串内容使用memcpy来复制,字符串的本质是可打印并且最后一个字符是’\0’,因此我们使用memcpy 和 '\0’来生成新的字符串。
const char *GetValueOf_c(const char *sbody, const char *name, char *ret,int retlen)
{if (strlen(name) > 63)return NULL;char buf_fn1[64];char buf_fn2[64];sprintf(buf_fn1, "<%s>", name);sprintf(buf_fn2, "</%s>", name);const char *start = sbody;const char *end = sbody + strlen(sbody);char *fn = &buf_fn1[0];char *fnn = &buf_fn2[0];int len = strlen(fn);const char * x1 = strstr(start, fn);const char * x2 = strstr(start + len,fnn);if (x1 != NULL && x2 != NULL){x1 += len;int len2 = (int)(x2 - x1);if (len2 > retlen - 1)return NULL;memcpy(ret, x1, x2 - x1);ret[x2 - x1] = '\0';return x2 + len+1;}return NULL;
}
获取三个节点内容
使用三个循环获取内容
int GetValueOf_Service_c(const char *fpos, s_xmlanalyse_c *value)
{const char * fname = "serviceType";const char * fname2 = "controlURL";int flag = 0;char tmp[256];for (int i = 0; i < 3; i++){fpos = GetValueOf_c(fpos, fname, tmp,256);if (fpos == NULL){cout << "not good,xml is error" << endl;return -1;}if (strstr(tmp,"ConnectionManager") != NULL){fpos = GetValueOf_c(fpos, fname2, value->url_ConnectionManager,sizeof(value->url_ConnectionManager));flag++;}else if (strstr(tmp,"AVTransport") != NULL){fpos = GetValueOf_c(fpos, fname2, value->url_AVTransport,sizeof(value->url_AVTransport));flag++;}else if (strstr(tmp,"RenderingControl") != NULL){fpos = GetValueOf_c(fpos, fname2, value->url_RenderingControl,sizeof(value->url_RenderingControl));flag++;}}if (flag == 3)return 0;return -1;
}
总结
我们使用分解分而治之对待软件工程的方式,首先
A 定义数据结构
B 得到流程 --》2.1 http 头部分解–》2.2 分解url --》2.3获取xml --》2.4获取节点内容
C 定义截取url函数
其中2.4 分解为如下步骤
D 定义获取节点内容的函数
E 定义 调用4 函数得到多个节点内容的函数
c函数strstr和sscanf组合高级技巧相关推荐
- C 函数 strstr 的高效实现
C函数库中有一个函数 strstr(char*, char*),它实现的是在一个原字符串中查找一个子串,如果找到这样的一个子串,返回这个子串在原字符串中的起始位置,若没有找到这样的一个子串 ...
- C语言学习笔记---字符串查找函数strstr()和strpbrk()函数
strstr()函数 C语言中如何向查找一个字符串中是否包含另一个字符串,可以使用strstr()函数.使用示例如下: int main(int argc, char *argv[]) {char ...
- R语言ggplot2可视化:patchwork包将一个ggplot2可视化结果和一个plot函数可视化结果横向组合起来形成最终结果图、两个可视化的组合结果对齐、并为组合图像的每个子图添加标题
R语言ggplot2可视化:使用patchwork包(直接使用加号+)将一个ggplot2可视化结果和一个plot函数可视化结果横向组合起来形成最终结果图.将两个可视化的组合结果对齐.并为组合图像的每 ...
- R语言拟合ARIMA模型:使用forecast包中的auto.arima函数自动搜索最佳参数组合、模型阶数(p,d,q)、设置seasonal参数指定在模型中是否包含季节信息
R语言拟合ARIMA模型:使用forecast包中的auto.arima函数自动搜索最佳参数组合.模型阶数(p,d,q).设置seasonal参数指定在模型中是否包含季节信息 目录
- 如何用C语言实现各种字符函数和字符串函数strstr、memcpy、memmove、strlen、strcpy、strcmp、strcat
用C语言模拟实现字符函数与字符串函数 strstr.memcpy.memmove.strlen.strcpy.strcmp.strcat 若使用本文相关代码,还请动手点个赞!!! #define _C ...
- c函数sscanf的高级技巧(二)
第一篇文章 c函数sscanf高级技巧 需求 解析特定json,而不引入特定的库,如字符串 json字符串1"{\"ip\": [\"http://192.16 ...
- c函数sscanf的高级技巧
在解析url过程中,有时需要非常简单的分解,这时候可以使用几种方法 例如 const char *url = "http://192.168.1.144:1551/AVTransport/c ...
- c语言函数库学习~sscanf~格式化输入
---恢复内容开始--- 今天算是被打击到了吧,由郑轻的acm老师来我学院指导安排了个现场的小比赛,,俺们居然有还是输给一个大一的新手,,哎,情何以堪,,所以还是要重视下基础编程能力的培训,现在嘛我就 ...
- linux c 字符串查找函数 strstr strcasestr
一.strstr函数使用 [1] 函数原型 char *strstr(const char *haystack, const char *needle); [2] 头文件 #include <s ...
最新文章
- Reddit票选 | 2019年绝对不能错过的机器学习论文
- java异常_聊聊Java中的异常及处理
- 【腾讯第二届校园编程马拉松】HDU-4525,威威猫系列故事——吃鸡腿
- 配置HDFS HttpFS和WebHDFS
- 省选+NOI 第六部分 技巧与思想
- 江苏通报“中通宠物盲盒”事件:已立案调查
- cn.cw.gps.domain.VisitReport.setVisitID([Ljava.lang.String;)]
- Python并行实例
- mysql 索引越界_mysql隐式转换造成索引失效的事故总结
- namesilo续费
- ABAP BDC个人使用见解
- 用C语言写一个简单的飞机大战游戏(用到easyx图形库)
- 中国计量大学现代科技学院第四届“中竞杯”程序设计校赛(同步赛)F.爬塔
- 对矩阵乘法本质的理解——从向量线性组合角度
- 【综合笔试题】难度 3/5,挺有意思的一道题(既可图论,也可贪心)
- CleanMyMac2023Mac下载排行最好的清理工具
- 高电压放大器与高电流放大器该如何选择使用
- 心跳异常检测--使用Keras,K折交叉训练CNN一维卷积
- Flash按键响应-键码值表
- linux pwm控制蜂鸣器 滴滴_第七章----pwm蜂鸣器