【问题标题】:C++ ifstream read only number of a wordC++ ifstream 只读一个单词的数量
【发布时间】:2017-05-10 23:09:27
【问题描述】:

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

文件.txt:

hello 123-abc
world 456-def

当前代码:

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

现在这显然行不通,我已经尝试解决这个问题“一段时间”,但我无法解决这个问题。

【问题讨论】:

  • 所以你想忽略任何可能不是数字的东西?尝试读入一个字符串。然后使用正则表达式匹配字符串,并从正则表达式的匹配组中获取数字。迷茫了吗? :-) 正则表达式无疑比其他类型的阅读更简单,因为像123 这样的连续字符系列,尽管stoi 通常会从字符串前面拉出尽可能多的整数,所以 YMMV
  • while(!file.eof()) 没有做你认为的事情

标签: c++ fstream ifstream


【解决方案1】:

有很多方法可以做到这一点。您尝试过的方法不起作用,因为流中的读取位置没有类似数字的东西。所以输入会失败,流的fail-bit会被设置。您将永远循环,因为您只是在测试 eofRead this 了解更多信息。

一种简单的方法是一次读取一行,并通过利用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;
}

这有点笨拙,它还会检测你可能不想要的底片。但这是一种简单的方法。如果提取了任何字符,next 指针将不同于 p。否则函数失败。然后将p 增加1 并再次搜索。它看起来像多项式搜索,但它是线性的。

我使用了 C++17 中的 std::optional,但我在 C++14 编译器上进行测试。是为了方便。没有它你也可以编写函数。

现场示例is here

解决此类问题的一种更灵活的方法是使用正则表达式。在这种情况下,您只需要一个简单的数字正则表达式搜索。以下只会找到正整数,但您也可以使用这种类型的模式来查找复杂数据。不要忘记包含标题&lt;regex&gt;

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

【讨论】:

    【解决方案2】:

    您需要检查文件是否打开,然后获取当前行,然后解析当前行以获取第一个数字:

    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); 获取子字符串来查找下一个空格

    我相信你能弄清楚剩下的,祝你好运。

    【讨论】:

    • 你怎么知道数字前面总会出现一个空格?
    • 我不认为这是此示例中的标准,因为他显示了两条相同的行,但只要文件中数字前后有空格,概念就相同。获取一个子字符串,看看它是否可以转换为一个 int,如果不能,则尝试下一个 substr,依此类推。
    【解决方案3】:

    逐行读取并删除所有非数字字符。在推送到您的 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));
    

    Live example

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多