【发布时间】:2015-03-01 14:15:47
【问题描述】:
我有一个如下所示的字符串:
水平分级:4
我将整行存储为字符串,并且可以使用 linestring[30] 之类的方法访问数字 4,其中 linestring 是整行存储为的字符串。我试图以整数而不是字符串的形式访问数字 4。我怎样才能做到这一点?我曾尝试使用 atoi(linestring[30].c_str());但这不喜欢对线串有参数。我无法使用 boost 等外部库。我该怎么做?
【问题讨论】:
我有一个如下所示的字符串:
水平分级:4
我将整行存储为字符串,并且可以使用 linestring[30] 之类的方法访问数字 4,其中 linestring 是整行存储为的字符串。我试图以整数而不是字符串的形式访问数字 4。我怎样才能做到这一点?我曾尝试使用 atoi(linestring[30].c_str());但这不喜欢对线串有参数。我无法使用 boost 等外部库。我该怎么做?
【问题讨论】:
使用substr 代替operator[]。它会给你另一个std::string,而不是char。然后使用std::stoi将字符串转换为整数。
或者,使用从operator[] 返回的char 创建一个新的std::string 以应用std::stoi。
在 C++11 之前的版本中,使用 std::istringstream 而不是 std::stoi。
顺便说一句,远离atoi。如果"0" 应该是有效输入,则无法进行错误检查。
【讨论】:
对于更通用的方法,您在表单中有对:
foo: <number>
你可以这样使用:
std::string s = "Horizontal Binning: 4";
size_t pos = s.find_last_of(':');
if(pos != std::string::npos)
{
int num;
std::stringstream(s.erase(0, pos + 1)) >> num;
std::cout << "num = " << num << std::endl;
}
else // give error here
【讨论】:
find_last_of 在这里可能会更好:)
你可以使用
int value = atoi(linestring.c_str() + 30);
但您必须确保字符串至少有 30 个字符,否则这将意味着未定义的行为。
【讨论】:
"Horizontal Binning: 0" 并且错误检查应该检测到像 "Horizontal Binning: x" 这样的错误输入,这将不起作用,因为 atoi 为转换错误返回 0。所以没有办法区分有效零和由转换错误引起的零。
如果您不知道数字前的文本有多长,您可以简单地循环直到找到一个数字并从那里调用 atoi:
auto it = begin(str);
while (it != end(str) && !isdigit(*it))
++it;
cout << atoi(&*it) << endl;
【讨论】:
由于这是 C++ 并且您使用的是 std::string,因此请使用 stoi 而不是 atoi。这是一个受Innocent Bystander 的回答启发的通用解决方案。
找到:在字符串中的位置,然后解析int:
size_t start = linestring.find_last_of(':') + 1;
int i = std::stoi(linestring.substr(start));
你甚至可以把它做成单线。
或者如果你知道这个数字永远只有一位,而且它是字符串中的最后一个字符:
int i = linestring.back() - '0';
【讨论】:
另一个选项是sscanf,它尝试匹配一个模式:
#include <cstdio>
#include <string>
void Extract(const std::string& s) {
int value = 0;
int r = sscanf(s.c_str(), "Horizontal Binning: %d", &value);
if (r == 1) {
printf("value is %d\n", value);
} else {
printf("cannot extract value\n");
}
}
int main() {
Extract("Horizontal Binning: 4");
Extract("Whatever: 4");
}
输出是:
value is 4
cannot extract value
【讨论】: