【问题标题】:C++ formatted input must match valueC++ 格式化输入必须匹配值
【发布时间】:2012-04-03 15:08:14
【问题描述】:

我正在用 C++ 读取文件;文件看起来像:

tag1 2345
tag2 3425
tag3 3457

我想要类似的东西

input>>must_be("tag1")>>var1>>must_be("tag2")>>var2>>must_be("tag3")>>var3;

如果接收的内容与 must_be() 的参数不匹配,那么一切都会爆炸,完成后,var1=2345, var2=3425, var3=3457

有这样做的标准方法吗? (希望“tag1”不一定是字符串,但这不是必需的。)来自 C 的 fscanf 让它变得非常容易。

谢谢!

为了澄清,每个>>input 中读取一组以空格分隔的字符。我想将一些传入的字符块 (tagX) 与我指定的字符串或数据进行匹配。

【问题讨论】:

    标签: c++ iostream


    【解决方案1】:

    您需要为您的班级实施operator>>。像这样的:

    #include <string>
    #include <iostream>
    #include <fstream>
    #include <sstream>
    
    struct A
    {
        A(const int tag_):tag(tag_),v(0){}
    
        int tag;
        int v;
    };
    
    #define ASSERT_CHECK( chk, err ) \
            if ( !( chk ) ) \
                throw std::string(err);
    
    std::istream& operator>>( std::istream & is, A &a )
    {
        std::string tag;
        is >> tag;
        ASSERT_CHECK( tag.size() == 4, "tag size" );
        std::stringstream ss(std::string(tag.begin()+3,tag.end()));
        int tagVal;
        ss >> tagVal;
        std::cout<<"tag="<<tagVal<<"  a.tag="<<a.tag<<std::endl;
        ASSERT_CHECK( a.tag == tagVal,"tag value" );
    
        is >> a.v;
        return is;
    }
    
    int main() {
        A a1(1);
        A a2(2);
        A a3(4);
    
        try{
            std::fstream f("in.txt" );
            f >> a1 >> a2 >> a3;
        }
        catch(const std::string &e)
        {
            std::cout<<e<<std::endl;
        }
    
        std::cout<<"a1.v="<<a1.v<<std::endl;
        std::cout<<"a2.v="<<a2.v<<std::endl;
        std::cout<<"a3.v="<<a3.v<<std::endl;
    }
    

    注意,标签值错误会抛出异常(表示标签高度匹配)。

    【讨论】:

    • 但是您知道执行此操作的标准(库/增强)方式吗?
    • @Richard 这是一种标准的做法。只需为您的班级实施operator&gt;&gt; 就可以了。 boost 不为自定义类提供 operator>>
    【解决方案2】:

    你不能逐行阅读,并为每一行匹配标签吗?如果标签与您期望的不匹配,您只需跳过该行并继续下一行。

    类似这样的:

    const char *tags[] = {
        "tag1",
        "tag2",
        "tag3",
    };
    int current_tag = 0;  // tag1
    const int tag_count = 3;  // number of entries in the tags array
    
    std::map<std::string, int> values;
    
    std::string line;
    while (current_tag < tag_count && std::getline(input, line))
    {
        std::istringstream is(line);
    
        std::string tag;
        int value;
        is >> tag >> value;
    
        if (tag == tags[current_tag])
            values[tag] = value;
        // else skip line (print error message perhaps?)
    
        current_tag++;
    }
    

    【讨论】:

    • 但是您知道执行此操作的标准(库/增强)方式吗?
    • @Richard 也许是Boost.spirit?
    猜你喜欢
    • 2016-08-11
    • 2017-10-17
    • 2015-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-16
    • 2011-11-22
    • 2019-03-28
    相关资源
    最近更新 更多