2014-11-08 105 views
10

考慮這個示例程序:printf(「%s」),printf(「%ls」),wprintf(「%s」)和wprintf(「%ls」)有什麼區別?

#include <cstdio> 
#include <cwchar> 
#include <string> 

int main() 
{ 
    std::string narrowstr = "narrow"; 
    std::wstring widestr = L"wide"; 
    printf("1 %s \n", narrowstr.c_str()); 
    printf("2 %ls \n", widestr.c_str()); 
    wprintf(L"3 %s \n", narrowstr.c_str()); 
    wprintf(L"4 %ls \n", widestr.c_str()); 

    return 0; 
} 

的這個輸出是:

1 narrow 
2 wide 

我想知道:

  1. 爲什麼3 & 4沒有打印
  2. 什麼差異在1 & 3和2 & 4.
  3. 它是否有任何區別,如果narrowstr在utf8中而且vasttr在utf16中?
+1

你看了文檔?值得注意的是[cstdio](http://www.cplusplus.com/reference/cstdio/)? – 2014-11-08 11:24:57

+0

「vasttr is in utf16」意味着您使用的是Windows(更適合Unicode的系統使用UTF-32作爲寬字符串的默認值)。如果你想在WIndows系統上使用標準的C++或C來完成除ASCII以外的任何事情,那麼有很多神祕的箍環可以跳轉。你也可以投入並使用WinAPI。 – Cubbi 2014-11-13 02:59:23

+0

不要投放到MICROSOFT STUPIDITY。節省自己的痛苦並編寫自己的字符串庫。對於上帝的愛不要使用Windows宏觀轉換和其他瘋狂,相信我,這是可怕的,並在混亂中各種錯誤蔓延。 – Owl 2017-05-12 14:38:00

回答

0

1和2的答案在文檔中。任何一套好的文檔都可以。他們說cppreference是非常好的。

至於3,語言標準沒有指定任何特定的字符串編碼或任何特定的尺寸wchar_t。你需要參考你的實現文檔,而不是語言本身(儘管編寫依賴於實現的代碼是很不明智的)。

5

你需要做的:

wprintf(L"3 %hs \n", narrowstr.c_str()); 
wprintf(L"4 %s \n", widestr.c_str()); 

爲什麼?因爲對於printf,%s表示窄字符串。對於wprintf%ls說寬。

但是,對於wprintf%S意味着廣,%LS將意味着廣本身。 %hs意味着縮小(對於兩者)。對於printf%S,以這種方式將僅僅意味着%HS

在VC++/Windows中,%S(大寫S),將扭轉的效果。因此,printf("%S")這意味着寬,wprintf("%S")意味着狹窄。這對於_tprintf很有用。

+0

這也不打印任何東西。 [鏈接](http://ideone.com/ZCiDb1) – 2014-11-08 21:02:51

+0

堅持!爲什麼它甚至不打印數字?你檢查過wprintf的作品嗎? – Ajay 2014-11-08 21:05:32

5

請注意,您正在使用C流。 C流具有非常特殊的質量,稱爲「定位」。流是不定向的,寬的或狹窄的。方向是通過任何特定流所發出的第一輸出決定(見http://en.cppreference.com/w/cpp/io/c的CI/O流的彙總)

在你的情況,stdout開始時未取向,並通過執行第一printf,你設置它窄。一旦縮小,它會陷入狹窄,並且wprintf失敗(檢查其返回代碼!)。更改C流的唯一方法是freopen它,它不適用於標準輸出。這就是爲什麼3和4沒有打印。

1和3之間的區別在於1是使用窄字符串轉換說明符%s的窄輸出函數:它從char數組讀取字節並將字節發送到字節流中。3是一個具有窄字符串轉換說明符%s的寬輸出函數:它首先從char數組中讀取字節並將它們讀入wchar_ts,然後將wchar_ts發送到一個寬流中,然後wctomb將它們轉換爲字節或多字節序列然後用write

將其推送到標準中。最後,如果widestr位於utf16中,則必須使用Windows,並且所有投注都關閉;在該平臺上對ASCII以外的任何內容都沒有支持。你不妨給並使用WinAPI的(你可以用標準C++ 11的一些Unicode的東西度日,甚至做C的輸出,用咒語_setmode(_fileno(stdout), _O_U16TEXT);,一個已經討論足夠多的次數)

相關問題