C++ string to double conversion - c++

Usually when I write anything in C++ and I need to convert a char into an int I simply make a new int equal to the char.
I used the code(snippet)
string word;
openfile >> word;
double lol=word;
I receive the error that
Code1.cpp cannot convert `std::string' to `double' in initialization
What does the error mean exactly? The first word is the number 50. Thanks :)

You can convert char to int and viceversa easily because for the machine an int and a char are the same, 8 bits, the only difference comes when they have to be shown in screen, if the number is 65 and is saved as a char, then it will show 'A', if it's saved as a int it will show 65.
With other types things change, because they are stored differently in memory. There's standard function in C that allows you to convert from string to double easily, it's atof. (You need to include stdlib.h)
#include <stdlib.h>
int main()
{
string word;
openfile >> word;
double lol = atof(word.c_str()); /*c_str is needed to convert string to const char*
previously (the function requires it)*/
return 0;
}

#include <iostream>
#include <string>
using namespace std;
int main()
{
cout << stod(" 99.999 ") << endl;
}
Output: 99.999 (which is double, whitespace was automatically stripped)
Since C++11 converting string to floating-point values (like double) is available with functions:
stof - convert str to a float
stod - convert str to a double
stold - convert str to a long double
As conversion of string to int was also mentioned in the question, there are the following functions in C++11:
stoi - convert str to an int
stol - convert str to a long
stoul - convert str to an unsigned long
stoll - convert str to a long long
stoull - convert str to an unsigned long long

The problem is that C++ is a statically-typed language, meaning that if something is declared as a string, it's a string, and if something is declared as a double, it's a double. Unlike other languages like JavaScript or PHP, there is no way to automatically convert from a string to a numeric value because the conversion might not be well-defined. For example, if you try converting the string "Hi there!" to a double, there's no meaningful conversion. Sure, you could just set the double to 0.0 or NaN, but this would almost certainly be masking the fact that there's a problem in the code.
To fix this, don't buffer the file contents into a string. Instead, just read directly into the double:
double lol;
openfile >> lol;
This reads the value directly as a real number, and if an error occurs will cause the stream's .fail() method to return true. For example:
double lol;
openfile >> lol;
if (openfile.fail()) {
cout << "Couldn't read a double from the file." << endl;
}

If you are reading from a file then you should hear the advice given and just put it into a double.
On the other hand, if you do have, say, a string you could use boost's lexical_cast.
Here is a (very simple) example:
int Foo(std::string anInt)
{
return lexical_cast<int>(anInt);
}

The C++ way of solving conversions (not the classical C) is illustrated with the program below. Note that the intent is to be able to use the same formatting facilities offered by iostream like precision, fill character, padding, hex, and the manipulators, etcetera.
Compile and run this program, then study it. It is simple
#include "iostream"
#include "iomanip"
#include "sstream"
using namespace std;
int main()
{
// Converting the content of a char array or a string to a double variable
double d;
string S;
S = "4.5";
istringstream(S) >> d;
cout << "\nThe value of the double variable d is " << d << endl;
istringstream("9.87654") >> d;
cout << "\nNow the value of the double variable d is " << d << endl;
// Converting a double to string with formatting restrictions
double D=3.771234567;
ostringstream Q;
Q.fill('#');
Q << "<<<" << setprecision(6) << setw(20) << D << ">>>";
S = Q.str(); // formatted converted double is now in string
cout << "\nThe value of the string variable S is " << S << endl;
return 0;
}
Prof. Martinez

Coversion from string to double can be achieved by
using the 'strtod()' function from the library 'stdlib.h'
#include <iostream>
#include <stdlib.h>
int main ()
{
std::string data="20.9";
double value = strtod(data.c_str(), NULL);
std::cout<<value<<'\n';
return 0;
}

#include <string>
#include <cmath>
double _string_to_double(std::string s,unsigned short radix){
double n = 0;
for (unsigned short x = s.size(), y = 0;x>0;)
if(!(s[--x] ^ '.')) // if is equal
n/=pow(10,s.size()-1-x), y+= s.size()-x;
else
n+=( (s[x]-48) * pow(10,s.size()-1-x - y) );
return n;
}
or
//In case you want to convert from different bases.
#include <string>
#include <iostream>
#include <cmath>
double _string_to_double(std::string s,unsigned short radix){
double n = 0;
for (unsigned short x = s.size(), y = 0;x>0;)
if(!(s[--x] ^ '.'))
n/=pow(radix,s.size()-1-x), y+= s.size()-x;
else
n+=( (s[x]- (s[x]<='9' ? '0':'0'+7) ) * pow(radix,s.size()-1-x - y) );
return n;
}
int main(){
std::cout<<_string_to_double("10.A",16)<<std::endl;//Prints 16.625
std::cout<<_string_to_double("1001.1",2)<<std::endl;//Prints 9.5
std::cout<<_string_to_double("123.4",10)<<std::endl;//Prints 123.4
return 0;
}

Related

How to make conversion function work?

I have a code that I'm trying to learn how to parse in C++. I understood everything I did, but I don't understand how to work with the likes of atoi(), atof (), strtod (). I know what it's supposed to do, but I don't understand why the compiler doesn't like it. My focus on the error is "scores[line_count] = strtod (score);"
#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <iomanip>
using namespace std;
int readScores(string inputFile, string name[], float scores[], int array_size)
{
//delcare variables
ifstream infile;
int line_count = 0;
string line;
string named;
float score;
char character;
int word_index;
string names[array_size];
// open input file
infile.open(inputFile);
//Check if file opens succesfully.
if(infile.fail())
{
cout << "File cannot open!!" << endl;
return -1;
}
while(getline(infile, line))
{
cout << line << endl;
// PARSING GOES HERE
word_index = 0;
for(int i=0; i < (int)line.length(); i++)
{
character = line[i];
if (character == ',')
{
names[line_count] = named;
named = "";
word_index++;
}
else
{
if(word_index == 0)
{
named += character;
}
else if (word_index == 1)
{
score += character;
cout << character << " " << endl;
}
}
}
scores[line_count] = strtod (score);
line_count++;
}
//close file
infile.close();
//return line count
return line_count;
cout << line_count << endl;
}
int main(void)
{
int array_size = 50;
string inputFile = "Test.txt";
string name [array_size];
float scores [array_size];
readScores(inputFile, name, scores, array_size);
}
The function strtod() takes the form
double strtod (const char* str, char** endptr);
But you only give it the string.
As you can see it takes two parameters, the string you wish to convert to a double, and an "endptr". The endptr is described here as a
Reference to an already allocated object of type char*, whose value is set by > the function to the next character in str after the numerical value.
This parameter can also be a null pointer, in which case it is not used.
So you need to declare a char pointer to save the next character after the decimal, even if there wont be one. This allows you to pull multiple doubles from a single string, much like a tokenizer.
char * endPtr;
scores[line_count] = strtod(score, &endPtr);
Edit
As Alex Lop pointed out, you aren't even passing a string to strtod, you're passing a float. It appears you would like to cast the float to a double?
Of course the compiler doesn't like it. Please read the description of strtod.
double strtod (const char* str, char** endptr);
Convert string to
double.
Parses the C-string str interpreting its content as a floating
point number (according to the current locale) and returns its value
as a double. If endptr is not a null pointer, the function also sets
the value of endptr to point to the first character after the number.
The function first discards as many whitespace characters (as in
isspace) as necessary until the first non-whitespace character is
found. Then, starting from this character, takes as many characters as
possible that are valid following a syntax resembling that of floating
point literals (see below), and interprets them as a numerical value.
A pointer to the rest of the string after the last valid character is
stored in the object pointed by endptr.
And in your code you pass to strtod only one parameter which is of type float and store the returned result of double into an array of floats. If you want to move the value of float from one variable to another, you don't need any "convertion" function:
scores[line_count] = score;
NOTE: I didn't really review your code as you asked specifically about scores[line_count] = strtod (score);. But after I looked how you modify score, maybe it should have been string and not float. If so, then it is the another point to fix.

Convert string to double variable which is seperated by a comma(0,07)

In C++ I've got a double variable to be read which is seperated by a comma(0,07).I am first reading it a string from an excel and trying to converting it into a double.
string str = "0,07"; // Actually from Excel.
double number = strtod(str .c_str(), NULL);
double number1 = atof(str .c_str());
cout << number<<endl;
cout <<number1<<endl;
Both of them return 0 as output instead of 0.07. can someone explain me how to convert double to 0.07 instead of 0.
You can define a customized numeric facet (numpunct) for it:
class My_punct : public std::numpunct<char> {
protected:
char do_decimal_point() const {return ',';}//comma
};
and then use a stringstream and locale with it:
stringstream ss("0,07");
locale loc(locale(), new My_punct);
ss.imbue(loc);
double d;
ss >> d;
DEMO
The problem is that the default locale is the "C" (for "Classic"), that uses '.' as decimal separator, while excel use the one of the OS. that is most likely the one of a lain language.
You can either:
ask the originator of the data to export with an english-like locale
set in your program a locale based on std::locale("")(so that your program work with the system locale -admitting they are the same, see http://en.cppreference.com/w/cpp/locale/locale)
set you program with a latin-based locale (IT, or ES, for example)
ignore locales and replace the ","-s in the string with "."-s before try to interpret it as number. (see std::replace)
Would this be fine ?
#include <string>
#include <iostream>
using namespace std;
int main()
{
string str = "0,07"; // Actually from Excel.
int index = str.find(',');
str.replace(index, index+1, '.');
double number = stod(str);
cout << number << endl;
return 0;
}
PS: stod is a c++11 function, but you need to use it instead of stof if you want to keep the double precision. Otherwise number should be a float
You can use:
std::replace(str.begin(), str.end(), ',', '.'); // #include <algorithm>
to replace the comma by a dot before converting.
Working example:
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
string str = "0,07"; // Actually from Excel.
replace(str.begin(), str.end(), ',', '.');
double number = strtod(str.c_str(), NULL);
double number1 = atof(str.c_str());
cout << number << endl;
cout << number1 << endl;
return 0;
}

How to do a true strtoul? Wont intake an actual string

Having an issue inputting an ACTUAL string to strtuol. The input string SHOULD be an unsigned binary value of 32 bits long.
Obviously, there is in issue with InputString = apple; but I'm not sure how to resolve the issue. any thoughts? This shouldnt be that difficult. not sure why I'm having such a hard time with it.
Thanks guys.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
char InputString[40];
char *pEnd = NULL; // Required for strtol()
string apple = "11111111110000000000101010101000";
//cout << "Number? ";
//cin >> InputString;
InputString = apple;
unsigned long x = strtoul(InputString, &pEnd, 2); // String to long
cout << hex << x << endl;
return 1;
}
A better approach would be to avoid the legacy-C functions and use the C++ standard functions:
string apple = "11111111110000000000101010101000";
unsigned long long x = std::stoull(apple, NULL, 2); // defined in <string>
NOTE: std::stoull will actually call ::strtoull internally, but it allows you to just deal with the std::string object instead of having to convert it to a C-style string.
Include :
#include<cstdlib> // for strtol()
#include<cstring> // for strncpy()
and then
strncpy(InputString ,apple.c_str(),40);
^
|
convert to C ctring
Or simply,
unsigned long x = strtoul(apple.c_str(), &pEnd, 2);

string (from substr) conversion to unsigned int

I have a string which actually contains a number and a string, separated by ,, for instance "12,fooBar".
I would like to put it into separated variables, i.e. the number into unsigned int myNum and the string into std::string myStr.
I have the following snipped of code:
size_t pos1=value.find(',');
std::cout << value.substr(0, pos1) << " and "
<< (value.substr(0, pos1)).c_str() << std::endl;
This yields 12 and 1. Anything I missed here? What happend to the 2 in the second part?
Note: I isolated the problem to this snipped of code. I need c_str() to pass it to atoi to get the unsigend int. Here I don't want to print the second part.
Update: I actually get the string from levelDB Get. If I put a test string like I put here, it works.
The posted code produces the same substring: value.substr(0, pos1). Note that std::string::substr() does not modify the object, but returns a new std::string.
Example:
#include <iostream>
#include <string>
int main ()
{
std::string value ="12,fooBar";
unsigned int myNum;
std::string myStr;
const size_t pos1 = value.find(',');
if (std::string::npos != pos1)
{
myNum = atoi(value.substr(0, pos1).c_str());
myStr = value.substr(pos1 + 1);
}
std::cout << myNum << " and "
<< myStr << std::endl;
return 0;
}
Output:
12 and fooBar
EDIT:
If the unsigned int is the only piece required then the following will work:
unsigned int myNum = atoi(value.c_str());
as atoi() will stop at the first non-digit character (excluding optional leading - or +), in this case the ,.
The cleanest C++ style solution to this problem is to use a stringstream.
#include <sstream>
// ...
std::string value = "12,fooBar";
unsigned int myNum;
std::string myStr;
std::stringstream myStream(value);
myStream >> myNum;
myStream.ignore();
myStream >> myStr;
Your second substr should be value.substr(pos1+1,value.length())
One more option is using std::from_chars function from the 17th standard (< charconv > header):
int x;
from_chars(&s[i], &s.back(), x); // starting from character at index i parse
// the nearest interger till the second char pointer
There are different overloads for different types of value x (double etc.).

how to convert a hexadecimal string to a corresponding integer in c++?

i have a unicode mapping stored in a file.
like this line below with tab delimited.
a 0B85 0 0B85
second column is a unicode character. i want to convert that to 0x0B85 which is to be stored in int variable.
how to do it?
You've asked for C++, so here is the canonical C++ solution using streams:
#include <iostream>
int main()
{
int p;
std::cin >> std::hex >> p;
std::cout << "Got " << p << std::endl;
return 0;
}
You can substitute std::cin for a string-stream if that's required in your case.
You could use strtol, which can parse numbers into longs, which you can then assign to your int. strtol can parse numbers with any radix from 2 to 36 (i.e. any radix that can be represented with alphanumeric charaters).
For example:
#include <cstdlib>
using namespace std;
char *token;
...
// assign data from your file to token
...
char *err; // points to location of error, or final '\0' if no error.
int x = strtol(token, &err, 16); // convert hex string to int