再记一下sscanf的一个小问题

正在进行的项目中有个网络传输模块,需要在设备端将上位机发送的XML命令解析出来并转发到其它模块。在我测试一个获取数据的命令时,发现上位机读取到的数据是错误,看XML命令格式,明明是对的,但读到的数据就是不正确,肯定有问题。因为网络传输模块在其它项目一直使用,一直OK,现在出问题了,很郁闷。于是使出printf大法跟踪、终于找到问题原因。原来,又是sscanf搞的问题。记得小弟刚来这家公司时接手前人写的ftp模块,里面大量用了sscanf,还专门写了篇文章。现在又遇到了。

这个XML命令是自定义的,格式类似:大人[1],大奔[黄],大小[250],中括号表示为传递的参数,其中既有数字(%d)也有字符串(%s),一开始还以为是中文搞的鬼,后来查发现是只要是字符中在命令的中间,使用sscanf的%s就会将该字符串及以后的所有的字符都解析到,因此,字符串后面的数据就不正确了。

一开始想着使用字符串查找strchr逐个字符来查找、确定每一个参数,但那个命令一共有20多个参数,这点我是不能接受的。后来再调试一下,发现只要将有字符串的参数放到最后就可以了。至于最后有个右中括号,则可以将它直接写'\0'来解决。

不过这种方法,只能适用于只有一个字符串的情况。如果复杂的情况,最终的方法是重新制定命令的格式。


示例代码如下:

void sscanf_test()

{
    char* buff = "wo:[12],ni:[25],ta:[中文我顶]";
    char wo[32] = {0};
    char ni[32] = {0};
    char ta[32] = {0};
    char buffer[128] = {0};
    int wo1, ni1, ta1;
    printf("test1:\n");
    sscanf(buff, "wo:[%d],ni:[%d],ta:[%s]", &wo1, &ni1, ta);
    printf("output1:wo: %d \nni: %d \nta: %s\n", wo1, ni1, ta);


    char* buff1 = "wo:[12],ni:[结束了还来],ta:[250]";
    printf("test2:\n");
    sscanf(buff1, "wo:[%d],ni:[%s],ta:[%d]", &wo1, ni, &ta1);
    printf("output2:wo: %d\nni: %s \nta: %d\n", wo1, ni, ta1);

}

输出:

test1:
output1:wo: 12 
ni: 25 
ta: 中文我顶]
test2:
output2:wo: 12
ni: 结束了还来],ta:[250] 
ta: 7 // 此处已是错误的了


李迟 2015年1月18日 周日 下午

本次实验是关于C语言学生信息管理系统的设计与实现。在本次实验中,我采用了以下的实现思路: 1. 定义结构体类型,包括学生姓名、学号、性别、年龄等基本信息。 2. 设计文件操作函数,包括读取学生信息、保存学生信息等操作。 3. 设计菜单函数,包括添加学生、删除学生、修改学生信息、查询学生信息等选项。 4. 设计主函数,通过调用菜单函数实现学生信息管理系统的主要功能。 5. 在程序中使用指针,对学生信息进行存储和操作。 6. 在程序中使用模块化设计,将不同的功能模块分离出来,提高程序的可读性和可维护性。 首先,我定义了一个结构体类型,用来存储学生的基本信息,包括姓名、学号、性别和年龄。在定义结构体类型时,我采用了typedef关键字,将结构体类型定义为一个新的数据类型,方便后续的使用。 接着,我设计了文件操作函数,包括读取学生信息和保存学生信息。在读取学生信息时,我采用了fgets函数,一次读取一行,然后使用sscanf函数将读取的字符串转换为相应的数据类型。在保存学生信息时,我采用了fprintf函数,将学生信息逐行写入文件中。 然后,我设计了菜单函数,包括添加学生、删除学生、修改学生信息、查询学生信息等选项。在每个选项中,我都使用了指针来对学生信息进行操作,并且在操作完成后,将学生信息保存到文件中。 最后,我设计了主函数,通过调用菜单函数实现学生信息管理系统的主要功能。在主函数中,我首先读取已有的学生信息,然后进入菜单循环,等待用户输入选项。用户可以通过菜单选项来添加、删除、修改和查询学生信息,直到用户选择退出程序为止。 通过这次实验,我深入了解了C语言中结构体、指针、文件操作等基本知识,并且掌握了C语言程序模块化设计的方法,提高了程序的可读性和可维护性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值