Problem with converting vector of string to vector of doubles - c++

I am trying to write a program that reads some numerical values from a .csv file, stores them in a std::vector<std::string>, and then converts these values into doubles and stores them in a std::vector<double>.
I am trying to do the conversion using stringstreams, which has worked fine for me in the past.
I have managed to import the numerical values and store them in the std::vector<std::string>, however I am getting a weird problem when trying to do the conversions to double. Only the very first value is stored in the std::vector<double> with a lot of significant figures missing, and the other entries are just ignored and not stored in the std::vector<double> at all.
Here is my code so far:
#include <string>
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
double extract_double(std::string str)
{
std::stringstream ss;
double grade;
//Pass all the course details to string stream
ss << str;
//Extract the double type part of the string stream which is the course grade
ss >> grade;
str = "";
ss.ignore();
return grade;
}
int main()
{
std::ifstream my_input_file;
std::string file_name;
my_input_file.open("scale_free_gamma_2_fitnesses.csv");
int number_of_data_in_file;
std::vector<std::string> fitnesses_string;
std::vector<double> fitnesses;
std::string string_temp;
while (my_input_file.good()) {
//Extract strings from file
std::getline(my_input_file, string_temp, ',');
fitnesses_string.push_back(string_temp);
}
for (auto fitnesses_it = fitnesses_string.begin();
fitnesses_it < fitnesses_string.end(); ++fitnesses_it){
fitnesses.push_back(extract_double(*fitnesses_it));
}
for (auto fitnesses_itt = fitnesses.begin();
fitnesses_itt < fitnesses.end(); ++fitnesses_itt){
std::cout << *fitnesses_itt << std::endl;
}
return 0;
}

You should be reading individual lines from the file first, and then splitting up each line on commas.
And there are easier ways to handle the rest of your code, too.
Try something more like this instead:
#include <string>
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
int main()
{
std::ifstream my_input_file("scale_free_gamma_2_fitnesses.csv");
std::vector<std::string> fitnesses_string;
std::vector<double> fitnesses;
std::string line, string_temp;
while (std::getline(my_input_file, line)) {
//Extract strings from line
std:::istringstream iss(line);
while (std::getline(iss, string_temp, ','))
fitnesses_string.push_back(string_temp);
}
for (const auto &s : fitnesses_string){
fitnesses.push_back(std:stod(s));
}
for (auto value : fitnesses){
std::cout << value << std::endl;
}
return 0;
}
In which case, even simpler would be to just get rid of the std::vector<std::string> altogether:
#include <string>
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
int main()
{
std::ifstream my_input_file("scale_free_gamma_2_fitnesses.csv");
std::vector<double> fitnesses;
std::string line, string_temp;
while (std::getline(my_input_file, line)) {
//Extract strings from line
std:::istringstream iss(line);
while (std::getline(iss, string_temp, ','))
fitnesses.push_back(std:stod(string_temp));
}
for (auto value : fitnesses){
std::cout << value << std::endl;
}
return 0;
}

A few things. First, there's a far better way to loop over your vectors.
for (const std::string &str: fitnesses_string) {
}
These are referred to as range-based for-loops, and I think you can see how much cleaner this syntax is. In modern C++, you rarely need to use iterators anymore. (I won't say never, but rarely.)
Next, your inner loop makes no sense at all. Instead, just do it quite simply:
for (const std::string &str: fitnesses_string) {
fitnesses.push_back(extract_double(str));
}
Now, let's talk about how to convert a string to double.
fitnesses.push_back(std::stod(str));
So you don't need your method. There's already a method waiting for you. It's defined in #include <string>.

Related

How to get input an array of strings with \n as delimiter?

#include<bits/stdc++.h>
using namespace std;
int main()
{
int i=0;
char a[100][100];
do {
cin>>a[i];
i++;
}while( strcmp(a[i],"\n") !=0 );
for(int j=0;j<i;i++)
{
cout<<a[i]<<endl;
}
return 0;
}
Here , i want to exit the do while loop as the users hits enter .But, the code doesn't come out of the loop..
The following reads one line and splits it on white-space. This code is not something one would normally expect a beginner to write from scratch. However, searching on Duckduckgo or Stackoverflow will reveal lots of variations on this theme. When progamming, know that you are probably not the first to need the functionality you seek. The engineering way is to find the best and learn from it. Study the code below. From one tiny example, you will learn about getline, string-streams, iterators, copy, back_inserter, and more. What a bargain!
#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <vector>
int main() {
using namespace std;
vector<string> tokens;
{
string line;
getline(cin, line);
istringstream stream(line);
copy(istream_iterator<string>(stream),
istream_iterator<string>(),
back_inserter(tokens));
}
for (auto s : tokens) {
cout << s << '\n';
}
return 0;
}
First of all, we need to read the line until the '\n' character, which we can do with getline(). The extraction operator >> won't work here, since it will also stop reading input upon reaching a space. Once we get the whole line, we can put it into a stringstream and use cin >> str or getline(cin, str, ' ') to read the individual strings.
Another approach might be to take advantage of the fact that the extraction operator will leave the delimiter in the stream. We can then check if it's a '\n' with cin.peek().
Here's the code for the first approach:
#include <iostream> //include the standard library files individually
#include <vector> //#include <bits/stdc++.h> is terrible practice.
#include <sstream>
int main()
{
std::vector<std::string> words; //vector to store the strings
std::string line;
std::getline(std::cin, line); //get the whole line
std::stringstream ss(line); //create stringstream containing the line
std::string str;
while(std::getline(ss, str, ' ')) //loops until the input fails (when ss is empty)
{
words.push_back(str);
}
for(std::string &s : words)
{
std::cout << s << '\n';
}
}
And for the second approach:
#include <iostream> //include the standard library files individually
#include <vector> //#include <bits/stdc++.h> is terrible practice.
int main()
{
std::vector<std::string> words; //vector to store the strings
while(std::cin.peek() != '\n') //loop until next character to be read is '\n'
{
std::string str; //read a word
std::cin >> str;
words.push_back(str);
}
for(std::string &s : words)
{
std::cout << s << '\n';
}
}
You canuse getline to read ENTER, run on windows:
//#include<bits/stdc++.h>
#include <iostream>
#include <string> // for getline()
using namespace std;
int main()
{
int i = 0;
char a[100][100];
string temp;
do {
getline(std::cin, temp);
if (temp.empty())
break;
strcpy_s(a[i], temp.substr(0, 100).c_str());
} while (++i < 100);
for (int j = 0; j<i; j++)
{
cout << a[j] << endl;
}
return 0;
}
While each getline will got a whole line, like "hello world" will be read once, you can split it, just see this post.

Split String to Vector with Whitespaces c++ error

#include <iostream>
#include <string>
#include <vector>
#include <sstream>
using namespace std;
vector<string> split_string(string s)
{
string buf;
stringstream ss(s);
vector<string> tokens;
while (ss >> buf)
tokens.push_back(buf);
return tokens;
}
int main()
{
cout << split_string("Alpha Beta Gamma");
}
when i try to split a string into a vector by using whitespaces i am not able to print out my solution.
i doesnt let me use std::cout but in my function the return value is given
why cant i use it like that? how do i fix this?
std::cout cannot take a vector, you need to iterate through the container and print each element separately, try using something like this:
int main()
{
string originalString = "Alpha Beta Gamma";
for (const auto& str : split_string(originalString))
cout << str << '\n';
return 0;
}

How to read a txt file and put it on a array with c++?

I have this .txt file that has a lot of words ( one each line ).
I tried
ifstream myReadFile;
myReadFile.open("restrict_words.txt");
char output[100];
if (myReadFile.is_open()) {
while (!myReadFile.eof()) {
printf("mamao");
myReadFile >> output;
cout<<output;
}
}
But i dont know how to make it work like... where should i pass it path and stuff
I would like to do
while(reading){
stringArray.add(file.line);
}
How can i do that?
First, this: (!myReadFile.eof()) is wrong. See the link for why. Second. If all you want is to load a file of strings into an array, this will do it:
#include <iostream>
#include <fstream>
#include <iterator>
#include <string>
#include <vector>
int main()
{
std::ifstream inp("restrict_words.txt");
std::istream_iterator<std::string> inp_it(inp), inp_eof;
std::vector<std::string> words(inp_it, inp_eof);
// words now has ever whitespace separated string
// from the input file as a vector entry
for (auto s : words)
std::cout << s << '\n';
}
Suggested reading:
std::vector<>
std::string
std::istream_iterator<>
C++11 Range-based for loop
Do you mean this?
//untested
#include <vector>
#include <fstream>
#include <string>
#include <iostream> //edited
int main()
{
std::ifstream ist("restrict_words.txt");
std::string word;
std::vector<std::string> readWords;
while(ist >> word)
readWords.push_back(word);
//test
for(unsigned i = 0; i != readWords.size(); ++i)
std::cout << readWords.at(i) << '\n'; // or readWords[i] (not range checked)
}
EDIT:
For each individual line you would do:
std::string line;
std::vector<std::string> readLines;
while(std::getline(ist, line))
{
readLines.push_back(line);
}

C++ Converting a String to Double

I've been trying to find the solution for this all day! You might label this as re-post but what I'm really looking for is a solution without using boost lexical cast. A traditional C++ way of doing it would be great. I tried this code but it returns a set of gibberish numbers and letters.
string line;
double lineconverted;
istringstream buffer(line);
lineconverted;
buffer >> lineconverted;
And I alse tried this, but it ALWAYS returns 0.
stringstream convert(line);
if ( !(convert >> lineconverted) ) {
lineconverted = 0;
}
Thanks in advance :)
EDIT: For the first solution I used (gibberish).. Here's a snapshot
#include <sstream>
int main(int argc, char *argv[])
{
double f = 0.0;
std::stringstream ss;
std::string s = "3.1415";
ss << s;
ss >> f;
cout << f;
}
The good thing is, that this solution works for others also, like ints, etc.
If you want to repeatedly use the same buffer, you must do ss.clear in between.
There is also a shorter solution available where you can initialize the value to a stringstream and flush it to a double at the same time:
#include <sstream>
int main(int argc, char *argv[]){
stringstream("3.1415")>>f ;
}
Since C++11 you could use std::stod function:
string line;
double lineconverted;
try
{
lineconverted = std::stod(line);
}
catch(std::invalid_argument)
{
// can't convert
}
But solution with std::stringstream also correct:
#include <sstream>
#include <string>
#include <iostream>
int main()
{
std::string str;
std::cin >> str;
std::istringstream iss(str);
double d = 0;
iss >> d;
std::cout << d << std::endl;
return 0;
}
If you want to store (to a vector for example) all the doubles of a line
#include <iostream>
#include <vector>
#include <iterator>
int main()
{
std::istream_iterator<double> in(std::cin);
std::istream_iterator<double> eof;
std::vector<double> m(in,eof);
//print
std::copy(m.begin(),m.end(),std::ostream_iterator<double>(std::cout,"\n"));
}

Reading parts of an input file

I would like to read an input file in C++, for which the structure (or lack of) would be something like a series of lines with text = number, such as
input1 = 10
input2 = 4
set1 = 1.2
set2 = 1.e3
I want to get the number out of the line, and throw the rest away. Numbers can be either integers or doubles, but I know when they are one or other.
I also would like to read it such as
input1 = 10
input2=4
set1 =1.2
set2= 1.e3
so as to be more robust to the user. I think this means that it shouldn't be red in a formatted fashion.
Anyway, is there a smart way to do that?
I have already tried the following, but with minimal knowledge of what I've been doing, so the result was as expected... no success.
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include <math.h>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdlib>
#include <boost/lexical_cast.hpp>
#include <string>
using namespace std;
using namespace boost;
int main(){
string tmp;
char temp[100];
int i,j,k;
ifstream InFile("input.dat");
//strtol
InFile.getline(temp,100);
k=strtol(temp,0,10);
cout << k << endl;
//lexical_cast
InFile.getline(temp,100);
j = lexical_cast<int>(temp);
cout << j << endl;
//Direct read
InFile >> tmp >> i;
cout << i << endl;
return 0;
}
Simply read one line at a time.
Then split each line on the '=' sign. Use the stream functionality do the rest.
#include <sstream>
#include <fstream>
#include <iostream>
#include <string>
int main()
{
std::ifstream data("input.dat");
std::string line;
while(std::getline(data,line))
{
std::stringstream str(line);
std::string text;
std::getline(str,text,'=');
double value;
str >> value;
}
}
With error checking:
#include <sstream>
#include <fstream>
#include <iostream>
#include <string>
int main()
{
std::ifstream data("input.dat");
std::string line;
while(std::getline(data,line))
{
std::stringstream str(line);
std::string text;
double value;
if ((std::getline(str,text,'=')) && (str >> value))
{
// Happy Days..
// Do processing.
continue; // To start next iteration of loop.
}
// If we get here. An error occurred.
// By doing nothing the line will be ignored.
// Maybe just log an error.
}
}
There are already some fine solutions here. However, just to throw it out there, some comments implied that Boost Spirit is an inappropriate solution for this problem. I'm not sure I completely disagree. However, the following solution is very terse, readable (if you know EBNF) and error-tolerant. I'd consider using it.
#include <fstream>
#include <string>
#include <boost/spirit.hpp>
using namespace std;
using namespace boost::spirit;
int main()
{
ifstream data("input.dat");
string line;
vector<double> numbers;
while(getline(data,line))
{
parse(line.c_str(),
*(+~ch_p('=') >> ch_p('=') >> real_p[push_back_a(numbers)]),
space_p);
}
}
Off the top of my head:
vector<double> vals(istream &in) {
vector<double> r;
string line;
while (getline(f, line)) {
const size_t eq = line.find('=');
if (eq != string::npos) {
istringstream ss(line.substr(eq + 1));
double d = 0;
ss >> d;
if (ss) r.push_back(d);
else throw "Line contains no value";
}
else {
throw "Line contains no =";
}
}
return r;
}
int main(int argc, char *argv[]) {
vector<double> vs = vals(ifstream(argv[1]));
}
C FTW (modified to handle doubles)
#include <stdio.h>
int
main ()
{
double num;
while (!feof (stdin))
if (1 == fscanf (stdin, "%*[^=] = %lf", &num))
printf ("%g\n", num);
return 0;
}
now that you are already using boost with lexical_cast, just parse each line with boost::split() and boost::is_any_of() into 1 2-element vector, with token_compress turned on.
the following code illustrates the parse, but skips the numeric conversion, which could be solved easily with boost lexical_cast.
#include <fstream>
#include <sstream>
#include <string>
#include <iostream>
#include <vector>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/foreach.hpp>
using std::string;
using std::cout;
using std::ifstream;
using std::stringstream;
using std::vector;
std::string file_to_string()
{
ifstream data("data.txt");
stringstream s;
s << data.rdbuf();
return s.str();
}
void print_parameter(vector<string>& v)
{
cout << v_para[0];
cout << "=";
cout << v_para[1];
cout << std::endl;
}
vector<string> string_to_lines(const string& s)
{
return v_lines;
}
int main()
{
vector<string> v_lines;
boost::split(v_lines, file_to_string(), boost::is_any_of("\n"), boost::token_compress_on);
vector<string> v_para;
BOOST_FOREACH(string& line, v_lines)
{
if(line.empty()) continue;
boost::split(v_para, line, boost::is_any_of(" ="), boost::token_compress_on);
// test it
print_parameter(v_para);
}
}
If you are devising this format, I would suggest adopting the INI file format.
The lightweight syntaxed INI format includes sections (allows you to have a little more structure in the format) which may or may not be desirable in your case:
I.e.
[section_1]
variable_1=value1
variable_2=999
[sectionA]
variable_A=value A
variable_B=111
The external links on this wikipedia page list a number of libraries that can be used for working with these types of files that extend/replace the basic GetPrivateProfileString functions from the Windows API and support other platforms.
Most of these would handle the space padded = sign (or at least before the = since a space after the = may be intentional/significant.
Some of these libraries might also have an option to omit [sections] if you don't want that (my own C++ class for handling INI like format files has this option).
The advantage to these libraries and/or using the Windows API GetPrivateProfileXXX functions is that your program can access specific variables
(I.e. get or set the value for variable_A from sectionA) without your program having to
write/scan/rewrite the entire file.
Here's my quickest STL solution:
#include <fstream>
#include <list>
#include <locale>
void foo()
{
std::fstream f("c:\\temp\\foo.txt", std::ios_base::in);
std::list<double> numbers;
while (!f.eof())
{
int c = f.get();
if (std::isdigit(c, std::locale::classic()) ||
c == '+' ||
c == '-' ||
c == '.')
{
f.putback(c);
double val;
f >> val;
if (f.fail()) {
f.clear(f.eof() ? std::ios_base::eofbit : std::ios_base::goodbit);
continue;
}
else
{
numbers.push_back(val);
}
}
}
}
Just tested this... it works, and doesn't require anything outside of the C++ standard library.
#include <iostream>
#include <map>
#include <string>
#include <algorithm>
#include <iterator>
#include <cctype>
#include <sstream>
using namespace std; // just because this is an example...
static void print(const pair<string, double> &p)
{
cout << p.first << " = " << p.second << "\n";
}
static double to_double(const string &s)
{
double value = 0;
istringstream is(s);
is >> value;
return value;
}
static string trim(const string &s)
{
size_t b = 0;
size_t e = s.size();
while (b < e && isspace(s[b])) ++b;
while (e > b && isspace(s[e-1])) --e;
return s.substr(b, e - b);
}
static void readINI(istream &is, map<string, double> &values)
{
string key;
string value;
while (getline(is, key, '='))
{
getline(is, value, '\n');
values.insert(make_pair(trim(key), to_double(value)));
}
}
int main()
{
map<string, double> values;
readINI(cin, values);
for_each(values.begin(), values.end(), print);
return 0;
}
EDIT: I just read the original question and noticed I'm not producing an exact answer. If you don't care about the key names, juts discard them. Also, why do you need to identify the difference between integer values and floating-point values? Is 1000 an integer or a float? What about 1e3 or 1000.0? It's easy enough to check if a given floating-point value is integral, but there is a clas of numbers that are both valid integers and valid floating-point values, and you need to get into your own parsing routines if you want to deal with that correctly.