Safer but easy-to-use and flexible C++ alternative to sscanf()(更安全但易于使用且灵活的 C++ 替代 sscanf())
问题描述
当我需要从一堆字符串中扫描值时,我经常发现自己完全回到了 C 的 sscanf() ,因为它的简单性和易用性.例如,我可以非常简洁地从字符串中提取几个双精度值:
When I need to scan in values from a bunch of strings, I often find myself falling back to C's sscanf() strictly because of its simplicity and ease of use. For example, I can very succinctly pull a couple double values out of a string with:
string str;
double val1, val2;
if (sscanf(str.c_str(), "(%lf,%lf)", &val1, &val2) == 2)
{
// got them!
}
这显然不是 C++.我不一定认为这是可憎的,但我一直在寻找一种更好的方法来完成一项共同的任务.我知道读取字符串的C++ 方式"是 istringstream,但是在上面的格式字符串中处理括号和逗号所需的额外输入只会让我想使用它太麻烦了.
This obviously isn't very C++. I don't necessarily consider that an abomination, but I'm always looking for a better way to do a common task. I understand that the "C++ way" to read strings is istringstream, but the extra typing required to handle the parenthesis and comma in the format string above just make it too cumbersome to make me want to use it.
是否有一种好方法可以以类似于上述的方式使内置设施符合我的意愿,或者是否有一个好的 C++ 库以更类型安全的方式执行上述操作?看起来Boost.Format确实很好地解决了输出问题,但我还没有找到任何类似简洁的输入.
Is there a good way to either bend built-in facilities to my will in a way similar to the above, or is there a good C++ library that does the above in a more type-safe way? It looks like Boost.Format has really solved the output problem in a good way, but I haven't found anything similarly succinct for input.
推荐答案
我编写了一些可以读取字符串和字符文字的代码.像普通的流读取一样,如果它得到无效数据,它会设置流的坏位.这应该适用于所有类型的流,包括宽流.将此位粘贴到新标题中:
I wrote a bit of code that can read in string and character literals. Like normal stream reads, if it gets invalid data it sets the badbit of the stream. This should work for all types of streams, including wide streams. Stick this bit in a new header:
#include <iostream>
#include <string>
#include <array>
#include <cstring>
template<class e, class t, int N>
std::basic_istream<e,t>& operator>>(std::basic_istream<e,t>& in, const e(&sliteral)[N]) {
std::array<e, N-1> buffer; //get buffer
in >> buffer[0]; //skips whitespace
if (N>2)
in.read(&buffer[1], N-2); //read the rest
if (strncmp(&buffer[0], sliteral, N-1)) //if it failed
in.setstate(in.rdstate() | std::ios::failbit); //set the state
return in;
}
template<class e, class t>
std::basic_istream<e,t>& operator>>(std::basic_istream<e,t>& in, const e& cliteral) {
e buffer; //get buffer
in >> buffer; //read data
if (buffer != cliteral) //if it failed
in.setstate(in.rdstate() | std::ios::failbit); //set the state
return in;
}
//redirect mutable char arrays to their normal function
template<class e, class t, int N>
std::basic_istream<e,t>& operator>>(std::basic_istream<e,t>& in, e(&carray)[N]) {
return std::operator>>(in, carray);
}
它会让输入字符变得非常容易:
And it will make input characters very easy:
std::istringstream input;
double val1, val2;
if (input >>'('>>val1>>','>>val2>>')') //less chars than scanf I think
{
// got them!
}
概念证明.现在您可以 cin 字符串和字符文字,如果输入不是完全匹配,它的行为就像任何其他未能正确输入的类型.请注意,这仅匹配不是第一个字符的字符串文字中的空格.只有四个功能,都是脑残的简单.
PROOF OF CONCEPT. Now you can cin string and character literals, and if the input is not an exact match, it acts just like any other type that failed to input correctly. Note that this only matches whitespace in string literals that aren't the first character. It's only four functions, all of which are brain-dead simple.
用流解析是个坏主意.使用正则表达式.
Parsing with streams is a bad idea. Use a regex.
这篇关于更安全但易于使用且灵活的 C++ 替代 sscanf()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:更安全但易于使用且灵活的 C++ 替代 sscanf()
基础教程推荐
- 如何将 std::pair 的排序 std::list 转换为 std::map 2022-01-01
- C++结构和函数声明。为什么它不能编译? 2022-11-07
- 如何在 C++ 中初始化静态常量成员? 2022-01-01
- 常量变量在标题中不起作用 2021-01-01
- 如何检查GTK+3.0中的小部件类型? 2022-11-30
- 我有静态或动态 boost 库吗? 2021-01-01
- 如何通过C程序打开命令提示符Cmd 2022-12-09
- 静态库、静态链接动态库和动态链接动态库的 .lib 文件里面是什么? 2021-01-01
- 在 C++ 中计算滚动/移动平均值 2021-01-01
- 这个宏可以转换成函数吗? 2022-01-01
