Resolving anomalous string to float operation on a vector? - c++

I have a code that takes a .csv file and reads the values and prints it out.
The contents of the .csv file are -
55
100
200
500
500
150
I am using the stof method to cast strings into floats like this -
for (unsigned int i = 0; i < DataStore.size(); i++)
cout << stof(DataStore[i]) << endl;
but in this case I only get the output as
55
instead of -
55
100
200
500
500
150
I am new to C++ so I'm pretty sure there's something trivial that I'm missing - but unable to figure it out.
Minimal Reproducible Code -
string line;
vector<string> DataStore;
{
ifstream file("test.csv");
while (getline(file, line, ','))
{
DataStore.push_back(line);
getline(file, line);
}
}
for (unsigned int i = 0; i < DataStore.size(); i++)
cout << stof(DataStore[i]) << endl;
Contents of test.csv are as follows -
55
100
200
500
500
150

while (getline(file, line, ','))
This reads from the file until the it encounters a comma. There are no commas in your file, so the whole file will be read into line, this line is inserted into DataStore and the loop does not iterate any further, because there is nothing left to be read for the next getline.
Therefore DataStore.size() will be one and in the single iteration the whole file's contents are passed to stof, which will form the parsed number from the beginning until it encounters something not part of a valid number, here the newline. The result will be 55. This is printed and the loop exits.
You seem to want to read line-by-line. This is done by getline without third argument (or third argument equal '\n'). Additionally there is a stray getline, the purpose of which I don't know.
string line;
vector<string> DataStore;
{
ifstream file("test.csv");
while (getline(file, line))
{
DataStore.push_back(line);
}
}
for (unsigned int i = 0; i < DataStore.size(); i++)
cout << stof(DataStore[i]) << endl;
Note that you can directly read the numbers from the file into a std::vector:
ifstream file("test.csv");
vector DataStore(istream_iterator<double>(file), {});
This requires #include<iterator> and before C++17 the vector type needs to be specified: vector<double>
It reads white-space separated numbers until the end of file.

Related

Cout empty when there are two getline?

I am trying to cout my array but it keep showing empty whenever I try to.
int array_size = 0;
int pos;
string line;
ifstream inFile;
string filename = 'test.txt';
inFile.open(filename);
for(array_size = 0; getline(inFile, line); array_length++);
string * array_holder = new string[array_size];
while(getline(inFile, line))
{
array_holder[pos++] = line;
}
printArray(array_holder, array_size);
Print array
void printArray(string * data, int x)
{
for(int z = 0; z < x; z++)
cout << data[z] << endl;
}
When I comment out this line:
for(array_size = 0; getline(inFile, line); array_length++);
The printArray will show all the contents inside.
But when I uncomment the line, it just show empty lines (depending on the array size).
I reckon this is due to double getline? Do I need to clear the getline buffer or something? I couldn't find any details about getline buffer except for cin. Or is this memory issue?
Note that I cannot use vector in my situation and I need to read the total number of lines in the text file in order to parse the array size to my array syntax.
Thanks.
for(array_size = 0; getline(inFile, line); array_length++);
This loop reads inFile, one line at a time, until the end of the file is reached.
After this loop terminates, the entire file has been read. After all, that's exactly what your program tells your computer to do: read one line at a time, incrementing the counter, until getline fails, which happens at the end of the file. But then immediately afterwards, the second loop attempts to continue reading from the file:
while(getline(inFile, line))
However, since the end of the file has already been reached, this immediately fails, and nothing happens.
You obviously want to reread the file from the beginning, here. However, the Golden Rule Of Computer Programming states "your computer will always do exactly what you tell it to do, instead of what you want it to do". You have not told your computer to go back to the beginning of the file here, so it has no reason to do that. So, you simply have to tell your computer to do that, by closing and reopening the file, or by using the seekg() method.

How to access individual word from c++ vector?

At the end of the program I output the contents of a vector, the strings were inputted from a text file. The entire vector is outputted, but how do I just output one word? I am asking this because I will later need to modify each string.
#include<iostream>
#include<fstream>
#include<vector>
#include<algorithm>
using namespace std;
int main(){
ifstream in;
string line, file_name;
vector <string> phrase;
int total_words, total_letters, total_chars;
cout << "PIG LATIN PROGRAM" << endl;
cout << "Which file are you accessing? : ";
cin >> file_name;
in.open(file_name);
if (in.fail()) cout << "\nFile not found!" << endl;
while(getline(in, line)) phrase.push_back(line);
for(int i = 0; i < phrase.size(); i++){
int limit = phrase.size() - 1;
while(i < limit && phrase[i] == phrase[i]){
i++;
}
cout << phrase[i];
}
You could start by splitting the line in phrase[i] at points there's whitespace:
std::istringstream iss{phrase[i]};
std::vector<std::string> words;
std::string word;
while (iss >> word)
words.push_back(std::move(word));
std::istringstream creates an input stream - a bit like cin - that contains the full line of text read from your file and stored in phrase[i]. If you then use >> word it will extract one whitespace-delimited word of text at a time.
Say your line/phrase[i] input contained "the blue socks were her favourites", it'll be split nicely into words. If there is also punctuation in the line, some of the strings in words will embed that punctuation, e.g. "world.". If you care about that, you can learn to use std::string member functions to search in and edit the strings.
In the case of punctuation you could use
std::erase(std::remove_if(word.begin(), word.end(), std::ispunct), word.end()) to remove it (further details/explanation).
phrase[i] == phrase[i]
Well, that's just redundant. This will always return true for a vector holding strings.
for(int i = 0; (...); i++){
while( (...) ){
i++;
}
}
You are modifying variable i twice in this a single for loop. Once in the third parameter of for, and once in an inner while loop. It's almost never a good idea.
What's happening here is that you set i=0, then immediately set it to point to the last element of a vector (as the second condition in while is always true).
Then you print this element to console, which is the last line of your text file.
What you want to do, is:
1. Load text file line by line into a vector.
2. Each element of vector will hold a single line.
3. Split each line into a vector of WORDS (space separated).
4. Work with the resulting vector.
Or pheraps:
1. Load file word by word at the beginning.
vector<string> words;
copy( istream_iterator<string>{YourFileStream}, istream_iterator<string>{}, back_inserter{words} ); // this will copy the content of file directly into vector, white-space-separated (no need for while loop to do it)
for ( auto i = phrase.begin(); i != phrase.end(); ++i ) // it's the proper c++ way of iterating over a vector. very similar, but variable i will point to every element of vector in order ( not just to the index of an element )
{
// do some work on *i. at least:
std::cout << *i; // dereference operator (*) is needed here, since i doesn't hold index of an element, it's a "pointer" to an element
}
If you need the first approach ( to differentiate between words in different lines ), here you can find some excellent ways to separate a string by any delimeter (space, for example): The most elegant way to iterate the words of a string

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.

Pushing a vector into another vector

I have a file that goes like this:
98
287 2352
987 4313 3253
235 34325 432 123
Basically I want to reproduce this file. I am trying to import a line at a time, extract the numbers, and push them into vectors. Each vector is pushed into a larger vector.
int main(int argc, char* argv[])
{
int sum = 0, one = 0, two = 1;
std::string line, number;
std::vector<int> vec;
std::vector<std::vector<int>> bigvec;
auto k = vec.begin();
std::ifstream in(argv[1]);
while(in >> line) {
std::istringstream is(line);
while(is >> number) {
vec.push_back(stoi(number));
}
bigvec.push_back(vec);
while(!vec.empty()) {
vec.pop_back();
}
std::cout << std::endl;
}
return 0;
}
My code though, when I print the result, seems to put each number in it's own vector instead of reproducing the file.
So my output is
98
287
2352
etc.
It seems that the line
while(is >> number) {
vec.push_back(stoi(number));
}
pushes one number and then exits the loop.
Where am I going wrong?
while(in >> line) reads next word from the input. Use getline(in, line) if you want to read a whole line.
There are multiple optimizations that you can add to your code. For instance instead of using stoi on the string you've read you can read an integer from the input stream. Also instead of popping the vector's elements one by one you can simply call clear.
Your problem lies here:
while(in >> line)
C++ by defult reads until it encounters interval or new line. In your case it encounters interval before new line. If you want to take the whole line take:
getline(cin, line);

new >> how would i read a file that has 3 columns and each column contains 100 numbers into an array?

int exam1[100];// array that can hold 100 numbers for 1st column
int exam2[100];// array that can hold 100 numbers for 2nd column
int exam3[100];// array that can hold 100 numbers for 3rd column
int main()
{
ifstream infile;
int num;
infile.open("example.txt");// file containing numbers in 3 columns
if(infile.fail()) // checks to see if file opended
{
cout << "error" << endl;
}
while(!infile.eof()) // reads file to end of line
{
for(i=0;i<100;i++); // array numbers less than 100
{
while(infile >> [exam]); // while reading get 1st array or element
???// how will i go read the next number
infile >> num;
}
}
infile.close();
}
int exam1[100];// array that can hold 100 numbers for 1st column
int exam2[100];// array that can hold 100 numbers for 2nd column
int exam3[100];// array that can hold 100 numbers for 3rd column
int main() // int main NOT void main
{
ifstream infile;
int num = 0; // num must start at 0
infile.open("example.txt");// file containing numbers in 3 columns
if(infile.fail()) // checks to see if file opended
{
cout << "error" << endl;
return 1; // no point continuing if the file didn't open...
}
while(!infile.eof()) // reads file to end of *file*, not line
{
infile >> exam1[num]; // read first column number
infile >> exam2[num]; // read second column number
infile >> exam3[num]; // read third column number
++num; // go to the next number
// you can also do it on the same line like this:
// infile >> exam1[num] >> exam2[num] >> exam3[num]; ++num;
}
infile.close();
return 0; // everything went right.
}
I assume you always have 3 numbers per line. If you know the exact number of lines, replace the while with a for from 0 to the number of lines.
Rule # 1 about reading data from a file: don't trust the contents of the file. You never know with absolute certainty what is in the file until you've read it
That said, one correct way to read lines of data from a file, where each line is composed of multiple whitespace-delimited fields would be to use a combination of getline and stringstream:
std::string line;
while (std::getline(infile, line))
{
std::stringstream ss(line);
int a, b, c;
if (ss >> a >> b >> c)
{
// Add a, b, and c to their respective arrays
}
}
In English, we get each line from the file stream using getline, then parse the line into three integers using a stringstream. This allows us to be certain that each line is formatted correctly.
We check to ensure the extraction of the integers succeeded before we add them to the arrays to ensure that the arrays always have only valid data.
There is other error handling that might be desirable:
In the example, if extraction of the integers from the line fails, we just ignore that line; it could be a good idea to add logic to abort the process or report an error.
After we get three integers, we ignore the rest of the line; it might be a good idea to add checks to ensure that there is no more data on the line after the required integers, depending on how strict the file's formatting needs to be.
After we finish reading the file, we should test to be sure eof() is set and not fail() or bad(); if one of those two flags is set, some error occurred when reading the file.