C++ ifstream 读取一个单词的数字

4
所以我想从一个 .txt 文件中读取数字作为整数。

file.txt:

hello 123-abc
world 456-def

当前代码:
int number;
ifstream file("file.txt");
while (!file.eof())
{
    file >> number; //123, 456
}

现在显然这不起作用,我一直在尝试解决这个问题,但我就是无法解决。

所以你想忽略任何可能不是数字的东西?尝试读入一个字符串。然后使用正则表达式匹配该字符串,并从正则表达式的匹配组中获取数字。还感到困惑吗? :-) 由于连续的字符系列(如123),因此正则表达式比其他类型的读取更简单,尽管stoi通常会从字符串前面提取尽可能多的整数,所以结果可能有所不同。 - AndyG
1
while(!file.eof())并不像你想的那样工作。 - pm100
3个回答

1

有很多种方法可以实现这个功能。你尝试的方法不起作用,因为在读取位置上没有类似数字的东西。输入操作将失败,并且流的故障位将被设置。您将一直循环,因为您仅测试了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


0
你需要检查文件是否已打开,然后获取当前行,接着解析该行以获取第一个数字:
std::string currentLine = "";
std::string numbers = "";
ifstream file("file.txt");
if(file.is_open())
{
    while(std::getline(file, currentLine))
    {
        int index = currentLine.find_first_of(' '); // look for the first space
        numbers = currentLine.substr(index + 1, xyz);
    }
} 

xyz是数字的长度(如果始终不变,则在此情况下为3),或者您可以通过从(index, currentLine.back() - index);获取子字符串来查找下一个空格。

我相信你可以解决剩下的部分,祝你好运。


你怎么知道这个数字前面总会有一个空格出现? - paddy
我不确定这是否是一个标准例子,因为他展示了两行相同的代码,但只要文件中数字前后有空格,这个概念就是一样的。获取一个子字符串,查看能否转换成整数,如果不能,则尝试下一个子字符串,依此类推。 - Omar Martinez

0
逐行读取并删除所有非数字字符。在将其推入您的std::vector之前,最后使用std::stoi函数完成转换。
std::ifstream file{"file.txt"};
std::vector<int> numbers;

for (std::string s; std::getline(file, s);) {
    s.erase(std::remove_if(std::begin(s), std::end(s),
        [] (char c) { return !::isdigit(c); }), std::end(s));
    numbers.push_back(std::stoi(s));
}

或者使用std::regex_replace来删除非数字字符:

auto tmp = std::regex_replace(s, std::regex{R"raw([^\d]+(\d+).+)raw"}, "$1");
numbers.push_back(std::stoi(tmp));

实时示例


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接