有没有一种方便的方法来解析c ++中string::iterator
的整数?对于这个特定问题,我只关心非负基10整数,但所有这些解都可以很容易地扩展到任意整数。注意,与similar questions不同,我没有引用原始字符串,只有一个迭代器,例如
int parse_next_int(std::string::iterator begin, std::string::iterator end) {
// ...
}
我可以想到很多方法,但没有一种方法很棒。另一个注意事项,我没有声明stl标题,我假设所有内容都在std
命名空间中完成。希望这不会使示例太难以解析。
分配一个新字符串,然后调用stoi:
int parse_next_int(string::iterator begin, string::iterator end) {
string::iterator num_end = find_if(
begin, end, [](char c)->bool{return !isdigit(c);});
string to_parse(begin, num_end);
return stoi(to_parse);
}
这样做的缺点是我最终会为可能在运行中解析的东西分配一个新的缓冲区。
不安全地将其视为c字符串。
int parse_next_int(std::string::iterator begin, std::string::iterator end) {
return atoi(&(*begin));
}
这有点起作用,但是如果它到达字符串的末尾并且它不是空终止(这不是c ++字符串保证)它会段错误,所以虽然简洁,但这可能是最糟糕的。
自己写一下:
int parse_next_int(std::string::iterator begin, std::string::iterator end) {
int result = 0;
while (begin != end && isdigit(*begin)) {
result = result * 10 + (*begin++ - '0');
}
return result;
}
这很有用,而且很简单,但它也很大程度上依赖于问题而且不容错。
是否有一些显着不同的方法,主要依赖于更宽容的stl调用,同时仍然很简单并避免复制不必要的缓冲区?
答案 0 :(得分:3)
如果你有权使用提升,你可以使用:
int parse_next_int(std::string::iterator begin, std::string::iterator end) {
return boost::lexical_cast<int>(&(*begin), std::distance(begin, end));
}
答案 1 :(得分:1)
std::string
。std::istringstream
。string
istringstream
。int parse_next_int(std::string::iterator begin, std::string::iterator end) {
std::string s(begin, end);
std::istringstream str(s);
int i;
str >> i;
return i;
}
PS 添加错误处理代码,使其值得生产。
答案 2 :(得分:1)
不要使用atoi
,如果数字超过INT_MAX
,则会导致未定义的行为。您的选项3也存在同样的问题。
我的建议是:
find_if
或strchr
或其他任何方法查找号码的结尾;如果您愿意,可以提前-
或+
。strtol
进行转换,使用代码处理所有溢出情况。关于空终止,您可以选择以下之一:
end
实际上不是字符串的结尾,则在那里写一个临时的空终止符,然后恢复旧字符。答案 3 :(得分:0)
请注意,由于C ++ 11,std::string
s 保证是以空值终止的,因此您的解除引用和处理为aC-string的解决方案并不安全所有;并且,通过评论解释发生了什么,我将投票支持这个问题的最佳解决方案。