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)));
}