sprintf' : cannot convert parameter 1 from 'const char *' to 'char *' - c++

std::string mystring;
sprintf(mystring.c_str(), "%s %d", "Helloworld", 2014);
Its is giving a compiler error to me:
'sprintf' : cannot convert parameter 1 from 'const char *' to 'char *'

It shouldn't be a warning, it should be an error. The pointer
returned by std::string::c_str() points to read-only memory;
any attempt to write through it is undefined behavior. (In your
case, if you use a const_cast to shut up the compiler, you're
code will probably crash, since you're calling c_str() on an
empty strying.)
Generally speaking, what you probably want is
std::ostringstream:
std::ostringstream formatter;
formatter << "Helloworld" << ' ' << 2014;
std::string myString = formatter.str();
FWIW: sprintf is one of the most dangerous functions in the
standard library, and only present for historical reasons. It's
almost impossible to use safely; even in C, you should prefer
snprintf (but in C++, std::ostringstream is far better).

your warning gives you all information you need.
std::string::c_str() returns a const char* and sprintf requires a char* since it modiefies the buffer.
But you are writing c++ and should avoid sprintf. Use a ostringstream to write formated data to a string.

std::string manages underlying C-style buffer. c_str returns const char* because it shouldn't be modified by anything other then string's methods.
You should rather use ostringstream. See this question: C++ equivalent of sprintf?

You are telling sprintf to store the result in mystring.c_str(). This is a readonly view of the underlying representation of mystring. Since it is readonly (or const char *), you can't write the result to it.
If you need to use sprintf, you will have to create a writable character buffer for it to use, and then assign that buffer to mystring.
A different way of performing this sort of operation without having to create character buffers and deal with possible overflow would be to use a stringstream:
std::stringstream buffer;
buffer << "Helloworld " << 2014;
mystring = buffer.str();

Alternatively, use old C snprintf into a temporary buffer, then assign into the string :
std::string mystring;
char buf[64];
snprintf(buf, sizeof(buf), "%s %d", "Helloworld", 2014);
mystring.assign(buf);
snprintf is always safer than sprintf since it avoids buffer overflow.
But of course using an ostringstream like answered here by James Kanze is better.

#include <iostream>
#include <string>
#include <sstream>
std::stringstream ss;
ss << "Helloworld";
ss << " ";
ss << "2014";
ss << std::endl;
std::string str = ss.str();
std::cout << str;
const char * mystring= str.c_str();
In this way also you can append int or long number into the string.
Example:
long year = 2014;
std::stringstream ss;
ss << "Helloworld";
ss << " ";
ss << year;
ss << std::endl;
std::string str = ss.str();
std::cout << str;
const char * mystring= str.c_str();

Related

What happens when converting char * to string *?

char * ss = "abscd";
string * b = (string *) ss;
std::cout << ss << std::endl;
std::cout << *b << std::endl;
The output is:
abscd
//empty line
I thought it would be :
abscd
abscd
You must have misunderstood something. First of all you miss a const here:
const char * ss = "abscd";
Next, std::string is meant to replace c-strings, like the one you have with ss. However, std::string is a string, while std::string* is a pointer to a string. As std::string is not related to char as far as conversions between pointers are concerned, your code has undefined behavior.
To create a std::string from a c-string use its constructor, eg like this:
std::string b{ss};
Last but not least, avoid c-style casts like this one string * b = (string *) ss;. You can cast anything to anything without getting a compiler error, but that does not mean that it is correct.

Getting garbage out from getline

I'm getting garbage out from getline but I'm not sure what I'm doing wrong.
Here is the code:
std::string str = "/command?device=c53b1f8&zoom=24&tilt=80";
std::istringstream ss(str);
std::string buf;
while (std::getline(ss, buf, '&'))
{
printf("%s\n", buf);
}
Output:
á╚╢ºA
á╚╢ºA
á╚╢ºA
Your bug is here:
printf("%s\n", buf);
std::printf() is a C language function, it is meant for C-style null-terminated strings. It does not understand std::string at all. Using it the way you are is undefined behavior. Your weird result is caused by printing the internal structure of the std::string up to the first 0x00 byte encountered in memory.
The correct solution is to use std::cout instead:
std::cout << buf << '\n';
However, if you want to stick to using printf() then you can have std::string output a C-style string using its c_str() method, like this:
std::printf("%s\n", buf.c_str());

What is the return type of stack.top() and stack.pop() using stack<string> in cpp?

I am trying to print the return value of stack.top() using printf() of a stack but it is giving a format mismatch. The code is given below :
int main(){
stack <string> cards;
char *ch1;
char ch2[20];
cards.push("Ace");
cards.push("King");
cards.push("Queen");
cards.push("Jack");
printf("Number of cards : %ld \n", cards.size());
ch1 = cards.top(); // As sizeof(cards.top()) is 8. error of type conversion
strcpy(ch2,cards.top()); // cannot convert ‘std::basic_string<char>’ to ‘const char*’
printf("Top of the Stack : %s \n", ch);
return 0
}
In all examples I saw it was printed using "cout".
A std::string is a different type from a char*, the following won't work:
ch1 = cards.top(); // top() returns a string, not a char*
I suggest using std::strings for your code:
int main(){
stack <string> cards;
string ch1; // std::strings
string ch2;
...
ch1 = cards.top(); // Correct
printf("Top of the Stack : %s \n", ch1.c_str()); // c_str() needed
return 0;
}
Also notice that using printf requires a char* type, you can get one with std::string::c_str(), or (even better) you can use cout in the first place:
std::cout << "Top of the Stack : " << ch1;
Therefore I'd suggest doing something like:
#include <iostream>
#include <stack>
#include <string>
int main() {
std::stack <std::string> cards;
std::string ch1;
cards.push("Ace");
cards.push("King");
cards.push("Queen");
cards.push("Jack in the Jack");
std::cout << "Number of cards : " << cards.size() << std::endl;
ch1 = cards.top(); // Get the top card
std::cout << "Top of the Stack : " << ch1;
}
Example
The return value of is pop is void, top returns a reference to the data type that the stack holds. std::string is not the same as an array of char and it does not directly work with any of the C string functions. You can use std::string::c_str() to get the raw data, but it is better to stay in STL land. You can directly print std::string using std::cout.
You can't use strcpy, which is a C function for C-style char * strings, for C++ std::strings - if you must use C strings for some reason then change:
strcpy(ch2,cards.top());
to
strcpy(ch2,cards.top().c_str());
^^^^^^^^
This takes the std::string returned by cards.top() and returns a const char * which can be used by strcpy.
A better solution though would be to stick to C++ idioms throughout, i.e. use std::string exclusively and use std::cout instead of printf for display purposes.
In the following line
ch1 = cards.top();
stack<string>::top() returns string, while ch1 is char *. There is no type conversion from string to char *. To convert it, use the member function c_str :
ch1 = cards.top().c_str();
And ch1 must be const char*, not char *, because thats what c_str returns.
Why it returns const char* ? Because otherwise you could disrupt the string value by extracting char * and changing it.

How to pass variable in C++ Sprintf 2nd(format) argument?

I've been cracking heads on how to achieve this in C++:
string format = "what is your %s";
new_string = sprintf(buffer, format, name);
Any help would be very much appreciated.
Thanks!
Use format.c_str():
string format = "what is your %s";
int total = sprintf(buffer, format.c_str(), name);
Also note the returned value is not the new string, it is the buffer which is the output string. The returned value is actually the total number of characters written. This count does not include the additional null-character automatically appended at the end of the string. On failure, a negative number is returned (see doc here).
But in C++, std::ostringstream is better and typesafe, as #Joachim explained in his answer.
Use ostringstream:
std::ostringstream os;
os << "what is your " << name;
std::string new_string = os.str();
You could always do something like:
char buffer[100];
string format = "what is your %s";
sprintf(buffer, format.c_str(), name.c_str());
string new_string(buffer);
Alternatively, use a stringstream:
stringstream buf;
buf << "what is your " << name;
string new_string = buf.str();
The format passed to sprintf must be a char*, not a std::string.
sprintf also returns the number of characters written, not a pointer to the constructed buffer.
int len = sprintf(buffer, "what is your%s", name);
std::string new_string(buffer, len);
Another possibility would be to use std::ostringstream to perform your formatting.
I'm not sure I understand the problem here - sprintf is a function that takes in a char* as its first argument, and a const char* as its second. These are both C data types, and so I don't know if using a C++ string will be recognised by the compiler as valid.
Also, the function returns an int (the number of characters written), not a string, which it looks like you're expecting with a return value like new_string.
For more information, you can look at http://www.cplusplus.com/reference/clibrary/cstdio/sprintf/
You may use stringstream form the C++ STL which is more OO.
Check out the documentation.
sprintf is part of the C library, and thus don't know anything about std::string. Use char* instead if you still want to use it.
To get the C char* string from an std::string, uses c_str method.

C++ convert int and string to char*

This is a little hard I can't figure it out.
I have an int and a string that I need to store it as a char*, the int must be in hex
i.e.
int a = 31;
string str = "a number";
I need to put both separate by a tab into a char*.
Output should be like this:
1F a number
With appropriate includes:
#include <sstream>
#include <ostream>
#include <iomanip>
Something like this:
std::ostringstream oss;
oss << std::hex << a << '\t' << str << '\n';
Copy the result from:
oss.str().c_str()
Note that the result of c_str is a temporary(!) const char* so if your function takes char * you will need to allocate a mutable copy somewhere. (Perhaps copy it to a std::vector<char>.)
Try this:
int myInt = 31;
const char* myString = "a number";
std::string stdString = "a number";
char myString[100];
// from const char*
sprintf(myString, "%x\t%s", myInt, myString);
// from std::string :)
sprintf(myString, "%x\t%s", myInt, stdString.c_str());
#include <stdio.h>
char display_string[200];
sprintf(display_string,"%X\t%s",a,str.c_str());
I've used sprintf to format your number as a hexadecimal.
str.c_str() will return a null-terminated C-string.
Note: not answering the main question since your comment indicated it wasn't necessary.
those who write "const char* myString = "a number";"
are just lousy programmers. Being not able to get the C basics - they rush into C++ and start speaking about the things they just don't understand.
"const char *" type is a pointer.
"a number" - is array. You mix pointers and arrays. Yes, C++ compilers sometimes allow duct typing. But you must also understand - if you do duct typing not understanding where your "ductivity" is - all your program is just a duct tape.