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

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.

Related

Gibberish is printed while reading from a file and writing to another [duplicate]

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";

Inserting a string into another string ... (sprintf)

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);

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

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();

C++ stringstream string to function(test, char *test2)

Have a MySQL query function, that needs to take a string parameter.
Which looks like this:
cin >> user_string;
stringstream ss;
ss << "select * from " << user_string;
Function looks like this:
mysql_perform_query(MYSQL *connection, char *sql_query)
Tried to convert to ss.c_str(); or ss.str().c_str();
Does not work.
What would be the correct way to do this? Skip Stingstream and build char?
C++ Strings confuses me...
It's unusual that mysql_perform_query doesn't want a const char *.
If that's your code, change it to accept a const char * and your approach will work.
mysql_perform_query( connection, user_string.str().c_str() );
If you can't change that function signature, this will work*.
mysql_perform_query( connection, &user_string.str()[0] );
*It's guaranteed to work in C++11, and while not guaranteed in C++03, does work in all common implementations
The SQL interface probably requires a char const*. ss.str()
will give you a string, and ss.str().c_str() will give you
a char const* from that string.
To points, however (more style than anything):
unless you actually need the bidirectional capacities of
stringstream, it's probably preferable to use the simpler
ostringstream (which only does output), and
if all you're doing is concatenation, there's no point in
using streams at all, just use the + operator on the strings.
(You can also use + to concatenate a string and a string
literal.) Streams are really for formatting and parsing, and
are overkill (unnecessary added complexity) for simple
concatenation.
ss.str().c_str() would be correct if only your function was
mysql_perform_query(MYSQL *connection, const char *sql_query);
This is because c_str() returns const char *.
If you are able to change the mysql_perform_query function to const char * then I would do so. Otherwise you could consider doing a const_cast, const_cast<char*>(ss.str().c_str()).
In the unlikely event that mysql_perform_query really does modify the C string being passed to it then you will have to copy your string to a vector and pass a pointer to that instead.
string str = ss.str();
vector<char> tmp(str.begin(), str.end());
tmp.push_back('\0');
mysql_perform_query(connection, &tmp[0]);
ss.str().c_str() is a const char * not a char * that is required. I would copy ss.str().c_str() into a char * then pass it to the function.
stringstream has a str method that returns a std::string; std::string has a c_str() method that returns a pointer to a char.
mysql_perform_query(connection, ss.str().c_str());
You did do a proper search before posting your question, didn't you?

What is the use of the c_str() function?

I understand c_str converts a string, that may or may not be null-terminated, to a null-terminated string.
Is this true? Can you give some examples?
c_str returns a const char* that points to a null-terminated string (i.e., a C-style string). It is useful when you want to pass the "contents"¹ of an std::string to a function that expects to work with a C-style string.
For example, consider this code:
std::string string("Hello, World!");
std::size_t pos1 = string.find_first_of('w');
std::size_t pos2 = static_cast<std::size_t>(std::strchr(string.c_str(), 'w') - string.c_str());
if (pos1 == pos2) {
std::printf("Both ways give the same result.\n");
}
See it in action.
Notes:
¹ This is not entirely true because an std::string (unlike a C string) can contain the \0 character. If it does, the code that receives the return value of c_str() will be fooled into thinking that the string is shorter than it really is, since it will interpret \0 as the end of the string.
In C++, you define your strings as
std::string MyString;
instead of
char MyString[20];.
While writing C++ code, you encounter some C functions which require C string as parameter.
Like below:
void IAmACFunction(int abc, float bcd, const char * cstring);
Now there is a problem. You are working with C++ and you are using std::string string variables. But this C function is asking for a C string. How do you convert your std::string to a standard C string?
Like this:
std::string MyString;
// ...
MyString = "Hello world!";
// ...
IAmACFunction(5, 2.45f, MyString.c_str());
This is what c_str() is for.
Note that, for std::wstring strings, c_str() returns a const w_char *.
Most old C++ and C functions, when dealing with strings, use const char*.
With STL and std::string, string.c_str() is introduced to be able to convert from std::string to const char*.
That means that if you promise not to change the buffer, you'll be able to use read-only string contents. PROMISE = const char*
In C/C++ programming there are two types of strings: the C strings and the standard strings. With the <string> header, we can use the standard strings. On the other hand, the C strings are just an array of normal chars. So, in order to convert a standard string to a C string, we use the c_str() function.
For example
// A string to a C-style string conversion //
const char *cstr1 = str1.c_str();
cout<<"Operation: *cstr1 = str1.c_str()"<<endl;
cout<<"The C-style string c_str1 is: "<<cstr1<<endl;
cout<<"\nOperation: strlen(cstr1)"<<endl;
cout<<"The length of C-style string str1 = "<<strlen(cstr1)<<endl;
And the output will be,
Operation: *cstr1 = str1.c_str()
The C-style string c_str1 is: Testing the c_str
Operation: strlen(cstr1)
The length of C-style string str1 = 17
c_str() converts a C++ string into a C-style string which is essentially a null terminated array of bytes. You use it when you want to pass a C++ string into a function that expects a C-style string (e.g., a lot of the Win32 API, POSIX style functions, etc.).
It's used to make std::string interoperable with C code that requires a null terminated char*.
You will use this when you encode/decode some string object you transfer between two programs.
Let’s say you use Base64 to encode some array in Python, and then you want to decode that into C++. Once you have the string you decode from Base64-decoded in C++. In order to get it back to an array of float, all you need to do here is:
float arr[1024];
memcpy(arr, ur_string.c_str(), sizeof(float) * 1024);
This is pretty common use, I suppose.
const char* c_str() const;
It 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.
This array includes the same sequence of characters that make up the value of the string object plus an additional terminating null - character ('\0') at the end.
std::string str = "hello";
std::cout << str; // hello
printf("%s", str); // ,²/☺
printf("%s", str.c_str()); // hello