28

I need to read from a .data or .txt file containing a new float number on each line into a vector.

I have searched far and wide and applied numerous different methods but every time I get the same result, of a Main.size() of 0 and an error saying "Vector Subscript out of Range", so evidently the vector is just not reading anything into the file.

Note: the file is both in the folder and also included in the VS project.

Anyway, here's my code:

#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;
}

The result I get is always simply:

Numbers:
0
Ziezi
  • 6,375
  • 3
  • 39
  • 49
Orgmo
  • 388
  • 1
  • 5
  • 12
  • 1
    Check the result of all I/O operations. – hmjd Feb 28 '13 at 15:06
  • What does your `test.data` actually look like? – us2012 Feb 28 '13 at 15:06
  • please have a look into de/-serialization. usually you would create a vector class and a vector collection class ( that can handle the txt input file ). A good start is the answer to this: http://stackoverflow.com/questions/11415850/c-how-serialize-deserialize-objects-without-any-library – Najzero Feb 28 '13 at 15:07
  • test.data is just like this: `1.4049 4.9166 3.3903 2.4963 2.4429 3.7053 1.9727 3.1569 2.5528 4.4527 1.5241` but with 1000 entries all on new lines – Orgmo Feb 28 '13 at 15:25
  • Possible duplicate of [How to read a binary file into a vector of unsigned chars](https://stackoverflow.com/questions/15138353/how-to-read-a-binary-file-into-a-vector-of-unsigned-chars). It looks like the dup was asked 20 minutes before you asked. Are you guys taking the same class? – jww Dec 16 '17 at 04:35

6 Answers6

51

Your loop is wrong:

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

Try this:

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

Also, a more idiomatic way of reading numbers into a vector and writing them to stdout is something along these lines:

#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;

}

although you should check the status of the ifstream for read errors.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • 2
    And there you go. Hidden assignment bug. Thanks, C! – Mike DeSimone Feb 28 '13 at 15:06
  • OK this works great but now it just seems the problem is it isnt finding the file or is reading the file as blank. – Orgmo Feb 28 '13 at 15:28
  • @Orgmo I added a bit of code showing one way of printing the contents of the vector out. It doesn't offer many advantages over a loop, but it shows yet another C++ idiom at work. – juanchopanza Feb 28 '13 at 15:46
9

Just to expand on juanchopanza's answer a bit...

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

does this:

  1. Create i and set it to 0.
  2. Set i to Main.size() - 1. Since Main is empty, Main.size() is 0, and i gets set to -1.
  3. Main[-1] is an out-of-bounds access. Kaboom.
Mike DeSimone
  • 41,631
  • 10
  • 72
  • 96
  • I think the main problem isn't the bounds, (thought it is a problem). The problem is the distinction between the assignment operator `=` and the comparison operator `==`. – LRDPRDX Dec 23 '21 at 16:23
  • That’s the thing that starts the avalanche. The bounds violation is the part that actually calls the error. The point was showing why it was an error. One of the things BASIC got right IMHO was making assignment a statement instead of an expression. So you didn’t need `==` or `:=` or any other made up operators, and couldn’t make a mistake like this in the first place. – Mike DeSimone Dec 24 '21 at 23:29
  • Agreed. I see my colleagues having been coding in C++ for years, still don't know that the assignment operator returns a value :) – LRDPRDX Dec 25 '21 at 07:37
  • It should be returning a reference. – Mike DeSimone Dec 26 '21 at 04:01
  • OFC, I meant that it _returns_. Many usual words became reserved and should be used accurately now :) – LRDPRDX Dec 26 '21 at 08:27
7

Just a piece of advice. Instead of writing

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

as suggested above, write a:

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

to use iterators. If you have C++11 support, you can declare i as auto i=Main.begin() (just a handy shortcut though)

This avoids the nasty one-position-out-of-bound error caused by leaving out a -1 unintentionally.

phoeagon
  • 2,080
  • 17
  • 20
2

1. In the loop you are assigning value rather than comparing value so

i=((Main.size())-1) -> i=(-1) since Main.size()

Main[i] will yield "Vector Subscript out of Range" coz i = -1.

2. You get Main.size() as 0 maybe becuase its not it can't find the file. Give the file path and check the output. Also it would be good to initialize the variables.

Shriraj
  • 56
  • 4
-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;
    }
}
  • Hello! While this code may solve the question, [including an explanation](https://meta.stackexchange.com/q/114762) of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please [edit] your answer to add explanations and give an indication of what limitations and assumptions apply. – Brian61354270 Apr 23 '20 at 19:16
-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();

}
  • It would be greate if you can also add brief comment to the answer, not just post the code. – Micer Mar 29 '18 at 19:45