【问题标题】:Getline to read data from txt fileGetline 从 txt 文件中读取数据
【发布时间】:2018-11-01 10:52:48
【问题描述】:

我在使用 getline 命令从简单的 .txt 文件中提取数据时遇到了一点问题。

txt 文件非常简单:一列 400 个数字。我使用向量来存储它们,代码如下:

int i = 0;
string line;
vector <double> vec;

while (getline(input, line))
{
    vec.push_back(i);
    N++;
    input >> vec[i];
    i++;
} 

它正确创建了一个包含 400 个元素的向量,但 txt 文件的第一行被忽略(我最终得到 vec[0] = txt 文件的第 2 行而不是第 1 行),第 399 个元素是 399 而不是 txt 的第 400 行文件。

我尝试了其他几种方法来提取此数据,但均未成功。

感谢您的帮助!

编辑:

我根据一些备注编辑了代码:

vector <double> vec;
string line;
double num;

while (getline(input, line))
{
    input >> num;
    vec.push_back(num);
}

不幸的是,它仍然跳过了我的文本文件的第一行。

编辑 2 --> 解决方案:

感谢您的所有评论,我意识到我在同时使用 getline 和 input >> num 时做错了;

问题的解决方法如下:

double num;
vector <double> vec;

while (input >> num)
{
    vec.push_back(num);
}

【问题讨论】:

  • 可能相关/欺骗,但我们需要minimal reproducible example t 确认:stackoverflow.com/questions/21567291/…
  • i 未定义。你有什么理由不push_back 只是line 的内容?
  • i 在 while (int i = 0) 之前定义。至于 push_back,它并没有完全解决我的问题,因为我仍然丢失了数据文件的第一行。
  • while (input &gt;&gt; i) vec.push_back(i);
  • 我已经用变量声明更新了代码。

标签: c++ getline istream


【解决方案1】:

您只需将std::istream_iterator 传递给std::vector 构造函数,就可以将整个文件读入向量,无需循环:

std::vector<int> v{
    std::istream_iterator<int>{input}, 
    std::istream_iterator<int>{}
};

例如:

#include <iostream>
#include <iterator>
#include <vector>
#include <exception>

template<class T>
std::vector<T> parse_words_into_vector(std::istream& s) {
    std::vector<T> result{
        std::istream_iterator<T>{s},
        std::istream_iterator<T>{}
    };
    if(!s.eof())
        throw std::runtime_error("Failed to parse the entire file.");
    return result;
}

int main() {
    auto v = parse_words_into_vector<int>(std::cin);
    std::cout << v.size() << '\n';
}

【讨论】:

  • 哇——太酷了。会不会抛出和stod一样的异常?
  • @Einsiedler 你有什么困难?
  • @MaximEgorushkin BTW:OP 已将向量更改为加倍。以防万一您想更新答案
【解决方案2】:

由于再次从文件中读取,您丢失了第一行 - 此处:

while (getline(input, line))
    // ^^^^^^^ Here you read the first line
{
    input >> num;
 // ^^^^^^^^ Here you will read the second line

你告诉过你想要一个双精度向量 - 比如:

std::vector<double> vec;

所以您应该使用std::stodgetline 读取的行转换为双精度。喜欢:

while (std::getline(input, line))
{
    // Convert the text line (i.e. string) to a floating point number (i.e. double)
    double tmp;
    try
    {
        tmp = stod(line);
    }
    catch(std::invalid_argument)
    {
        // Illegal input
        break;
    }
    catch(std::out_of_range)
    {
        // Illegal input
        break;
    }

    vec.push_back(tmp);
} 

不要在循环内执行input &gt;&gt; num;

如果你真的想使用input &gt;&gt; num;,那么你应该不要使用getline。也就是说 - 您可以使用其中一个,但不能同时使用。

【讨论】:

  • 其实是double的向量。
  • 我用更有意义的代码编辑了原始帖子,因此我不需要转换。它仍然跳过第一行:(
  • @Einsiedler:抱歉,新代码没有“更有意义”。 不要input &gt;&gt; num;你已经已经getline读取了文件的第一行。所以你松开了第一行。试试我的建议。
  • @Einsiedler 我对您的方法的问题添加了一些额外的解释。希望对您有所帮助。
  • 非常感谢您的发言。我理解得更清楚,但不幸的是,没有定义 stod(尽管包括所有库),所以它在这里不起作用。
【解决方案3】:

改变你的while循环如下:-

while (getline(input, line))
{
    vec.push_back(line);
    //N++;
    //input >> vec[i];
    //i++;
} 

也可以试试下面的选项

 do{
    vec.push_back(i);
    //N++;
    //i++;
 }while (input >> vec[i++]);

【讨论】:

  • 带字符串的 push_back?这很奇怪......它实际上给了我一个错误:错误:无法在当前范围内调用vector >::push_back(line)
  • 你应该像vector一样声明你的向量
  • 这样做仍然给我同样的问题,除了这一次,第 399 个元素是空的。我还是错过了txt文件的第一行。
  • 在将其添加到矢量并检查之前只需打印行。可能您在代码的某处阅读了第一行。在你的 while 循环之前添加几行
  • 我在答案中添加了一个 do while 循环选项。试试这个
【解决方案4】:

您首先在第一次迭代中将 0 放入向量中:

vec.push_back(i);

然后在你读取第一行之后你读取下一个字符串,但是从文件中获取的流指针已经在不同的位置,所以你覆盖这个 0 并从流中跳过第一个值。更糟糕的是奇怪地转换为双精度:

input >> vec[i];

这样你就会出错。 试试这个:

while (std::getline(file, line)) {
    //In c++11
    vec.emplace_back(std::stod(line));
    //In c++ 98, #include <stdlib.h> needed
    //vec.push_back(atof(line.c_str())); 
}

这假设您将始终拥有正确的文件。

【讨论】:

  • 感谢您的评论,我已经编辑了我的帖子。你能告诉我这是否真的改变了你的言论吗?
猜你喜欢
  • 2013-10-14
  • 1970-01-01
  • 2016-07-29
  • 1970-01-01
  • 2012-02-08
  • 2023-03-26
  • 1970-01-01
  • 2021-10-25
  • 1970-01-01
相关资源
最近更新 更多