This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I convert a double into a string in C++?
I want to combine a string and a double and g++ is throwing this error:
main.cpp: In function ‘int main()’:
main.cpp:40: error: invalid operands of types ‘const char [2]’ and ‘double’ to binary ‘operator+’
Here is the line of code which it is throwing the error on:
storedCorrect[count] = "("+c1+","+c2+")";
storedCorrect[] is a string array, and c1 and c2 are both doubles. Is there a way to convert c1 and c2 to strings to allow my program to compile correctly?
You can't do it directly. There are a number of ways to do it:
Use a std::stringstream:
std::ostringstream s;
s << "(" << c1 << ", " << c2 << ")";
storedCorrect[count] = s.str()
Use boost::lexical_cast:
storedCorrect[count] = "(" + boost::lexical_cast<std::string>(c1) + ", " + boost::lexical_cast<std::string>(c2) + ")";
Use std::snprintf:
char buffer[256]; // make sure this is big enough!!!
snprintf(buffer, sizeof(buffer), "(%g, %g)", c1, c2);
storedCorrect[count] = buffer;
There are a number of other ways, using various double-to-string conversion functions, but these are the main ways you'll see it done.
In C++11, use std::to_string if you can accept the default format (%f).
storedCorrect[count]= "(" + std::to_string(c1) + ", " + std::to_string(c2) + ")";
Use std::stringstream. Its operator << is overloaded for all built-in types.
#include <sstream>
std::stringstream s;
s << "(" << c1 << "," << c2 << ")";
storedCorrect[count] = s.str();
This works like you'd expect - the same way you print to the screen with std::cout. You're simply "printing" to a string instead. The internals of operator << take care of making sure there's enough space and doing any necessary conversions (e.g., double to string).
Also, if you have the Boost library available, you might consider looking into lexical_cast. The syntax looks much like the normal C++-style casts:
#include <string>
#include <boost/lexical_cast.hpp>
using namespace boost;
storedCorrect[count] = "(" + lexical_cast<std::string>(c1) +
"," + lexical_cast<std::string>(c2) + ")";
Under the hood, boost::lexical_cast is basically doing the same thing we did with std::stringstream. A key advantage to using the Boost library is you can go the other way (e.g., string to double) just as easily. No more messing with atof() or strtod() and raw C-style strings.
std::string stringify(double x)
{
std::ostringstream o;
if (!(o << x))
throw BadConversion("stringify(double)");
return o.str();
}
C++ FAQ:
http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.1
I believe the sprintf is the right function for you. I's in the standard library, like printf. Follow the link below for more information:
http://www.cplusplus.com/reference/clibrary/cstdio/sprintf/
Related
I see in this topic C++ convert hex string to signed integer that boost::lexical_cast can convert hexadecimal inside string to another type (int, long...)
but when I tried this code:
std::string s = "0x3e8";
try {
auto i = boost::lexical_cast<int>(s);
std::cout << i << std::endl; // 1000
}
catch (boost::bad_lexical_cast& e) {
// bad input - handle exception
std::cout << "bad" << std::endl;
}
It ends with a bad lexical cast exception !
boost doesn't support this kind of cast from string hex to int ?
As per the answer from C++ convert hex string to signed integer:
It appears that since lexical_cast<> is defined to have stream conversion semantics. Sadly, streams don't understand the "0x" notation. So both the boost::lexical_cast and my hand rolled one don't deal well with hex strings.
Also, as per boost::lexical_cast<> documentation
The lexical_cast function template offers a convenient and consistent form for supporting common conversions to and from arbitrary types when they are represented as text. The simplification it offers is in expression-level convenience for such conversions. For more involved conversions, such as where precision or formatting need tighter control than is offered by the default behavior of lexical_cast, the conventional std::stringstream approach is recommended.
So for more involved conversion, std::stringstream is recommended.
If you have access to C++11 compiler, you can use std::stoi to convert any hexadecimal sting to an integer value.
stoi prototype is:
int stoi( const std::string& str, std::size_t* pos = nullptr, int base = 10 );
Your program can be converted to
int main() {
std::string s = "3e8";
auto i = std::stoi(s, nullptr, 16);
std::cout << i << '\n';
}
And the output will be
1000
What you want exists in Boost Convert:
Boost.Convert builds on the boost::lexical_cast experience and takes
those type conversion/transformation-related ideas further
to be applicable to a wider range of conversion-related deployment scenarios,
to provide a more flexible, configurable and extendible type-conversion framework,
to provide generic consistent behavior,
to unify and to uniformly deploy various conversion facilities through one consistent interface.
Simple Usage
You can e.g. use stream conversion:
boost::cnv::cstream converter;
You can configure it with the manipulators you want, e.g.:
converter(std::hex)(std::skipws); // IO manipulators
You could use directly:
boost::optional<int> i;
converter(s, i);
std::cout << i << std::endl; // 1000
But I'd suggest applying with pre-configured error-handling:
auto f = apply<int>(std::ref(converter))
.value_or(-1); // decorate error-handling
Now you can simply write:
for (auto s : cases)
std::cout << f(s) << std::endl;
Live Demo
Live On Coliru
#include <boost/convert.hpp>
#include <boost/convert/stream.hpp>
#include <iostream>
static const std::string cases[]{
"0x3e8", "3e8", "-7a", "-0x7a",
"0x-7a", // error
};
int main() {
boost::cnv::cstream converter;
converter(std::hex)(std::skipws); // IO manipulators
auto f = apply<int>(std::ref(converter)).value_or(-1); // decorate error-handling
for (auto s : cases)
std::cout << std::quoted(s) << " -> " << f(s) << std::endl;
auto g = apply<int>(std::ref(converter)); // throwing
for (auto s : cases)
try {
std::cout << std::quoted(s) << " -> " << g(s) << std::endl;
} catch (std::exception const& e) {
std::cout << e.what() << std::endl;
}
}
Prints
"0x3e8" -> 1000
"3e8" -> 1000
"-7a" -> -122
"-0x7a" -> -122
"0x-7a" -> -1
"0x3e8" -> 1000
"3e8" -> 1000
"-7a" -> -122
"-0x7a" -> -122
"0x-7a" -> Attempted to access the value of an uninitialized optional object.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I'm trying to add multiple variables inside the std::system function. By using .c_str on the end it only accepts one variable.
system(("riverctl map normal " + modkey + " " + i + " set-focused-tags " + decimal).c_str);
I recommend the format library:
C++20 format standard library
#include <cstdlib>
#include <format>
auto test(int modkey, int i, int decimal)
{
auto cmd = std::format("riverctl map normal {} {} set-focused-tags {}",
modkey, i, decimal);
system(cmd.c_str());
}
or
{fmt} library
#include <cstdlib>
#include <fmt/core.h>
auto test(int modkey, int i, int decimal)
{
auto cmd = fmt::format("riverctl map normal {} {} set-focused-tags {}",
modkey, i, decimal);
system(cmd.c_str());
}
This code
"riverctl map normal " + modkey
calls operator+ on two things: "riverctl map normal " and modkey. Which operator+ this is depends on the types of the two operands of +.
You want it to call operator+ which concatenates strings; if any of the two first operands is a string (std::string), the first + will do the right thing, and all the following + will do too (because the result of the first + would be std::string).
If modkey is an integer (any type of integer, including char), this + will do the wrong thing (unwanted pointer arithmetic). To fix, convert any of the first two operands to a string. If modkey is an integer, you have to use std::to_string on it anyway, so converting the first operand is not necessary. But for consistency (i.e. to stop worrying what would happen if you changed the format of your message), you might want to convert even the first one:
// minimal required change
system(("riverctl map normal " +
std::to_string(modkey) + " " +
std::to_string(i) + " set-focused-tags " +
std::to_string(decimal)).c_str());
// more robust code (C++14 and later)
system(("riverctl map normal "s +
std::to_string(modkey) + " " +
std::to_string(i) + " set-focused-tags " +
std::to_string(decimal)).c_str());
// more robust code (C++11)
system((std::string("riverctl map normal ") +
std::to_string(modkey) + " " +
std::to_string(i) + " set-focused-tags " +
std::to_string(decimal)).c_str());
If your command line is too complex, you might want to use a temporary stream for formatting; there are fewer surprises then:
std::ostringstream stream;
stream << "riverctl map normal " << modkey << " " << i << " set-focused-tags " << decimal;
system(stream.str().c_str());
In case all variables declared in the system block are primitives (I guess that 'modkey' is already std::string) - you need to cast everything to std::string and call c_str as a function.
system(("riverctl map normal " + modkey + " " + std::to_string(i) + " set-focused-tags " + std::to_string(decimal)).c_str());
I have been using mostly C so I am pretty new into c++. I want to convert a int vector (std::vector) into hexadecimal representation and then store that into a string. I found something I would use in C in the following thread: Converting hex into a string using 'sprintf'
The code proposed by user411313 is the following:
static unsigned char digest[16];
static unsigned char hex_tmp[16];
for (i = 0; i < 16; i++) {
printf("%02x",digest[i]);
sprintf(&hex_tmp[i], "%02x", digest[i]);
}
One of my concerns is that this could go out of index at some point since sprintf may try to add a 0 after the content. Also, I was wondering if there is any way to do it with native C++, perhaps any built function could be used instead of C functions. Is this preferable in c++ over c functions? Thank you very much for your assistance!
if there is any way to do it with native C++, perhaps any built function could be used instead of C functions. Is this preferable in c++ over c functions?
Sure there is a way, and yes it's preferable:
static std::array<unsigned char,16> digest;
static std::string hex_tmp;
for (auto x : digest) {
std::ostringstream oss;
oss << std::hex << std::setw(2) << std::setfill('0') << (unsigned)x;
hex_tmp += oss.str();
}
One of my concerns is that this could go out of index at some point since sprintf may try to add a 0 after the content.
That's a valid concern. The classes used in my code snippet above will overcome all these issues, and you don't need to care about.
You can use std::stringstream
std::string hex_representation(const std::vector<int>& v) {
std::stringstream stream;
for (const auto num : v) {
stream << "0x" << std::hex << std::setw(2) << std::setfill('0') << num
<< ' ';
}
return stream.str();
}
Obviously you can remove the "0x" prefix if you don't need it
Here a live demo.
I would like concatenate string literals and ints, like this:
string message("That value should be between " + MIN_VALUE + " and " + MAX_VALUE);
But that gives me this error:
error: invalid operands of types ‘const char*’ and ‘const char [6]’ to binary ‘operator+’|
What is the correct way to do that? I could split that in 2 string declarations (each concatenating a string literal and a int), but that's ugly. I've also tried << operator.
Thanks
You should probably use stringstream for this.
#include <sstream>
std::stringstream s;
s << "This value shoud be between " << MIN_VALUE << " and " << MAX_VALUE;
message = s.str();
The c++ way to do this is to use a stringstream then you can use the << operator. It will give you a more consistent code feel
There are many ways to do this, but my favourite is:
string message(string("That value should be between ") + MIN_VALUE + " and " + MAX_VALUE);
That extra string() around the first literal makes all the difference in the world because there is an overloaded string::operator+(const char*) which returns a string, and operator+ has left-to-right associativity, so the whole thing is turned into a chain of operator+ calls.
#include <sstream>
#include <string>
template <typename T>
std::string Str( const T & t ) {
std::ostringstream os;
os << t;
return os.str();
}
std::string message = "That value should be between " + Str( MIN_VALUE )
+ " and " + Str( MAX_VALUE );
You probably want to use a stringstream like this:
std::stringstream msgstream;
msgstream << "That value should be between " << MIN_VALUE << " and " << MAX_VALUE;
std::string message(msgstream.c_str());
I have an application in which I need to combine strings within a variable like so:
int int_arr[4];
int_arr[1] = 123;
int_arr[2] = 456;
int_arr[3] = 789;
int_arr[4] = 10;
std::string _string = "Text " + int_arr[1] + " Text " + int_arr[2] + " Text " + int_arr[3] + " Text " + int_arr[4];
It gives me the compile error
Error C2210: '+' Operator cannot add pointers" on the second string of the expression.
As far as I can tell I am combining string literals and integers, not pointers.
Is there another concatenation operator that I should be using? Or is the expression just completely wrong and should figure out another way to implement this?
BTW I am using Visual Studio 2010
Neither C nor C++ allow concatenation of const char * and int. Even C++'s std::string, doesn't concatenate integers. Use streams instead:
std::stringstream ss;
ss << "Text " << int_arr[1] << " Text " << int_arr[2] << " Text " << int_arr[3] << " Text " << int_arr[4];
std::string _string = ss.str();
You can do this in Java since it uses the toString() method automatically on each part.
If you want to do it the same way in C++, you'll have to explicitly convert those integer to strings in order for this to work.
Something like:
#include <iostream>
#include <sstream>
std::string intToStr (int i) {
std::ostringstream s;
s << i;
return s.str();
}
int main (void) {
int var = 7;
std::string s = "Var is '" + intToStr(var) + "'";
std::cout << s << std::endl;
return 0;
}
Of course, you can just use:
std::ostringstream os;
os << "Var is '" << var << "'";
std::string s = os.str();
which is a lot easier.
A string literal becomes a pointer in this context. Not a std::string. (Well, to be pedantically correct, string literals are character arrays, but the name of an array has an implicit conversion to a pointer. One predefined form of the + operator takes a pointer left-argument and an integral right argument, which is the best match, so the implicit conversion takes place here. No user-defined conversion can ever take precedence over this built-in conversion, according to the C++ overloading rules.).
You should study a good C++ book, we have a list here on SO.
A string literal is an expression returning a pointer const char*.
std::stringstream _string_stream;
_string_stream << "Text " << int_arr[1] << " Text " << int_arr[2] << " Text " << int_arr[3] << " Text " << int_arr[4];
std::string _string = _string_stream.str();