Printf With Std::String

printf with std::string?

It's compiling because printf isn't type safe, since it uses variable arguments in the C sense1. printf has no option for std::string, only a C-style string. Using something else in place of what it expects definitely won't give you the results you want. It's actually undefined behaviour, so anything at all could happen.

The easiest way to fix this, since you're using C++, is printing it normally with std::cout, since std::string supports that through operator overloading:

std::cout << "Follow this command: " << myString;

If, for some reason, you need to extract the C-style string, you can use the c_str() method of std::string to get a const char * that is null-terminated. Using your example:

#include <iostream>
#include <string>
#include <stdio.h>

int main()
{
using namespace std;

string myString = "Press ENTER to quit program!";
cout << "Come up and C++ me some time." << endl;
printf("Follow this command: %s", myString.c_str()); //note the use of c_str
cin.get();

return 0;
}

If you want a function that is like printf, but type safe, look into variadic templates (C++11, supported on all major compilers as of MSVC12). You can find an example of one here. There's nothing I know of implemented like that in the standard library, but there might be in Boost, specifically boost::format.


[1]: This means that you can pass any number of arguments, but the function relies on you to tell it the number and types of those arguments. In the case of printf, that means a string with encoded type information like %d meaning int. If you lie about the type or number, the function has no standard way of knowing, although some compilers have the ability to check and give warnings when you lie.

std::string formatting like sprintf

You can't do it directly, because you don't have write access to the underlying buffer (until C++11; see Dietrich Epp's comment). You'll have to do it first in a c-string, then copy it into a std::string:

  char buff[100];
snprintf(buff, sizeof(buff), "%s", "Hello");
std::string buffAsStdStr = buff;

But I'm not sure why you wouldn't just use a string stream? I'm assuming you have specific reasons to not just do this:

  std::ostringstream stringStream;
stringStream << "Hello";
std::string copyOfStr = stringStream.str();

Correct way to printf() a std::string_view?

This is strange requirement, but it is possible:

    std::string_view s{"Hallo this is longer then needed!"};
auto sub = s.substr(0, 5);
printf("=%.*s=\n", static_cast<int>(sub.length()), sub.data());

https://godbolt.org/z/nbeMWo1G1

As you can see you were close to solution.

Best way to safely printf to a string?

This StackOverflow question has a similar discussion. Also in that question I present my favorite solution, a "format" function that takes identical arguments to printf and returns a std::string.

Using printf to print string value

Use std::cout instead of printf.

The problem is that you are passing a std::string to printf, when you actually need a const char*. Using std::string::c_str solves this. But its better to not use printf in the first place.

Live working example

#include <iostream>
#include <string>

int main(int argc, char** argv)
{
std::string hi[] = { "hi", "cool", "what" };

for (const std::string& s : hi) {
std::cout << s << std::endl;
}

return 0;
}

C++ printf(%s , string) is giving me very strange output

For printf you need a c-style string. Use wantedString.c_str().

Why dont c++ strings work with scanf and printf

The reasons std::string can't be used with printf is that std::string is not a sequence of characters.

The printf function expects a sequence of characters terminated by '\0'.

For all we know the std::string class could be implemented as:

class string
{
unsigned int capacity;
unsigned int size;
char * p_char_sequence;
};

As you can see, the first two items are not characters.

Also, there are not printf format specifiers for std::string.

In summary, there is no guarantee that the first items in memory of a std::string are the characters; it could be a class or structure.

There is a mitigation, the std::string::c_str() method. This method returns a pointer to a C-Style string equivalent of the std::string contents.

Edit 1: scanf

The scanf function is more interesting. The scanf function requires a pointer to an array of characters. There is no guarantee that the first memory address in a std::string is a sequence of characters. See printf explanation above.

Also, there is no guarantee that the pointer returned by std::string::c_str() is valid for receiving characters. It could be a temporary area in memory, used only for output. Thus it can't be used for scanf.

The scanf function will write characters to the array locations until the input is terminated. This means that if you allocate space for 3 characters and the User inputs 20 characters, the scanf function will start overwriting the array and write to whatever follows it. This could trigger a system error (such as writing outside your program's area) or write to hardware addresses. This is why most references say to use fscanf where a limit or capacity can be specified.

Getting different output with printf and cout - C++

it's because rawname is defined as a std::string. You need to use

printf("rawname: %s", rawname.c_str());

The reason is that printf with the %s is expecting a null terminated C string in memory. Whereas a std::string stl string isn't exactly raw - it eventually null terminates in your situation, not sure if that's even a guarantee, since the length is internally managed by stl container class.

Edit:

As pointed out in a comment, internally it's guaranteed to be null terminated. So what you're seeing as 'squiggly lines' is an output of all the allocated but not utilized (or initialized) memory in that string up until the null terminator character.

How to print a string in C++

#include <iostream>
std::cout << someString << "\n";

or

printf("%s\n",someString.c_str());


Related Topics



Leave a reply



Submit