I'm getting warnings when I compile something like this...
std::string something = "bacon";
sprintf("I love %s a lot", something.c_str());
Where it says "warning: deprecated conversion from string constant to 'char *'. I tried converting the text to be...
const char *
instead but I get a different error. I'm not committed to sprintf if there is a better option.
For sprintf to work, you need to provide an array of char big enough to write the result to as the first argument.
However, you can (and should!) just use the far easier operator+ for C++ strings:
std::string res = "I love " + something + " a lot";
sprintf("I love %s a lot", something.c_str);
In that code, you should call something.c_str() with proper function call () syntax.
Note also that the above use of sprintf() is wrong, since you didn't provide a valid destination string buffer for the resulting formatted string.
Moreover, for security reasons, you should use the safer snprintf() instead of sprintf(). In fact, with snprintf() you can specify the size of the destination buffer, to avoid buffer overruns.
The following compilable code is an example of snprintf() usage:
#include <stdio.h>
#include <string>
int main()
{
std::string something = "bacon";
char buf[128];
snprintf(buf, sizeof(buf), "I love %s a lot", something.c_str());
printf("%s\n", buf);
}
P.S.
In general, in C++ you may consider string concatenation using std::string::operator+, e.g.:
std::string result = "I love " + something + " a lot";
It doesn't look like a correct use of sprintf.
First parameter is supposed to be a char * with already a backing memory.
For example:
char *str = malloc (BUFSIZ);
sprintf (str, "I love %s a lot", something.c_str);
Related
In the following code:
#include <string>
using namespace std;
int main(){
char command[300];
string stringz = "mystringy";
sprintf(command,"echo \"something with a string %s\" ", stringz);
system(command);
return 0;
}
why is the output
something with a string 8�
rather than the expected
something with a string mystringy
A silly question, but I couldn't find an answer around.
The '%s' modifier of printf takes a char*, not a std::string.
You can write:
sprintf(command,"echo \"something with a string %s\" ", stringz.c_str());
Which gives you a const char* to the contents of a std::string. This shows one of the major weaknesses of sprintf -- no type checking!
sprintf format %s expects a C string, that's a 0-terminated array of char, not a std::string.
stringz.c_str() and since C++11 &stringz[0] and stringz.data() are a few ways to get at the C string held by the std::string.
To add on Deduplicator answer, try putting
sprintf(command,"echo \"something with a string %s\" ", stringz.c_str());
and you should be set.
This is because sprintf is expecting a char * as an argument to expand the %s token. It would work like
sprintf(command,"echo \"something with a string %s\" ", stringz.c_str());
Which passes the "char *" version of the string to sprintf.
The reason why it shows those strange characters is because the whole std::string object is copied into sprintf's stack frame. Then, sprintf, which accepts variable number of arguments, looks into its own stack space and assumes that what it is going to find there is a char *, but actually is some garbage that results from reinterpreting the string data as char *, and when it is dereferenced, it results into that sequence. It could as well segfault if you are unlucky.
You should not use sprintf in the first place. This is C++, not C. std::string supports concatenation in a very natural way, with the + operator, like in some other programming languages:
#include <string>
int main(){
std::string stringz = "mystringy";
std::string command = "echo \"something with a string " + stringz + "\" ";
system(command.c_str());
return 0;
}
If you insist on using char-array functions like sprintf, use stringz.c_str(). As a matter of fact, this is also what system requires. But note how my example converts the string only at the last possible occasion.
You can use:
sprintf(command,"echo \"something with a string %s\" ", stringz.c_str());
Note that %s takes the C strings and not std::string.
Better still use, iostreams:
string stringDemo("MYSTRING");
std::cout << stringDemo << "\n";
How can I combine two const char*s into a third?
i'm trying to do this with this code:
const char* pName = "Foo"
printf("\nMy name is %s.\n\n\n",pName);
const char* nName;
int num_chars = asprintf(&nName, "%s%s", "Somebody known as ", pName);
But I get this error:
'asprintf': identifier not found
I include stdio.h via this code:
#include <stdio.h>
Simple, just use C++:
const char* pName = "Foo"
std::string name("Somebody known as ");
name += pName;
const char* nName = name.c_str();
asprintf is a GNU extension. You can instead use snprintf, or
strncat, but you'll need to handle the memory management yourself: asprintf allocates the result for you.
Better to use std:string, which will make the code much easier.
sprintf(snprintf) or strcat(strncat).
sprintf.
sprintf(nName, "%s%s", "Somebody known as ", pName);
strcat.
strcpy(nName, "Somebody known as ");
strcat(nName, pName);
I will assume that you are using C, besides that you've tagged this question as C++. If you want C++, see Luchian's answer.
There are few errors in the code - the bigger error is that you didn't allocated memory for string pointing by pName. Second error is that you are taking address of the nName variable, and not the address of reserved memory location in you asprintf function. Third error is that asprintf function is no standard C function, but the GNU extension and it might not be available on your compiler (you didn't say which is): http://linux.die.net/man/3/asprintf
You should use something like this:
#include <stdio.h>
const char* pName = "Foo"
printf("\nMy name is %s.\n\n\n",pName);
char nName[30];
int num_chars = sprintf(nName, "%s%s", "Somebody known as ", pName);
Edit: I've read more about asprintf function now. You should pass address of your pointer in asprintf, but it should not be const char * but the char*, as memory location it points will change after allocating enough memory in asprintf.
I'm interested (for various reasons) format using sprintf with the result in a std::string object. The most syntactically direct way I came up with is:
char* buf;
sprintf(buf, ...);
std::string s(buf);
Any other ideas?
Don't use the printf line of functions for formatting in C++. Use the language feature of streams (stringstreams in this case) which are type safe and don't require the user to provide special format characters.
If you really really want to do that, you could pre-allocate enough space in your string and then resize it down although I'm not sure if that's more efficient than using a temporary char buffer array:
std::string foo;
foo.resize(max_length);
int num_bytes = snprintf(&foo[0], max_length, ...);
if(num_bytes < max_length)
{
foo.resize(num_bytes);
}
If you absolutely want to use sprintf, there is no more direct way than the one you wrote.
sprintf Writes into the array pointed by str a C string
If you want to transform this C string into a std::string, there is no better and safer way than the one you wrote.
Answered here. To get length of buffer needed, call:
snprintf( nullptr, 0, format, args... )
You can write short function which can be used as such:
std::string s = string_sprintf("%g, %g\n", 1.23, 0.001);
Example in linked stackoverflow answer.
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.
which is the best way to concat?
const char * s1= "\nInit() failed: ";
const char * s2 = "\n";
char buf[100];
strcpy(buf, s1);
strcat(buf, initError);
strcat(buf, s2);
wprintf(buf);
It gives error. What should be the correct way?
Thanks.
I think the correct way is:
std::string msg = std::string("Init() Failed ") + initError + "\n";
std::cout<<msg;
or
std::cout<<"Init() Failed "<<initError<<"\n";
Your big problem is that you're mixing data types. Use either char and associated functions or wchar and associated functions. If you need to mix them, use a conversion function. This makes no more sense than trying to pass a float to a function needing a string. (The compiler should be able to catch both problems, since the declaration of wprintf is something like int wprintf(const wchar_t *, ...).)
Another, more minor, issue is that printf and such are not the right functions to print out general strings, since if there are any percent signs in the strings you'll get undefined behavior. Use printf("%s",...) or puts(...) or related functions.
And, since this is C++, you'd be much better off using the std::string class. It isn't perfect, but it's far better than C-style strings.
Also, telling us what the error is would help. You haven't even told us whether it's a compiler error or a run-time error.