Creating vector of vectors from text file - c++

I have to create a vector of vectors from a text file. The values in question are integers.
The values are a fixed 3 columns with varying rows. However, I don't believe this is causing my issues. The main issue I think I'm having is that the values from the text file aren't being put into the vector of vectors. The relevant code is as follows:
ifstream infile("material_properties.txt");
if (!infile)
{
cout << "File material_properties.txt not found." << endl;
return -1;
}
int lines = 0;
string line;
while (getline(infile, line))
{
++lines;
}
vector< vector<int> > properties(lines,vector<int>(3));
while (getline(infile,line)) {
for(int i=0; i < lines; i++){
for (int j=0; j<4; j++){
infile >> properties[i][j];
}
}
}
I'm very new to coding and very confused.

You need to rewind your ifstream, add:
infile.seekg(0);
before your second while (getline(infile,line)) {
This is because when you read a file, an internal pointer to the current file position is incremented. It incremented until end of file in first getline loop, so in second you need to rewind it.
Your second bug is that in;
vector< vector<int> > properties(lines,vector<int>(3));
you create vector of three elements in your vector of vector, but in the read loop you add four elements from your file. You should change it to vector<int>(4).
Third issue, is your way of parsing file. In your second loop you read file line by line, which indicates you want to parse it, but your code is actually wrong:
int i = 0;
while (getline(infile,line)) {
// This actually makes no sense, you have read one line
// which you should parse and put results into properties vector.
//for(int i=0; i < lines; i++){
// for (int j=0; j<4; j++){
// infile >> properties[i][j];
// }
//}
// parsing would look like this (depends on your input file):
std::istringstream in(line);
in >> properties[i][0] >> properties[i][1] >> properties[i][2];
i++;
}

First off
while (getline(infile, line))
{
++lines;
}
Is going to read in the file until it reaches the end of the file. Then when you go to read from the file again you are already at the end so nothing will be read. Instead of read in from the file to find the file size you can just read from the file and input the values into the vector. The vector will grow as you add data to it automatically.
ifstream infile("material_properties.txt");
vector< vector<int> > properties;
vector<int> row(3);
while (infile >> row[0] >> row[1] >> row[2])
{
properties.push_back(row);
}

Related

How do i read a csv text file into a 2D array?

This is the sample text file content:
5 //columns
Id,Age,history,chemistry,biology //column names
100// number of data rows
3245167,12,45,78,12 //data rows separated by commas
30980424,10,26,38,98
and so on..
This is the general code i have so far:
int main()
{
//prints out input from file.
ifstream myFile;
myFile.open("WRITE FILE NAME");
while(Myfile.good()) { // good means while there is smthg in the file keep reading it
// until you reach to the end.
string line;
getline(myFile, line, ','); //read text until comma, then stop and store in variable.
cout << line << endl;
}
return 0;
}
You have a general outline of parsing the file itself, the data will be read from the file left to right. So there's two things I'd recommend for you to do at this point since you've already parsed the data. You'll probably want something to hold it like a queue to store and hold all the data and a double for loop to place it into the 2D array so like this:
std::queue<string> holder;
std::string myArray[row][col];
getline(myFile, line, ',');
holder.push(line);
for(int i=0; i < row; i++)
{
for(int j=0; j < col; j++)
{
myArray[i][j] = holder.pop();
}
}

How to use file.eof() while reading in integers from a file?

I am writing a program that reads in data from a file. The file contains lines of integers, such as
5 6 2 8 6 7
2 5 3
4 0 9 1 3
The first integer of each line corresponds to how many numbers there are in that line. My goal is to read in each line, store the numbers in a vector, and do some operation on them. Here is what I have done:
int main(){
vector<int> vec;
int amount;
int nums;
ifstream file ("file.txt");
while(!(file.eof())){
file >> amount;
cout << amount << endl;
for (int i = 0; i < amount; i++){
file >> nums;
vec.push_back(nums);
}
printArray(vec);
bubbleSort(vec);
vec.clear();
}
return 0;
}
Unfortunately, the last line always gets read twice. I looked online and saw that the eof() function should not be used to maintain loops. What else could I use in this situation?
Thanks.
operator>> sets the stream's eofbit flag if it tries to read past EOF. You can use that condition to break your loops. But you have to actually perform a read operation BEFORE you can evaluate eof(). See Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong? for more details on that.
Since you are dealing with line-based text, you can use std::getline() to read each line first, and then you can use std::istringstream to parse each line, eg:
int main()
{
vector<int> vec;
ifstream file ("file.txt");
string line;
while (getline(file, line)) {
istringstream iss(line);
int amount, nums;
iss >> amount;
cout << amount << endl;
for (int i = 0; (i < amount) && (iss >> nums); ++i){
vec.push_back(nums);
}
printArray(vec);
bubbleSort(vec);
vec.clear();
}
return 0;
}
Alternatively, you can simply take advantage of the fact that operator>> skips whitespace, including line breaks, eg:
int main()
{
vector<int> vec;
int amount, nums;
ifstream file ("file.txt");
while (file >> amount) {
cout << amount << endl;
for (int i = 0; (i < amount) && (file >> nums); ++i){
vec.push_back(nums);
}
printArray(vec);
bubbleSort(vec);
vec.clear();
}
return 0;
}
Although, this approach would be a little less resilient to errors in the input data, compared to the std:getline() approach. If the actual amount of numbers in a given line does not match the specified amount at the beginning of the line, this approach will get its reading of the file out of sync. Worse, if a given line contains any non-integer values, this approach will fail to read any subsequent data at all.
In the std:getline() approach, if a given line is malformed, the code will simply move on to the next line and continue on like nothing bad happened.

Getline to read data from txt file

I'm having a bit of a problem with extracting data from a simple .txt file with the getline command.
The txt file is very simple: a column of 400 numbers. I use a vector to store them with the following code:
int i = 0;
string line;
vector <double> vec;
while (getline(input, line))
{
vec.push_back(i);
N++;
input >> vec[i];
i++;
}
It correctly creates a vector of 400 elements but first line of txt file is ignored (I end up with vec[0] = 2nd line of txt file instead of 1st) and 399th element is 399 instead of the 400th line of txt file.
I tried several other ways to extract this data but it was unsuccessful.
Thank you for your help!
EDIT:
I have edited the code according to some of the remarks:
vector <double> vec;
string line;
double num;
while (getline(input, line))
{
input >> num;
vec.push_back(num);
}
Unfortunately, it still skips the first line of my text file.
EDIT 2 --> SOLUTION:
Thanks to all of your remarks, I realized that I was doing something wrong when using both getline and input >> num;
Here is how the problem was solved:
double num;
vector <double> vec;
while (input >> num)
{
vec.push_back(num);
}
You can read the entire file into a vector just by passing std::istream_iterator to std::vector constructor, without loops:
std::vector<int> v{
std::istream_iterator<int>{input},
std::istream_iterator<int>{}
};
E.g.:
#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';
}
You loose the first line due to reading from the file once more - here:
while (getline(input, line))
// ^^^^^^^ Here you read the first line
{
input >> num;
// ^^^^^^^^ Here you will read the second line
You told you want a vector of doubles - like:
std::vector<double> vec;
So you should use std::stod to convert the line read by getline into a double. Like:
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);
}
Don't do input >> num; inside the loop.
If you really want to use input >> num; then you shall not use getline. That is - you can use either but not both.
Change your while loop like below:-
while (getline(input, line))
{
vec.push_back(line);
//N++;
//input >> vec[i];
//i++;
}
Also try with below option
do{
vec.push_back(i);
//N++;
//i++;
}while (input >> vec[i++]);
You are starting by putting 0 in vector in first iteration:
vec.push_back(i);
then after you read first line you read next string, but stream get pointer from file is already in different place, so you override this 0 and skip first value from stream. What is worse that is oddly converted to double:
input >> vec[i];
This way you will get wrong.
Try this:
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()));
}
This assumes you will always have proper file.

could'nt read correct values of vector produced from file

I am trying to read text file line by line and then read each column as vector but when i am tryin to cout first column it shows zeros i.e. not reading the file correctly.
int main(void)
{
ifstream myfile ("data1.txt");
string line;
if (myfile.is_open())
{
int ln=1;
while ( getline (myfile,line) )
{
if(ln==1){ln++; continue;}
istringstream iss(line);
string word;
vector<double> column;
int w=1;
while(iss >> word)
{
//double dw=atof(Form("%s",word));
column.push_back(atof(Form("%s",word)));
cout<<column[0];
w++;
}
ln++;
cout<<"\n";
}
myfile.close();
}
//else
else cout<<"Unable to open file";
cout<<"\n";
return ;
}enter code here
push_back appends an element as last element of the vector while columns[0] always refers to the first element of the vector.
Is the first element 0
Is there another problem?
(Please explain what is Form, give an example of input file and output in the command line)
First of all learn how to indent and consistently use some scheme for inserting blank lines that makes sense. When you do that you can read your own code and figure out if it is doing what you think it is.
Second. Save Form("%s",word) in a string ( for now call it form_string) add this line cout<<"form returns "<<form_string<<endl; 99.99% probably it will print zeros.
Finally change: cout<<column[0]; to cout<<column[0]<<" "; or cout<<*(column.rbegin())<<" ";. The latter prints out all the values that you read, the former prints out the first value you read over and over.

c++ open .txt file and read numbers to place in an array

i have a text file that has the numbers on one line like (no spaces between commas):
-1,5,-3,10,500000,-6000
so far this is the code i have but i am not getting anything back at all in the vector array
fstream fp;
vector<int> numbers;
int number;
fp.open("numbers.txt", ios::in | ios::binary);
if(fp.is_open()){
while(fp >> number){
numbers.push_back(number);
}
}
fp.close();
cout << "Numbers:\n";
for (int i=0; i < numbers.size(); i++) {
cout << numbers[i] << '\n';
}
i feel like im just not reading the file properly or the whole line is just getting put into the number var. Also, the number of numbers in the file is unknown so i would like to stay away from hardcoding it
fstream fp;
vector<int> numbers;
int number;
fp.open("numbers.txt", ios::in | ios::binary);
if(fp.is_open()){
while(fp >> number){
numbers.push_back(number);
fp.get();
}
}
fp.close();
cout << "Numbers:\n";
for (int i=0; i < numbers.size(); i++) {
cout << numbers[i] << '\n';
}
You just forgot about the comma's! use fp.get(); to get rid of them, and then it'll work fine :D
First of all, your input file is not binary - don't use ios::binary.
Second of all, you need to split your input tokens. Your input operation will fail every time you stumble upon a comma. You might need to input a character or a string to deal with those.
Your input fails when it trys to insert a , into an integer. You should use getline to insert the values up until the comma delimiter:
while (std::getline(fp, number, ','))
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Like this
if(fp.is_open()){
while(fp >> number){
numbers.push_back(number);
char dummy_variable_for_the_comma;
fp >> dummy_variable_for_the_comma; // read and discard a comma
}
}
You have to tell the computer to skip the commas, it won't do that for you.