VoidZero
VoidZero

Reputation: 550

why string has to be converted to c_str (c string) when passing to printf?

I am new to C++ and I know I shouldn't be using printf in c++ while I have cout but this was for experiment sake. My Question here is Why we have to convert a string to c_str (c string) while passing to printf in c++ while it works fine without converting in cout. Below is my code

#include<iostream>
#include<stdio.h>
using namespace std;


class A{
int i;
string str;
public:
    A (int value, const string & s) : i(value), str(s){};// constructor
    // setters
    void setvalue(int value) {i = value;}
    void setstr(const string & s) {str = s;}
    //geters
    int get_value() {return i;}
    string get_str() {return str;}

    const char *get_str_cstr() {return str.c_str();}// I didn't get why we have to declare constant


};

int main(){
// new code
A obj1 = {11, "Jill"};

cout<<"value is : "<<obj1.get_value()<<" string is "<<obj1.get_str()<<endl;

// Now we wil change the values in A
obj1.setvalue(2);
obj1.setstr("Jack");
cout<<"value after change is : "<<obj1.get_value()<<" string after change is "<<obj1.get_str()<<endl;

// now we will use printf where get_str dosen't not work


//Error: for below commented printf function
/*In function 'int main()':|
error: cannot pass objects of non-trivially-copyable type 'std::string {aka class std::basic_string<char>}' through '...'|
||=== Build finished: 1 errors, 0 warnings (0 minutes, 0 seconds) ===|
*/

//printf("Value is %d and String is %s",obj1.get_value(),obj1.get_str());

// hence we declare a new char * get_str_cstr to make it work in printf;

printf("Value is %d and String is %s",obj1.get_value(),obj1.get_str_cstr());

return 0;}

I have also provided the error in program comments. Thank you!

Upvotes: 3

Views: 2377

Answers (4)

basav
basav

Reputation: 1495

string is a class in c++ stl. c_str() is a member function of class string .

The signature is:

const _CharT* c_str() const { return _M_start; }

now, coming to printf, its signature is:

int printf ( const char * format, ... );

now, as long as you give it an argument that meets const char * format, it accepts it.

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726569

printf comes from C library, which predates objects, templates, and function overloading. When you specify %s format, the function takes an address of a null-terminated character sequence, and prints it. printf has no idea where the string comes from. In fact, it has no idea of its parameter types, because it uses variable-length parameter list feature.

std::string is a C++ string. Calling c_str() on it produces a pointer to the beginning of a C string, which is suitable for passing to printf and other functions expecting a C string.

cout, on the other hand, has been built with classes and overloading in mind. There is a special overload for operator << for std::string, which lets cout and other output streams extract characters from a C++ string.

Upvotes: 5

NathanOliver
NathanOliver

Reputation: 180585

Because printf() has no idea what a std::string is. The protypes for printf() are

int printf( const char* format, ... );
int fprintf( std::FILE* stream, const char* format, ... );
int sprintf( char* buffer, const char* format, ... );
int snprintf( char* buffer, std::size_t buf_size, const char* format, ... );

The reason std::string works with cout is that std::string provieds operator << which works with cout

Upvotes: 1

Cory Kramer
Cory Kramer

Reputation: 117866

printf is originally from C, which does not have std::string, so the analogous argument type is const char* which is what you get when you call .c_str()

The reason std::cout works with std::string is because operator<< is defined for that class.

Upvotes: 2

Related Questions