I cannot get the atof() function to work. I only want the user to input values (in the form of decimal numbers) until they enter '|' and it to then break out the loop. I want the values to initially be read in as strings and then converted to doubles because I found in the past when I used this method of input, if you input the number '124' it breaks out of the loop because '124' is the code for the '|' char.
I looked around and found out about the atof() function which apparently converts strings to doubles, however when I try to convert I get the message
"no suitable conversion function from std::string to const char exists".
And I cannot seem to figure why this is.
void distance_vector(){
double total = 0.0;
double mean = 0.0;
string input = " ";
double conversion = 0.0;
vector <double> a;
while (cin >> input && input.compare("|") != 0 ){
conversion = atof(input);
a.push_back(conversion);
}
keep_window_open();
}
You need
atof(input.c_str());
That would be the "suitable conversion function" in question.
std::string::c_str Documentation:
const char* c_str() const;
Get C string equivalent
Returns a pointer to an array that contains a null-terminated sequence of characters (i.e., a C-string) representing the current value of the string object.
You can also use the strtod function to convert a string to a double:
std::string param; // gets a value from somewhere
double num = strtod(param.c_str(), NULL);
You can look up the documentation for strtod (e.g. man strtod if you're using Linux / Unix) to see more details about this function.
Related
I am reading in a value with a string, then converting it to a double. I expect an input such as 2.d to fail with std::stod, but it returns 2. Is there a way to ensure that there is no character in the input string at all with std::stod?
Example code:
string exampleS = "2.d"
double exampleD = 0;
try {
exampleD = stod(exampleS); // this should fail
} catch (exception &e) {
// failure condition
}
cerr << exampleD << endl;
This code should print 0 but it prints 2. If the character is before the decimal place, stod throws an exception.
Is there a way to make std::stod (and I'm assuming the same behavior also occurs with std::stof) fail on inputs such as these?
You can pass a second argument to std::stod to get the number of characters converted. This can be used to write a wrapper:
double strict_stod(const std::string& s) {
std::size_t pos;
const auto result = std::stod(s, &pos);
if (pos != s.size()) throw std::invalid_argument("trailing characters blah blah");
return result;
}
This code should print 0 but it prints 2.
No, that is not how std::stod is specified. The function will discard whitespace (which you don't have), then parse your 2. substring (which is a valid decimal floating-point expression) and finally stop at the d character.
If you pass a non-nullptr to the second argument pos, the function will give you the number of characters processed, which maybe you can use to fulfill your requirement (it is not clear to me exactly what you need to fail on).
I am developing an c++ app in gtkmm 2
I have a problem to cast the string from an entryfield to a double (or int).
I get the following compilation error
cannot convert from Glib::ustring to double
The entryfield
interestrate.set_max_length(50);
interestrate.set_text(interestrate.get_text() );
interestrate.select_region(0, interestrate.get_text_length());
m_box1.pack_start(interestrate);
interestrate.show();
the button
m_button3.signal_clicked().connect(sigc::bind<-1, Glib::ustring>(
sigc::mem_fun(*this, &HelloWorld::on_button_clicked), "OK"));
m_box1.pack_start(m_button3);
m_button3.show();
and the eventhandler
void HelloWorld::on_button_clicked(Glib::ustring data)
{
std::cout << "interestrate: " << interestrate.get_text() << std::endl;
}
so i want to get a double of the returnvalue from
interestrate.get_text()
I didnt beleive it could be so easy
std::string s = interestrate.get_text();
double d = atof(s.c_str());
Your suggestion would work for valid C locale input.
If you want to deal with bad number formats and locale considerations you have to do a little bit more; atof returns 0 on error, but 0 may be a valid input, and here in Germany users would perhaps enter a comma as the decimal point.
I would think (from reading the glib docs and this answer: How can I convert string to double in C++?), that you should get the proper localized std::string first via Glib::locale_from_utf8() and then create a stringstream from that and read your double out of that. The stream gives you error information and the conversion/operator>>() will deal with locale issues if you have "imbued" a locale.
I am designing a gui in visual c++ and there is a textbox where user inputs values so a calculation can be performed. How do I validate the input to ensure it can be cast to a double value?
In any C++ environment where you have a std::string field and wish to check if it contains a double, you can simply do something like:
#include <sstream>
std::istringstream iss(string_value);
double double_value;
char trailing_junk;
if (iss >> double_value && !(iss >> trailing_junk))
{
// can use the double...
}
As presented, this will reject things like "1.234q" or "-13 what?" but accept surrounding whitespace e.g. " 3.9E2 ". If you want to reject whitespace, try #include <iomanip> then if (iss >> std::noskipws >> double_value && iss.peek() == EOF) ....
You could also do this using old-style C APIs:
double double_value;
if (sscanf(string_value.c_str(), "%lf%*c", &double_value) == 1)
You cannot "cast" a string to a double, you can only convert it. strtod function will return a pointer to the character within the string where the conversion stopped, so you can decide what to do further. So you can use this function for conversion AND checking.
I'd recommend Boost's lexical_cast, which will throw an exception if the conversion fails.
Since this seems to be a C++ CLI related question and your string from the textbox might be a .NET string, you might want to check the static Double::Parse method. For more portable solutions see the other answers...
As stated already, strtod(3) is the answer.
bool is_double(const char* str) {
char *end = 0;
strtod(str, &end);
// Is the end point of the double the end of string?
return end == str + strlen(str);
}
To address #Ian Goldby's concern, if white space at the end of the sting is a concern, then:
bool is_double(const char* str) {
char *end = 0;
strtod(str, &end);
// Is the end point of the double plus white space the end of string?
return end + strspn(end, " \t\n\r") == str + strlen(str);
}
Simply convert it to a double value. If it succeeds, the input is valid.
Really, you shouldn't be writing your own rules for deciding what is valid. You'll never get exactly the same rules as the library function that will do the actual conversion.
My favourite recipe is to use sscanf(), and check the return value to ensure exactly one field was converted. For extra credit, use a %n parameter to check that no non-whitespace characters were left over.
In C++, how can I convert a data of type float64 to a string without losing any of the data in float64? I need it to not only be converted to a string, but add a string to either side of the number and then sent to be written in a file.
Code:
string cycle("---NEW CYCLE ");
cycle+=//convert float64 to string and add to cycle
cycle+= "---\r\n";
writeText(cycle.c_str()); //writes string to txt file
Thanks.
The usual way of converting numbers to std::strings is to use std::ostringstream.
std::string stringify(float value)
{
std::ostringstream oss;
oss << value;
return oss.str();
}
// [...]
cycle += stringify(data);
You should use sprintf. See documentation here C++ Reference.
As an example it would be something like:
char str[30];
float flt = 2.4567F;
sprintf(str, "%.4g", flt );
Also I would use string::append to add the string. See here .
UPDATE
Updated code according to comment.
You can use sprintf to format the string.
I have a config file:
#X,Name,hostid,processid,executecommand,Max Runs, Max failure time
X,Main_XYZ_service,1,1,/opt/bada/bin,3,6,300
I parsed the above config file and stored each of the values in a vector of type string.
This is stored in vector<string> scanned:
//scanned[0]=X
//scanned[1]=Main_XYZ_service.........
long H_hostid = atoi(scanned[5].c_str());
how can I detect the type of the elements present in the vector?
If I call atoi() with a string that doesn't have a number, atoi() returns 0, but it also returns 0 if the string contains the number 0. How can I correctly assign a value to H_hostid?
In an absolute sense, you can't. If you encounter the string "0", you
can't know whether the user intended a string, an integer or a floating
point value. On the other hand, if you know what you need, you can try
to convert (say by using boost::lexical_cast), and generate an error
if it doesn't match. Alternatively, you can use regular expressions for
pattern matching, and decide what type you want as a result of what
pattern matches.
For a configuration file, I'd suggest the former. Just keep everything
as a string until you know what you need, then try the conversion (using
something reasonable for the conversion, which will report an error, and
not atoi).
Don't use atoi() - as you say, there is no way to detect errors. Use std::istringstream in C++, or strtol() in C.
long H_hostid;
std::istringstream stream(scanned[5]);
if (!(stream >> H_hostid)) {
// handle error
}
You could also use boost::lexical_cast, which does the same thing as that example, and throws an exception if the conversion fails.
If this is the data stored as a single string:
X,Main_XYZ_service,1,1,/opt/bada/bin,3,6,300
then the solution is, split this string using , as separator, and store each token in an array of size 8, then you can interpret each token based on the index as shown below:
char,string, int, int, string, int, int, int
0 1 2 3 4 5 6 7
Code would look like this:
std::string s = "X,Main_XYZ_service,1,1,/opt/bada/bin,3,6,300";
std::vector<std::string> tokens = split(s); //write the function yourself!
char c = tokens[0]; //token with index 0 is char
std::string service = tokens[1]; //token with index 1 is string
std::string path = tokens[4]; //token with index 4 is string
int int_indices[] = {2,3,5,6,7}; //rest of the index has int : total 5
for(int i = 0 ; i < 5 ; i++ )
{
try
{
int value = boost::lexical_cast<int>(tokens[int_indices[i]]);
//store value
}
catch(const bad_lexical_cast &)
{
std::cout << tokens[int_indices[i]] <<" is not an int" << std::endl;
}
}
Whenever you write a config file to be used by your application, you know in advance in what order the values will appear in that file. Otherwise, an xml or key value coding will be a better option to write a config file for general case. Personally, I would never create a config file as you have shown in your example.