printf 和自定義類 (printf and custom class)


問題描述

printf 和自定義類 (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);

‑‑‑‑‑

參考解法

方法 1:

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.

方法 2:

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;

方法 3:

printf is defined as

int printf(char const *fmt, ...)

passing a class or structure to a ... argument list has undefined behaviour and may work or crash, or just do something random (I've seen all 3) depending on the class and the compiler.

printf(str)

requires a char *, and the compiler finds you have an appropriate casting operator, so it invokes it. Note that this is pretty dodgy as you have no idea if str might or might not have a % in it.

So, you to do want printf("%s", str) but as you have said, that doesn't work. Some compilers will give you a warning (though 'warning: This will crash' as produced by gcc isn't, in my opinion, terribly well thought out), so you have to force it to be cast to a string. So, your best solution is to explicitly cast it yourself,

printf("%s", static_cast<char const *>(str));

I'm not sure how much code all of the examples you've got there would require, as most of them are going to involve constructing a std::string from your custom string, then outputting it, then deleting the std::string.

方法 4:

You have to use printf("%s\n", str.c_str());%s expects a char array and you gave it a CustomString object which is something different. You have to get char array from the string by calling c_str() function.

(by user1616375Luchian GrigoreRookTom TannerAdam Sznajder)

參考文件

  1. printf and custom class (CC BY‑SA 3.0/4.0)

#printing #visual-studio-2012 #C++






相關問題

是否可以創建網頁打印視圖的 PDF? (Is it possible to create a PDF of a webpage's print view?)

使用 PHP 打印到共享的 windows 打印機 (Linux PHP Server) (Using PHP to print to a shared windows printer (Linux PHP Server))

printf 和自定義類 (printf and custom class)

Firefox 無法訪問同一域上的 iframe 打印 (Firefox can't access iframe print on the same domain)

在python 3中動態打印一行 (Printing a line dynamically in python 3)

用於打印 div 的 JS 函數 - 在 Chrome 中不起作用? (JS function to print div - Doesn't work in Chrome?)

進程 WaitForExit 不等待 (Process WaitForExit not waiting)

你能給我打印屏幕並在javascript或flash中轉換為jpg的功能嗎 (Could you please give me the function of taking print screen and convert in to jpg in javascript or flash)

當我使用轉換時,我的打印輸出看起來不像打印預覽 (My printout doesn't look like the print preview when I use a Transform)

如何在 C# 中使用 PrintDialog 打印文檔 (How to print a document using PrintDialog in C#)

MKMapView 遮擋是否剔除它的註釋? (Does MKMapView occlusion cull it's annotations?)

在網絡環境中從 Brother TD-4100N 打印機檢索打印機狀態 (Retrieving the printer status from the Brother TD-4100N printer in a network environment)







留言討論