免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 6967 | 回复: 11
打印 上一主题 下一主题

讨论一下和sscanf完全等价的最简单sstream实现 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-04-30 05:01 |只看该作者 |倒序浏览
本帖最后由 numdisp 于 2010-04-30 05:30 编辑

如果不用sscanf,不用任何C的库,只用所谓“纯C++”的标准流库(或者加上其它"纯C++"的标准库),sscanf的等价实现怎样才能最简洁(包括写法和执行效率)?

譬如

char sz[] = "1, 2,3.14,,";
int m, n;
float x;

要正确从sz中提取m, n, x的话,用sscanf只要 sscanf(sz, "%d,%d,%f", &m, &n, &x) 就行了。

如果只用流库和 >> 操作符的话,怎么才能简单一点呢?


方法1. 简单地替换sz中所有的","为空格:

这个方法不等价,举例:如果 sz[] = “1, ,2,3.14”,sscanf会出错,而替换后的字符串为"1  2 3.14",用stringstream ss >> m >> n >> x不会出错。

方法2. 用ignore方法:

istringstream ss(sz);
ss >> m;
ss.ignore(1, ',');
ss >> n;
ss.ignore(1, ',');
ss >> x;

if (ss.fail())
{
    cerr << "Error occurred!\n";
}

这个方法也不等价,举例:sz[] = "1 2 3.14",sscanf会出错,而方法2不出错。


方法3. 把 m, n, x 封装到一个struct里,或者class里,然后重载>>操作符。但是这样凭空多了一个class,而且离散的变量多一点的话,就更不方便了。


还有一个问题,就是sscanf可以通过判断返回值来确定有几个数已经被成功读入了,这个用sstream的话好像不太好办。

有没有什么简单而又高效一点的方法?这里“等价”的含义仅包括对字符串sz的处理(包括成功或失败时的行为,当然抛出异常和返回错误代码之类的区别是忽略的)。

纯讨论而已,认为没有意义或者说“既然可以用sscanf为什么不用”的人就不劳烦您回帖了。

论坛徽章:
0
2 [报告]
发表于 2010-04-30 07:31 |只看该作者
用C++不用Boost::regex库处理输入,不如不用C++。对了现在应该叫std::tr1:regex库了。

论坛徽章:
0
3 [报告]
发表于 2010-04-30 07:35 |只看该作者
很多编译器还没有 tr1 吧?

论坛徽章:
0
4 [报告]
发表于 2010-05-01 00:26 |只看该作者
很多编译器还没有 tr1 吧?
numdisp 发表于 2010-04-30 07:35



    随着C++0x/1x标准的接近,这世界上已经没有很多C++编译器了。目前几巨头是:GCC, M$VC++, Intel C++, LLVM-clang. 其他的可以无视,近几年内能实现C++0x/1x标准的可能性太低。
如果你不是一个怀旧主义者的话,不用担心很多编译器不支持tr1,因为主流的都支持。

论坛徽章:
0
5 [报告]
发表于 2010-05-01 02:10 |只看该作者
那用正则表达式如何弄,可否写个例子?

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
6 [报告]
发表于 2010-05-01 05:35 |只看该作者
\s*(\d+),\s*(\d+),\s*((?:\d+|\.\d+|\d*\.(?:\d*)?)(?:[eE][+-]?\d+)?)

差不多就是这样子的。pcre。其实很简单的,%d替换成\s*(\d+),%c替换成.,%s替换成\s*(\S+),%f替换成上面一大串很复杂的东西(主要是浮点数的格式太多了,不好判断),差不多就是这样子了。正则看上去复杂,用起来还是蛮方便的。


另外求与上面一大串等价的浮点数正则实现。注意以下形式都应该通过:
1
1.
.1
1.1
1e1
1.e1
.1e1
1.1e1

论坛徽章:
0
7 [报告]
发表于 2010-05-01 05:36 |只看该作者
用C++的东西,和C的东西比较,有意思吗?

论坛徽章:
0
8 [报告]
发表于 2010-05-01 05:42 |只看该作者
回复 6# starwing83

正则倒是了解一些,但是这写法要维护起来……

算了,还是老老实实 sscanf 吧,怎么感觉C++老是要把简单的东西复杂化呢?难道以前说的C++发明只是为了提高程序员薪水的传说是真的?

论坛徽章:
0
9 [报告]
发表于 2010-05-01 05:47 |只看该作者
用正规式来处理输入,可以在很大程度上杜绝黑客的字串构造攻击。你自己写C/C++代码分析字串,工作量大不说,难免有疏忽遗漏的情况。学习一点正规表达式,用成熟的库来分析输入,效率和可靠性都要好上不少。

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
10 [报告]
发表于 2010-05-01 05:56 |只看该作者
回复 8# numdisp


    维护起来很方便,const string,用的时候直接构造即可。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP