有很多种方法可以实现这个功能。你尝试的方法不起作用,因为在读取位置上没有类似数字的东西。输入操作将失败,并且流的故障位将被设置。您将一直循环,因为您仅测试了eof。阅读此文以获取更多信息。
一个简单的方法是逐行读取,并通过利用std::strtol
的第二个参数来查找第一个数字:
#include <iostream>
#include <string>
#include <experimental/optional>
std::experimental::optional<int> find_int_strtol( const std::string & s )
{
for( const char *p = s.c_str(); *p != '\0'; p++ )
{
char *next;
int value = std::strtol( p, &next, 10 );
if( next != p ) {
return value;
}
}
return {};
}
int main()
{
for( std::string line; std::getline( std::cin, line ); )
{
auto n = find_int_strtol( line );
if( n )
{
std::cout << "Got " << n.value() << " in " << line << std::endl;
}
}
return 0;
}
这个方法有些繁琐,也会检测到负数,可能不是你想要的。但这是一种简单的方法。如果提取了任何字符,则“下一个”指针将与“p”不同。否则,函数失败。然后你通过加1来增加“p”,再次搜索。它看起来像一个多项式搜索,但它是线性的。
我使用了C++17中的std::optional,但我在C++14编译器上进行测试。这是为了方便。你可以不用它来编写该函数。
现场演示
在这里。
解决此类问题的更灵活的方法是使用正则表达式。在这种情况下,一个简单的数字正则表达式搜索就足够了。以下代码只会找到正整数,但你也可以使用这种类型的模式来查找复杂数据。不要忘记包含头文件:
std::experimental::optional<int> find_int_regex( const std::string & s )
{
static const std::regex r( "(\\d+)" );
std::smatch match;
if( std::regex_search( s.begin(), s.end(), match, r ) )
{
return std::stoi( match[1] );
}
return {};
}
这里有实时示例is here。
123
),因此正则表达式比其他类型的读取更简单,尽管stoi
通常会从字符串前面提取尽可能多的整数,所以结果可能有所不同。 - AndyG