更安全,但易于使用和灵活的C ++替代sscanf() [英] Safer but easy-to-use and flexible C++ alternative to sscanf()

查看:1150
本文介绍了更安全,但易于使用和灵活的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.

推荐答案

我写了一些代码,可以读取字符串和字符文字。像正常的流读取,如果它获取无效的数据,它设置流的badbit。这应该适用于所有类型的流,包括宽流。将此位置于新标头中:

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()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆