Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

printf and custom class

I have my own class that represents a custom string class. I'm using VS2012RC. I have overloaded some operators of my class CustomString.

Here's some code:

CustomString::CustomString(string setstr)
{           
    str = setstr;
}

CustomString::operator const char *()
{   
    return (this->str.c_str());
}

CustomString &CustomString::operator = (char *setstr)
{
    str = setstr;
    return *this;
}

I can define my object and use it like this:

CustomString str = "Test string";

and i can print the result as:

printf(str);

printf((string)(str).c_str());

printf((string)(str).data());

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

printf("%s\n",(string)(str).data());

And there is not any error.

But if i use it like this:

printf("%s\n", str);

There is an exception in msvcr110d.dll (error in memory access)

Why printf(str) is ok, but printf("%s\n",str) is not ok?

How can i modify my code to use printf("%s\n",str) ?

...

After hours of googling, I found that explict cast (string), static_cast (str) and _str() method are add a null-terminated chars: '\0';

i've modified my code as:

printf("%s\n",str + '\0');

and it's worked!

Is there any way to modify my custom constructor to add a null-terminated string and pass a correct value with null-terminated chars to get working the following code:

printf("%s\n",str);
like image 780
user1616375 Avatar asked Sep 06 '25 03:09

user1616375


2 Answers

Don't use printf, its more C-like than C++. Instead, use iostreams, which provide a facility for you to format your own custom classes and send the to a file or stdout.

Here's a quick (untested) example that might work for you:

std::ostream& operator<< (std::ostream &os, const CustomString& str)
{ 
    os << str.data();
    return os; 
} 

and you'd print your custom string to stdout by doing something like

CustomString str;
// put some text in the custom string, then:
std::cout << str << std::endl;
like image 141
Rook Avatar answered Sep 07 '25 22:09

Rook


You can't (at least not in a portable way). printf looks at the object passed as parameter and treats it as a %s, which is a char array. You run into undefined behavior. Also, the parameters passed to printf are, sort of say, type-less.

Why printf(str) is ok?

Because the first parameter is types, and is a const char*. The implicit cast is made via your operator. The rest of the parameters don't behave the same.

I'd use cout instead, and overload operator << (ostream&, const CustomString&).

Don't do this:

I said you can't, in a portable way. For a class like

class CustomString
{
   char* str;
   //...
};

that might work, because of how classes are represented in memory. But, again, it's still undefined behavior.

like image 42
Luchian Grigore Avatar answered Sep 07 '25 21:09

Luchian Grigore