C++ Converting a String to Double - c++

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"));
}

Related

Problem with converting vector of string to vector of doubles

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>.

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.

reading data file into 2d array c++

I have a text file with 2 columns and many rows. each column is separated by spaces. i need to read them to a 2D array for further calculations.
my data file looks like
0.5 0.479425539
1 0.841470985
1.5 0.997494987
2 0.909297427
2.5 0.598472144
3 0.141120008
3.5 -0.350783228
4 -0.756802495
4.5 -0.977530118
5 -0.958924275
And my feeble attempt is
#include <iostream>
#include <fstream>
#include <string>
#include <conio.h>
#include <ctype.h>
using namespace std;
int main () {
char line,element;
std::ifstream myfile ("C:\\Users\\g\\Desktop\\test.txt");
if (myfile.is_open())
{
while ( myfile.good() )
{
getline(myfile,line);
cout << line<<endl;
_getch();
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
The problem is I'm not able to read them correctly.... its either reading the whole line... if I specify the delimiter as 'space' then, its not reading the next row.
Pls point out whats wrong. and what should i do to store the data into 2d array for further calculations.
Thank you
#include <fstream>
#include <string>
#include <sstream>
#include <iostream>
#include <vector>
int main(int argc, char** argv) {
std::ifstream f(argv[1]);
std::string l;
std::vector<std::vector<double> > rows;
while(std::getline(f, l)) {
std::stringstream s(l);
double d1;
double d2;
if(s >> d1 >> d2) {
std::vector<double> row;
row.push_back(d1);
row.push_back(d2);
rows.push_back(row);
}
}
for(int i = 0; i < rows.size(); ++i)
std::cout << rows[i][0] << " " << rows[i][1] << '\n';
}
The last for loop shows how to use the values in the "array". The variable rows is strictly speaking not an array, but a vector of vectors. However, a vector is much safer than c-style arrays, and allows access to its elements using [].
[As I posted this I saw a very similar program posted as a response. I wrote mine independently.]
You can read the whole line into a std::string, then use std::istringstream to extract the values from the line.
A complete working program:
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
int main()
{
std::ifstream file("C:\\Users\\g\\Desktop\\test.txt");
std::string line;
// Read a line of input from the file
while (std::getline(file, line))
{
// `istringstream` behaves like a normal input stream
// but can be initialized from a string
std::istringstream iss(line);
float value;
// The input operator `>>` returns the stream
// And streams can be used as a boolean value
// A stream is "true" as long as everything is okay
while (iss >> value)
{
std::cout << "Value = " << value << '\t';
}
// Flush the standard output stream and print a newline
std::cout << std::endl;
}
}
Given the contents in the file being as in the question, the first three lines of output should be:
Value = 0.5 Value = 0.479425539
Value = 1 Value = 0.841470985
Value = 1.5 Value = 0.997494987
For a 2d-array, I would use a std::vector of std::array:
#include <vector>
#include <array>
...
std::vector<std::array<float, 2>> array;
...
float value1, value2;
if (iss >> value1 >> value2)
{
std::cout << "Values = " << value1 << ", " << value2;
array.emplace_back(std::array<int, 2>{{value1, value2}});
}
Now the first line values are array[0][0] and array[0][1], and the last lines values are array[array.size() - 1][0] and array[array.size() - 1][1].
As C++ has evolved over the years, below is a Modern C++ version.
It uses auto where possible
Uses std::pair to hold 2 values (A std::pair is a specific case of a std::tuple with two elements)
Does not close file (destructor does that at end of block)
Does not read line by line, as the stream uses <space> and <enter> as delimiters
The variables have meaningful names, so the program "reads" easily,
Uses a range for loop to output the data.
Doesn't bring the whole std namespace into the code - Why is “using namespace std” considered bad practice?
.
#include <fstream>
#include <iostream>
#include <vector>
#include <utility>
int main( int argc, char** argv )
{
if ( argc < 1 )
return -1;
const auto fileName = argv[ 1 ];
std::ifstream fileToRead( fileName );
typedef std::pair< double, double > DoublesPair;
std::vector< DoublesPair > rowsOfDoublesPair;
DoublesPair doublePairFromFile;
while ( fileToRead >> doublePairFromFile.first >> doublePairFromFile.second )
{
rowsOfDoublesPair.push_back( doublePairFromFile );
}
for ( const auto row : rowsOfDoublesPair )
std::cout << row.first << " " << row.second << '\n';
}

get list of numbers from stdin and tokenize them

How would I get a list of numbers from the user and then tokenize them.
This is what I have but it doesn't get anything except for the first number:
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
using namespace std;
int main()
{
string line = "";
cin >> line;
stringstream lineStream(line);
int i;
vector<int> values;
while (lineStream >> i)
values.push_back(i);
for(int i=0; i<values.size(); i++)
cout << values[i] << endl;
system("PAUSE");
return 0;
}
Related Posts:
C++, Going from string to stringstream to vector
Int Tokenizer
Here is probably the easiest way to read values from cin into a container:
#include <iostream>
#include <iterator>
#include <vector>
int main()
{
std::vector<int> values;
std::copy(
std::istream_iterator<int>(std::cin),
std::istream_iterator<int>(),
std::back_inserter(values));
// For symmetry with the question copy back to std::cout
std::copy(
values.begin(),
values.end(),
std::ostream_iterator<int>(std::cout,"\n"));
}
I believe cin >> breaks on whitespace, which means you're only getting the first number entered.
try:
getline(cin, line);
Like Donnie mentioned cin breaks on whitespace, so do overcome this we can use a 'getline()', the following example works nicely:
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
using namespace std;
int main()
{
string line = "";
::getline(std::cin,line,'\n');
std::stringstream lineStream(line);
int i;
std::vector<int> values;
while (lineStream >> i)
values.push_back(i);
for(int i=0; i<values.size(); i++)
cout << values[i] << endl;
system("PAUSE");
return 0;
}
on top of main
string line = "";
getline (cin, line );
stringstream lineStream(line);
Yep, and is the string version of getline, no the istream one.
OK: Pavel Minaev has the best answer.
But all the people mentioning that cin breaks on white space.
That is a good thing (because it also ignores white space);
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
using namespace std;
int main()
{
int i;
vector<int> values;
// prefer to use std::copy() but this works.
while (std::cin >> i)
{
values.push_back(i);
}
// prefer to use std::copy but this works.
for(vector<int>::const_iterator loop = values.begin();loop != values.end();++loop)
{
cout << *loop << endl;
}
return 0;
}

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.