如何在C++中将文件读入向量?

30
我需要从一个包含每行一个新的float数字的.data或.txt文件中读取数据到一个向量中。
我已经广泛搜索并尝试了许多不同的方法,但每次都得到相同的结果,即Main.size()为0,并出现错误提示"Vector Subscript out of Range",因此很明显这个向量没有从文件中读取任何内容。
注意:该文件既在文件夹中,也包含在VS项目中。
无论如何,这是我的代码:
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>

using namespace std;

int main() {

    vector<double> Main;
    int count;
    string lineData;
    double tmp;

    ifstream myfile ("test.data", ios::in);

    double number;  

    myfile >> count;
    for(int i = 0; i < count; i++) {
        myfile >> tmp;
        Main.push_back(tmp);
        cout << count;
    }

    cout << "Numbers:\n";
    cout << Main.size();
    for (int i=0; i=((Main.size())-1); i++) {
        cout << Main[i] << '\n';
    }

    cin.get(); 
    return 0;
}

我得到的结果总是简单的:
Numbers:
0

1
检查所有I/O操作的结果。 - hmjd
你的 test.data 实际上是什么样子? - us2012
请查看序列化/反序列化。通常您会创建一个向量类和一个向量集合类(可以处理txt输入文件)。一个好的起点是这个答案:https://dev59.com/zGgu5IYBdhLWcg3wUlft - Najzero
test.data 就像这样:1.4049 4.9166 3.3903 2.4963 2.4429 3.7053 1.9727 3.1569 2.5528 4.4527 1.5241但有1000个条目,每个条目都在新行上。 - Orgmo
可能是重复的问题,与如何将二进制文件读入无符号字符向量有关。看起来这个问题在你提问之前20分钟就被问过了。你们是上同一门课吗? - jww
6个回答

53

你的循环有问题:

for (int i=0; i=((Main.size())-1); i++) {

试试这个:

for (int i=0; i < Main.size(); i++) {

此外,更符合惯用语的将数字读入向量并将它们写入标准输出的方法如下:
#include <iostream>
#include <iterator>
#include <fstream>
#include <vector>
#include <algorithm> // for std::copy

int main()
{
  std::ifstream is("numbers.txt");
  std::istream_iterator<double> start(is), end;
  std::vector<double> numbers(start, end);
  std::cout << "Read " << numbers.size() << " numbers" << std::endl;

  // print the numbers to stdout
  std::cout << "numbers read in:\n";
  std::copy(numbers.begin(), numbers.end(), 
            std::ostream_iterator<double>(std::cout, " "));
  std::cout << std::endl;

}

尽管您应该检查ifstream的状态以获取读取错误。

2
然后你就发现了隐藏的赋值错误。谢谢,C! - Mike DeSimone
好的,这很好,但现在问题似乎是它找不到文件或者将文件读取为空。 - Orgmo
@Orgmo 我添加了一些代码,展示了打印向量内容的一种方式。它并没有比循环提供更多优势,但它展示了另一种C++语法习惯的运作方式。 - juanchopanza

9
只是为了补充一下juanchopanza的答案...
for (int i=0; i=((Main.size())-1); i++) {
    cout << Main[i] << '\n';
}

这段代码做了以下操作:

  1. 创建变量 i 并将其设置为 0
  2. i 设置为 Main.size() - 1。由于 Main 是空的,所以 Main.size() 的结果为 0,因此 i 被设置为 -1
  3. Main[-1]是越界访问,程序将会崩溃。

我认为主要的问题不是边界(虽然这也是个问题)。问题在于赋值运算符“=”和比较运算符“==”之间的区别。 - LRDPRDX
那就是引发雪崩的事情。越界违规是实际调用错误的部分。重点在于说明为什么这是一个错误。在我看来,BASIC做对了一件事,那就是将赋值作为语句而不是表达式。因此,您不需要使用“==”、“:=”或任何其他虚构的运算符,并且在第一次就不会犯这样的错误。 - Mike DeSimone
同意。我看到我的同事们已经用C++编程多年,仍然不知道赋值运算符会返回一个值 :) - LRDPRDX
它应该返回一个引用。 - Mike DeSimone
OFC,我的意思是它“返回”。许多通常的单词现在已经被保留,因此现在应该准确使用 :) - LRDPRDX

7
只是一些建议。不要写成

for (int i=0; i=((Main.size())-1); i++) {
   cout << Main[i] << '\n';
}

如上所建议,写一个:

for (vector<double>::iterator it=Main.begin(); it!=Main.end(); it++) {
   cout << *it << '\n';
}

使用迭代器。如果您支持C++11,可以将i声明为auto i=Main.begin()(只是一个方便的快捷方式)

这避免了因无意中省略-1而导致的讨厌的超出边界一位错误。


2

1. 在循环中,你正在赋值而不是比较数值,因此

i=((Main.size())-1) -> i=(-1),因为 Main.size()

Main[i]将产生“向量下标超出范围”的错误,因为i=-1。

2. 如果无法找到文件,你将得到Main.size()的值为0。给出文件路径并检查输出。还应该初始化变量。


-1
  //file name must be of the form filename.yourfileExtension
       std::vector<std::string> source;
bool getFileContent(std::string & fileName)
{
    if (fileName.substr(fileName.find_last_of(".") + 1) =="yourfileExtension")
    {

        // Open the File
        std::ifstream in(fileName.c_str());

        // Check if object is valid
        if (!in)
        {
            std::cerr << "Cannot open the File : " << fileName << std::endl;
            return false;
        }
        std::string str;
        // Read the next line from File untill it reaches the end.
        while (std::getline(in, str))
        {
            // Line contains string of length > 0 then save it in vector
            if (str.size() > 0)
                source.push_back(str);
        }
        /*for (size_t i = 0; i < source.size(); i++)
    {
        lexer(source[i], i);
        cout << source[i] << endl;
    }
    */
        //Close The File
        in.close();
        return true;
    }
    else
    {
        std::cerr << ":VIP doe\'s not support this file type" << std::endl;
        std::cerr << "supported extensions is filename.yourfileExtension" << endl;
    }
}

你好!虽然这段代码可能解决了问题,但是包括解释它如何以及为什么解决了问题将有助于提高您的帖子质量,并可能导致更多的赞。请记住,您正在回答未来读者的问题,而不仅仅是现在提问的人。请[编辑]您的答案以添加解释并指出适用的限制和假设。 - Brian61354270

-2
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;

int main()
{
fstream dataFile;
string name , word , new_word;
vector<string> test;
char fileName[80];
cout<<"Please enter the file name : ";
cin >> fileName;
dataFile.open(fileName);
if(dataFile.fail())
{
     cout<<"File can not open.\n";
     return 0;
}
cout<<"File opened.\n";
cout<<"Please enter the word : ";
cin>>word;
cout<<"Please enter the new word : ";
cin >> new_word;
while (!dataFile.fail() && !dataFile.eof())
{
      dataFile >> name;
      test.push_back(name);
}
dataFile.close();

}

如果您不仅仅是发布代码,而是添加简短的注释到答案中,那将非常棒。 - Micer

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