Why am I getting these symbols in console, using printf()? [duplicate] - c++

This question already has answers here:
printf with std::string?
(9 answers)
Read into std::string using scanf
(7 answers)
Closed 10 months ago.
I have question about output in console
string str;
scanf("%s", str);
printf("%s", str);
Why do I get strange symbols, which have trouble with encoding?

std::string is a class (user-defined type). On the other hand, the conversion specifier s is designed to input or output character arrays. So the code snippet has undefined behavior.
Instead you could use operators >> and << overloaded for the class std::string to input or output data from/to streams like
std::string str;
std::cin >> str;
std::cout << str << '\n';
If you want to use the functions scanf and printf then use character arrays as for example
char str[100];
scanf( "%99s", str );
printf( "%s\n", str );
If as you wrote in a comment
I have a task, out string with help printf.
then in this case you should check whether string is indeed the standard C++ type or an alias for the type char * introduced like for example
typedef char *string;
or like
using string = char *;

printf and scanf expect variables of type [const] char * with an "%s" format specifier.
In general, the other answer to use std::cin / std::cout instead is preferrable.
If you absolutely must use printf to output a std::string, use the c_str() method to get access to a const char * representing the same string as in the std::string; example:
string str;
std::cin >> str;
printf("%s", str.c_str());
Note the const in const char* c_str() - meaning you are not allowed to change the returned string. So, it cannot be used for scanf. There, you'd have to stick to a char *...

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

Initializing std::string with const char * results in gibberish

I use rapidjson to read JSON files, and some of the values are string. Now, rapidjson's GetString() method returns a const char *. I'd like to store this in std::string, though. I've tried this:
const char* foo = d["foo"].GetString();
printf("Foo: %s\n", foo); // Prints correctly
std::string fooStr(foo);
printf("FooString: %s\n", fooStr); // Gibberish
How do I get the correct std::string?
You can't pass std::string directly to printf. It's a C-style variadic function, that only works with C-compatible types, not (non-trivial) C++ classes. In particular, the %s specifier requires its matching argument to be a pointer to C-style string (a zero-terminated character array), of type const char *.
You can either use a C++ stream:
std::cout << "FooString: " << fooStr << '\n';
or extract a C-style pointer from the string:
printf("FooString: %s\n", fooStr.c_str());
You should also enable compiler warnings; that should tell you exactly what's wrong.
To convert string to const char* use string::c_str()

Why do I get an exception when I pass a std::string to printf? [duplicate]

This question already has answers here:
printf with std::string?
(9 answers)
Closed 9 years ago.
#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
int main()
{
char a[10] = "asd asd";
char b[10] ="bsd bsd";
string str(a);
str.append(b);
printf("\n--------%s--------\n", str);
return 0;
}
I can't understand why this produces an exception? This program mainly tries to append strings. I get the desired output when using std::cout but not when using printf.
Because std::string is not the same as char const *, which is what the %s format specifies. You need to use the c_str() method to return the pointer expected by printf():
printf("\n--------%s--------\n", str.c_str());
To be more technical, printf() is a function imported from the C world and it expects a "C-style string" (a pointer to a sequence of characters terminated by a null character). std::string::c_str() returns such a pointer so that C++ strings can be used with existing C functions.
c_str(). Have to use style string using this function..
printf() handles c strings (char *), you are using a c++-style string and therefore need to convert between them.
Simply use the c_str() method like so
printf("%s", str.c_str());
printfs %s format specifier is expecting a C style string not a std::string, so you need to use c_str() which return a const char*:
printf("\n--------%s--------\n", str.c_str());
Basically you have undefined behavior since printf will try to access your argument as if it was a pointer to a null terminated C style string. Although, since this is C++ you should just use std::cout is safer.

c++ char to const char* [duplicate]

This question already has answers here:
C++ convert char to const char*
(5 answers)
Closed 10 years ago.
I need to convert a character in a character array to a const char * in order to print it to a file using fstream. I'm not sure exactly how to do so. I've tried putting the single char into a string, then using c_str(), but that does not work..
If you want to write a single character, just use operator<<:
char arr[256] = "...";
fstream f(...);
f << arr[2];
You don't need to convert the character to a C string.
Hm... If you have a character array, that already decays into char * when passed to a function.
If you need only one character:
char array[128]; // whatever - you want to extract the char from this
char s[] = { array[64], 0 };
then use s which now can decay into char *.
Edit: D'oh, I just read this:
in order to print it to a file using fstream
Well, then don't bother converting it to a proper C string. operator<< knows its job, and it's overloaded for char too.

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.