Convert string from getline into a number - c++

I am trying to create a 2D array with vectors. I have a file that has for each line a set of numbers. So what I did I implemented a split function that every time I have a new number (separated by \t) it splits that and add it to the vector
vector<double> &split(const string &s, char delim, vector<double> &elems) {
stringstream ss(s);
string item;
while (getline(ss, item, delim)) {
cout << item << endl;
double number = atof(item.c_str());
cout << number;
elems.push_back(number);
}
return elems;
}
vector<double> split(const string &s, char delim) {
vector<double> elems;
split(s, delim, elems);
return elems;
}
After that I simply iterate through it.
int main()
{
ifstream file("./data/file.txt");
string row;
vector< vector<double> > matrix;
int line_count = -1;
while (getline(file, row)) {
line_count++;
if (line_count <= 4) continue;
vector<double> cols = split(row, '\t');
matrix.push_back(cols);
}
...
}
Now my issues is in this bit here:
while (getline(ss, item, delim)) {
cout << item << endl;
double number = atof(item.c_str());
cout << number;
Where item.c_str() is converted to a 0. Shouldn't that be still a string having the same value as item? It works on a separate example if I do straight from string to c_string, but when I use this getline I end up in this error situation,
hints?

instead of using atof use the stringstream
while(!ss.eof())
{
double number;
ss>>number;
}
EDIT:
I have updated your split function and removed the superfluous return.
void split(const string &s, vector<double> &elems) {
stringstream ss(s);
while (!ss.eof()) {
double number;
ss >> number;
cout << number;
elems.push_back(number);
}
}
int main()
{
std::vector<double> columns;
split("1.32\t1.65\t1.98456\t2.34",columns);
return 0;
}

Related

getline() skipping over string line from text file

My project is supposed to basically sum up the value of all ints on a line and print the word in the next line that amount of times. However, something is causing it to skip over the string line where the word but I am getting the summed value right.
Input file:
1,2,3
word
2,3,4
word2
Here is my code:
int main() {
std::ifstream in;
std::ofstream out;
std::string line;
in.open("input.txt");
out.open("output.txt");
while(std::getline(in, line)){
std::stringstream ss(line);
while(ss){
std::string word;
std::string number;
int a = 0;
while(std::getline(ss, number, ',')){
a = a + atoi(number.c_str());}
std::getline(ss, word);
for (int z = 0; z < a; z++){
out << word << ",";}
out << "\n";
}
}
return(0);
}
Output I'm getting:
,,,,,,
,,,,,,,,,
What I should be getting:
word,word,word,word,word,word
word2,word2,word2,word2,word2,word2,word2,word2
Change:
std::getline(ss, word);
To this:
// Gets the next line in input.txt and stores it in the variable 'word'
std::getline(in, word);
This is because during the while loop, ss is emptied (exhausted) by the nested while loop (the 2nd while loop) and has no words when it's contents are inserted into the variable 'word'.
Final code:
#include <iostream>
#include <fstream>
#include <sstream>
int main() {
std::ifstream in;
std::ofstream out;
std::string line;
in.open("input.txt");
out.open("output.txt");
while (std::getline(in, line)) {
std::stringstream ss(line);
while (ss) {
std::string word;
std::string number;
int a = 0;
while (std::getline(ss, number, ',')) {
a = a + atoi(number.c_str());
}
std::getline(in, word); // Changed line
for (int z = 0; z < a; z++) {
out << word << ",";
}
out << "\n";
}
}
return(0);
}

Adding values returned from a function to an array in C++

Output:
cola
coke
3
I want these values to be stored in an array. Please guide me how to!
TIA
This is the code:
int cola(string str)
{
// word variable to store word
string word;
// making a string stream
stringstream iss(str);
// Read and print each word.
while (iss >> word)
{cout << word << endl;}}
// Driver code
int main()
{
string s = "cola coke 3";
cola(s);
return 0;
}
Is this what you are looking for:
using std::string;
std::vector<string> cola(const string& str)
{
// word variable to store word
string word;
// making a string stream
stringstream iss(str);
// vector containing words
std::vector<string> temp;
// Read and print each word.
while (iss >> word)
temp.push_back(word);
return std::move(temp);
}
// Driver code
int main()
{
string s = "cola coke 3";
std::vector<string> array = cola(s);
return 0;
}

C++ ifstream, issue loading with ";"

int a, b;
while (infile >> a >> b)
{
// process pair (a,b)
}
So this is the code i've been watching but i ran into a problem because my strings doesn't have whitespaces between them, they have ";"
My code:
void load(string filename){ // [LOAD]
string line;
ifstream myfile(filename);
string thename;
string thenumber;
if (myfile.is_open())
{
while (myfile >> thename >> thenumber)
{
cout << thename << thenumber << endl;
//map_name.insert(make_pair(thename,thenumber));
}
myfile.close();
}
else cout << "Unable to open file";
}
[Inside the txt.file]
123;peter
789;oskar
456;jon
What i get right now is "thename" as 123;peter and "thenumber" as 789;oskar.
I want "thename" as peter and "thenumber" as 123 so i can then insert it back into my map correctly, How?
The infile >> a read from infile the eligible type for a. In your case a is int so '>>' expect to find an int. In your code myfile >> thename >> thenumber both are string type so they expect string type in your file. The problem is that string include ';' so the variable name will take all the row until it find \n(new line).
in your code
std::string thename, thenumber;
char delimeter(';'); //It is always '-' is it?
std::getline(std::cin, thename, delimeter);
std::getline(std::cin, thenumber);
also thenumber will be string type. To convert your thenumber into int:
std::istringstream ss(thenumber);
int i;
ss >> i;
if (ss.fail())
{
// Error
}
else
{
std::cout << "The integer value is: " << i;
}
return 0;
It is fairly simple to read in a file in the format. You can use std::getline with a different delimiter to tell it where to stop reading the input.
while(getline(myfile, thenumber, ';')) // reads until ';' or end of file
{
getline(myfile, thename); // reads until newline or end of file
map_name.insert(make_pair(thename,thenumber));
}
You have to input a single string and then split it to get the name and number
....
#include <string>
#include <sstream>
#include <vector>
std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim)) {
elems.push_back(item);
}
return elems;
}
std::vector<std::string> split(const std::string &s, char delim) {
std::vector<std::string> elems;
split(s, delim, elems);
return elems;
}
....
void load(string filename){
..........
if (myfile.is_open())
{
while (myfile >>whole)
{
std::vector<std::string> parts = split(whole, ';');
name = parts[0];
number = parts[1];
}
}

C++ reading from data from text file

I have the following data:
$GPVTG,,T,,M,0.00,N,0.0,K,A*13
I need to read the data, however there are blanks in between the commas, therefore I am not sure how I should read the data.
Also, how do I select GPVTG only for a group of data? For example:
GPVTG,,T,,M
GPGGA,184945.00
GPRMC,18494
GPVTG,,T,,M,0
GPGGA,184946.000,3409
I have tried using:
/* read data line */
fgets(gpsString,100,gpsHandle);
char type[10] = "GPVTG";
sscanf(gpsString," %GPVTG", &type);
if (strcmp(gpsString, "GPTVG") == 0){
printf("%s\n",gpsString);
}
Thats what i'd do
#include <iostream>
#include <vector>
#include <sstream>
#include <fstream>
#include <string>
using namespace std;
vector<string> &split(const string &s, char delim, vector<string> &elems) {
stringstream ss(s);
string item;
while (getline(ss, item, delim)) {
elems.push_back(item);
}
return elems;
}
vector<string> split(const string &s, char delim) {
vector<string> elems;
split(s, delim, elems);
return elems;
}
int main()
{
ifstream ifs("file.txt");
string data_string;
while ( getline( ifs, data_string ) )
{
//i think you'd want to erase first $ charachter
if ( !data_string.empty() ) data_string.erase( data_string.begin() );
//now all data put into array:
vector<string> data_array = split ( data_string, ',' );
if ( data_array[0] == "GPVTG" )
{
//do whatever you want with that data entry
cout << data_string;
}
}
return 0;
}
Should handle your task. All empty elements will be empty "" strings in array. Ask if you need anything else.
Credits for split functions belong to Split a string in C++? answer.
How about this
#include <istream>
#include <sstream>
class CSVInputStream {
public:
CSVInputStream(std::istream& ist) : input(ist) {}
std::istream& input;
};
CSVInputStream& operator>>(CSVInputStream& in, std::string& target) {
if (!in.input) return in;
std::getline(in.input, target , ',');
return in;
}
template <typename T>
CSVInputStream& operator>>(CSVInputStream& in, T& target) {
if (!in.input) return in;
std::string line;
std::getline(in.input, line , ',');
std::stringstream translator;
translator << line;
translator >> target;
return in;
}
//--------------------------------------------------------------------
// Usage follow, perhaps in another file
//--------------------------------------------------------------------
#include <fstream>
#include <iostream>
int main() {
std::ifstream file;
file.open("testcsv.csv");
CSVInputStream input(file);
std::string sentence_type;
double track_made_good;
char code;
double unused;
double speed_kph;
char speed_unit_kph;
double speed_kmh;
char speed_unit_kmh;
input >> sentence_type >> track_made_good >> code;
input >> unused >> unused;
input >> speed_kph >> speed_unit_kph;
input >> speed_kmh >> speed_unit_kmh;
std::cout << sentence_type << " - " << track_made_good << " - ";
std::cout << speed_kmh << " " << speed_unit_kmh << " - ";
std::cout << speed_kph << " " << speed_unit_kph << std::endl;;
}
This separates the comma separation from the reading of the values, and can be reused on
most other comma separated stuff.
If you want use C++ style code based on fstream:
fin.open(input);
cout << "readed";
string str;
getline(fin, str); // read one line per time

Loop iteration issue c++

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
using namespace std;
int main()
{
string line;
ifstream infile ("Input.csv");
vector<string> table;
string word;
if(infile.is_open())
{
getline(infile,line);
istringstream iss(line);
while(!iss.eof())
{
getline(iss,word, ',');
table.push_back(word);
}
}
for(int index=0; index<11; ++index)
{
cout<< "Element" << index << ":" << table.at(index) << endl ;
}
infile.close();
}
In the above program I am reading values from input file and splitting based on comma and finally storing the values into a vector.
when I print vector I am able to view only the first line of input file.
Input file:
CountryCode,Country,ItemCode,Item,ElementGroup,ElementCode,Element,Year,Unit,Value,Flag
100,India,3010,Population - Est. & Proj.,511,511,Total Population - Both sexes,1961,1000,456950,
100,India,3010,Population - Est. & Proj.,511,511,Total Population - Both sexes,1962,1000,466337,
100,India,3010,Population - Est. & Proj.,511,511,Total Population - Both sexes,1963,1000,476025,
100,India,3010,Population - Est. & Proj.,511,511,Total Population - Both sexes,1964,1000,486039,
Output:
Element0:CountryCode
Element1:Country
Element2:ItemCode
Element3:Item
Element4:ElementGroup
Element5:ElementCode
Element6:Element
Element7:Year
Element8:Unit
Element9:Value
Element10:Flag
Problem: Only 1st line is being printed
I suggest rewriting it like this:
int main()
{
string line;
ifstream infile ("Input.csv");
vector<string> table;
string word;
while(getline(infile, line))
{
istringstream iss(line);
while(getline(iss,word, ','))
{
table.push_back(word);
}
}
for(int index=0; index<11; ++index)
{
cout<< "Element" << index << ":" << table.at(index) << endl ;
}
infile.close();
}
The stream will return false from getline and most other operations whenever it is invalid. So if it didn't open, the while loop won't run. And when it reaches EOF, the while loop will stop. Much simpler to read this way I think.
You have several issues, addressed below:
int main()
{
std::string line;
std::ifstream infile ("Input.csv");
std::vector<std::string> table;
while (std::getline(infile, line)) // this is the loop you want to read the file
{
std::istringstream iss(line);
std::string word;
while (std::getline(iss, word, ',')) // there are better ways to do this, but this will work
{
table.push_back(word);
}
}
for(int index=0; index<table.size(); ++index) // loop through the whole size
{
std::cout<< "Element" << index << ":" << table[index] << std::endl ;
}
infile.close();
return 0;
}
Alternatively, you can avoid the use of nested while loops altogether:
struct csv_reader : std::ctype<char>
{
csv_reader() : std::ctype<char>(get_table()) {}
static std::ctype_base::mask const* get_table()
{
static std::vector<std::ctype_base::mask> rc(table_size, std::ctype_base::mask());
rc['\n'] = std::ctype_base::space;
rc[','] = std::ctype_base::space;
return &rc[0];
}
};
int main()
{
std::string line;
std::ifstream infile ("Input.csv");
csv_reader reader;
infile.imbue(std::locale(std::locale(), &reader);
std::vector<std::string> table{std::istream_iterator<std::string>(infile), std::istream_iterator<std::string>()};
// or
//std::vector<std::string> table;
//std::copy(std::istream_iterator<std::string>(infile), std::istream_iterator<std::string>(), std::back_inserter(table));
for(int index=0; index<table.size(); ++index) // loop through the whole size
{
std::cout<< "Element" << index << ":" << table[index] << std::endl ;
}
infile.close();
return 0;
}
You read only one line of the file
if(infile.is_open())
{
getline(infile,line);
istringstream iss(line);
while(!iss.eof())
{
getline(iss,word, ',');
table.push_back(word);
}
}
If you need to read all lines of the file then you can write instead
while (getline(infile,line))
{
istringstream iss(line);
while(!iss.eof())
{
getline(iss,word, ',');
table.push_back(word);
}
}
You only read the first line.
Add a loop with a condition like
while (getline(infile, line)) {
...
}
Your for loop only print the first 11 posts from the array.
You should it to the lenght of the array.
Not sure what the syntax is for c++ for length of the table but that should be the issue.
for(int index=0; index<table.size(); ++index)
{
cout<< "Element" << index << ":" << table.at(index) << endl ;
}