【问题标题】:How do you read a text file into a vector in c++?如何在 C++ 中将文本文件读入向量?
【发布时间】:2020-05-05 18:45:06
【问题描述】:

我正在尝试将包含 9 行单个整数的文本文件读入向量中。 VS Code 没有返回语法错误,但是当我调试程序时,我在 main 下遇到了分段错误(我在特定行上发表了评论)。我的实施有问题吗?提前谢谢!

#include <iostream>
#include <vector>
#include <fstream>
#include <string>
using namespace std;
vector <int> list = {};

int count_line(){   //Count the number of accounts in the txt file
    int count = 0;
    string line;
    ifstream count_file;
    count_file.open("text.txt"); //The text file simply have 9 lines of single integers in it
    if (!count_file){
        cerr<<"Problem reading from file"<<endl;
        return 1;
    }
    while (!count_file.eof()){
        getline(count_file,line);
        count ++;
    }
    count_file.close();
    return count - 1;
}

int main(){
    int i{0};
    count_line();
    ifstream input {"text.txt"};
    if (!input){
        cout<<"Problem reading from file"<<endl;
        return 1;
    }
    while (i <= count_line() && count_line() > 0){
        input>>list[i]; //I am getting a segmentation fault error here
        i++;
    }
    for (int k = 0; k < 9 ; k++){
        cout<<list[k];
    }
}

【问题讨论】:

  • 我强烈建议在发帖前先搜索一下互联网。 StackOverflow 上已经有很多同名的问题。还可以在互联网上搜索“C++ 读取文件逗号分隔”以获取从文本文件读取的示例。
  • 您可能希望在阅读每一行时保留std::vector 的文件位置。这将允许您更有效地访问文件中的一行(查找文件位置,然后将文件位置设置为该值)。
  • 您的代码存在c - Why is “while ( !feof (file) )” always wrong? - Stack Overflow 中描述的问题。您通过从count 中减去 1 来解决此问题,但是您的程序会将 0 行文件报告为具有 -1 行。

标签: c++ vector fstream


【解决方案1】:

这个向量:

vector <int> list = {};

只有零个成员。您永远不会尝试增加其大小,因此对该数组的任何访问都会导致错误的结果。

有几个地方可以访问这个向量:

input>>list[i];

// and

cout<<list[k];

这些都是对列表的无效访问。

要解决此问题,您可以将数据读入一个值,然后将其附加到向量:

int value;
input >> value;
list.emplace_back(value); // emplace back expands the vector by one place.

但这不是你唯一的问题:

 while (i <= count_line() && count_line() > 0){

此 while 语句包含对打开文件的调用解析整个文件并返回计数。我怀疑编译器是否可以优化它,所以调用 make 的成本非常高。

您可以只读取值直到没有剩余吗?

 int   value;
 while(input >> value) {
     list.emplace_back(value);
 }

但正确的做法是:

 #include <vector>
 #include <iterator>
 #include <iostream>
 #include <fstream>

 int main()
 {
     std::ifstream     file("text.txt");
     std::vector<int>  data(std::istream_iterator<int>{file},
                            std::istream_iterator<int>{});

     for(auto val: data) {
         std::cout << val << " ";
     }
     std::cout << "\n";
 }

【讨论】:

  • 这是一个很好的建议!我可以通过索引而不是使用 push_back() 为向量赋值吗?
  • @Brian:您可以使用索引为向量赋值 iff 向量已经至少具有该大小。使用索引将不会增加向量的大小。使用push_back()emplace_back() 会扩大向量的大小。
  • 我明白了。由于一些非常复杂的原因,我不能像你建议的那样将数据附加到向量中,有没有办法用空占位符预先分配向量的大小?
  • @Brian 您可以通过调用resize() 手动重新调整向量的大小,这将根据需要显式设置向量的大小。但是简单地使用push_back()会更容易。
  • 就像我想控制数据被附加到的位置,而不是仅仅将其添加到下一个索引
【解决方案2】:

您必须在使用之前分配元素。

修复之一:

    while (i <= count_line() && count_line() > 0){
        if (list.size() <= (size_t)i) list.resize(i + 1); // add this
        input>>list[i];

【讨论】:

  • 这个作品,非常感谢!我是 C++ 的初学者,你能解释一下代码的作用吗?我以前从未见过这样写的 if 语句!
  • 当元素数量不足时分配元素,使list[i]变为可用。 std::vector<T,Allocator>::resize - cppreference.com
  • 那么是分配向量的空间吗?
  • 是的,通过调整矢量大小。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-21
  • 1970-01-01
  • 1970-01-01
  • 2019-10-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多