C++ 从字符串中提取特定对象

C++ 从字符串中提取特定对象,c++,string,c++11,substring,stdstring,C++,String,C++11,Substring,Stdstring,我有一个格式为的字符串,它表示有向图中的一条边(a是源,b是目标)a和b本身也是字符串(例如,a可以是“正方形”,b是“圆形”) 我需要构建一个提取a的函数,以及另一个提取b的函数。因此,签名将是: stringgetsource(字符串边缘)//将返回b 字符串getTarget(字符串边缘)//将返回一个 我正在使用std::string库来表示这些字符串 我知道我需要找到一种方法来找到,'< /> >在字符串的中间分隔它们,并去掉 '。但是我在std::string中找不到有助于我实现这

我有一个格式为
的字符串,它表示有向图中的一条边(
a
是源,
b
是目标)
a
b
本身也是字符串(例如,
a
可以是
“正方形”
b
“圆形”

我需要构建一个提取
a
的函数,以及另一个提取
b
的函数。因此,签名将是:

stringgetsource(字符串边缘)//将返回b
字符串getTarget(字符串边缘)//将返回一个
我正在使用
std::string
库来表示这些字符串

<>我知道我需要找到一种方法来找到<代码>,'< /> >在字符串的中间分隔它们,并去掉<代码> '<代码>。但是我在
std::string
中找不到有助于我实现这一点的函数


您将如何继续执行此操作?

如果您确定字符串的格式正确,则只需使用查找感兴趣的字符,然后从这些迭代器构造新字符串即可。例如:

std::string getSource(std::string const & edge) {
    return {
        std::next(std::find(std::begin(edge), std::end(edge), '<')),
        std::find(std::begin(edge), std::end(edge), ',')
    };
}

std::string getTarget(std::string const & edge) {
    return {
        std::next(std::find(std::begin(edge), std::end(edge), ',')),
        std::find(std::begin(edge), std::end(edge), '>')
    };
}
std::string getSource(std::string const&edge){
返回{
标准::下一步(标准::查找(标准::开始(边缘),标准::结束(边缘),“”)
};
}
如果字符串格式不正确,则这些函数可能会表现出未定义的行为。这可以通过使用辅助函数轻松解决:

template <typename T>
std::string checkedRangeToString(T begin, T end) {
    if (begin >= end) {
        // Bad format... throw an exception or return an empty string?
        return "";
    }

    return {begin, end};
}

std::string getSource(std::string const & edge) {
    return checkedRangeToString(
        std::next(std::find(std::begin(edge), std::end(edge), '<')),
        std::find(std::begin(edge), std::end(edge), ',')
    );
}

std::string getTarget(std::string const & edge) {
    return checkedRangeToString(
        std::next(std::find(std::begin(edge), std::end(edge), ',')),
        std::find(std::begin(edge), std::end(edge), '>')
    );
}
模板
std::string checkedRangeToString(T开始,T结束){
如果(开始>=结束){
//格式错误…引发异常或返回空字符串?
返回“”;
}
返回{开始,结束};
}
std::string getSource(std::string const&edge){
返回checkedRangeToString(
标准::下一步(标准::查找(标准::开始(边缘),标准::结束(边缘),“”)
);
}

这似乎是一个很好的正则表达式用例:

std::regex sd {R"(<(.*),(.*)>)"};

getTarget
中,您将返回
m[2].str();

这听起来像是它属于一个类,其构造函数接受该
std::string
参数并对其进行解析

class edge {
public:
    edge(const std::string& str);
    std::string source() const { return src; }
    std::string target() const { return tgt; }
private:
    std::string src;
    std::string tgt;
};

edge::edge(const std::string& str) {
    auto comma = std::find(std::begin(str), std::end(str), ',');
    if (str.length() < 3 || comma == std::end(str) || str.front() != '<' || str.back() != '>')
        throw std::runtime_error("bad input");
    src = std::string(std::next(std::begin(str)), comma);
    tgt = std::string(std::next(comma), std::prev(std::end(str)));
}
类边缘{
公众:
边(常量std::string和str);
std::string source()常量{return src;}
std::string target()常量{return tgt;}
私人:
std::字符串src;
std::字符串tgt;
};
边缘::边缘(常量std::字符串和str){
自动逗号=std::find(std::begin(str),std::end(str),,);
如果(str.length()<3 | |逗号==std::end(str)| | str.front()!=“”)
抛出std::运行时_错误(“错误输入”);
src=std::string(std::next(std::begin(str)),逗号);
tgt=std::string(std::next(逗号),std::prev(std::end(str));
}
我不会使用正则表达式进行如此简单的解析。正则表达式代价高昂,而且被高估了。

“a是源代码,b是目标”,但
getSource()
返回b,而
getTarget()
返回a!?对于简单的情况,和应该是所有需要的。签名“String”应该是“String”。另外,“使用名称空间std;”不是一个好习惯。
class edge {
public:
    edge(const std::string& str);
    std::string source() const { return src; }
    std::string target() const { return tgt; }
private:
    std::string src;
    std::string tgt;
};

edge::edge(const std::string& str) {
    auto comma = std::find(std::begin(str), std::end(str), ',');
    if (str.length() < 3 || comma == std::end(str) || str.front() != '<' || str.back() != '>')
        throw std::runtime_error("bad input");
    src = std::string(std::next(std::begin(str)), comma);
    tgt = std::string(std::next(comma), std::prev(std::end(str)));
}