1. 程式人生 > >C++輸出中文字元 C/C++多位元組字元與寬字元的輸出

C++輸出中文字元 C/C++多位元組字元與寬字元的輸出

使用C++標準庫的iostream,可以方便地將控制檯、檔案、字串以及其它可擴充的外部表示作為流來處理,但要處理中文,卻會碰到很多問題。本人原來沒怎麼用過這個iostream,這幾天嘗試用這個寫點東西,一會兒不能輸出中文,一會兒不支援中文檔名的,搞得頭大。網上搜了搜,沒有發現適用於所有情況的解決方案。不過後來自己經過多次測試,基本解決了這些問題,現在寫成文字作為一個總結,也供碰到同樣問題的朋友參考。關於C語言中的 printf和wprintf的中文輸出,本文也進行了探討。

  需要說明的是,我的開發環境是VS 2005(標準庫當然也是微軟實現的),不保證其它環境下是相同的效果。
1、cout和wcout

  在預設的C locale下,cout可以直接輸出中文,但對於wcout卻不行。對於wcout,需要將其locale設為本地語言才能輸出中文:
  wcout.imbue(locale(locale(),"",LC_CTYPE)); // ①
  也有人用如下語句的,但這會改變wcout的所有locale設定,比如數字“1234”會輸出為“1,234”。
  wcout.imbue(locale(""));

2、ofstream和wofstream
  在預設的C locale下,ofstream能正確輸出中文到檔案中,但不支援中文檔名;wofstream支援中文檔名,但不能向檔案中輸出中文。要解決這個問題,需要在開啟檔案之前將全域性locale設為本地語言。將全域性locale設為本地語言後,ofstream和wofstream的問題都解決了,但 cout和wcout卻不能輸出中文了。要讓cout和wcout輸出中文,需要將全域性locale恢復原來的設定,如下所示:

  locale &loc=locale::global(locale(locale(),"",LC_CTYPE)); // ②
  ofstream ofs("ofs測試.txt");
  wofstream wofs(L"wofs測試.txt");
  locale::global(loc); // ③
  ofs<<"test測試"<<1234<<endl;
  wofs<<L"Another test還是測試"<<1234<<endl;

3、printf和wprintf
  加上這兩位C語言中的老兄,問題更加複雜。考慮如下語句(注意s的大小寫):

   printf("%s", "multibyte中文/n"); // ④
   printf("%S", L"unicode中文/n"); // ⑤
   wprintf(L"%S", "multibyte中文/n"); // ⑥
   wprintf(L"%s", L"unicode中文/n"); // ⑦
  預設情況下,⑤、⑦兩條語句不能輸出中文,這兩條語句中字串的形式是unicode形式的。如果在所有輸出語句之前加上如下語句將C語言的全域性locale設定為本地語言(C語言中只有全域性locale)就可以正常輸出了:
  setlocale(LC_CTYPE, ""); // ⑧
  但這會導致cout和wcout不能輸出中文,將C語言的全域性locale恢復後cout和wcout就正常了,如下所示:
  setlocale(LC_CTYPE, "C"); // ⑨
  但恢復後,printf和wprintf輸出Unicode文字又不正常了(輸出MultiByte文字總是正常的)。總不能每寫一個 printf/wprintf就設定一次然後再恢復一次吧?所以,建議不要混用iostream和printf/wprintf,實在要混用,那就讓 printf/wprintf只輸出MultiByte字串,這樣不需要呼叫setlocale(),也就不會影響到cout和wcout。

總結
  總之,用iostream、printf/wprintf輸出中文,有點麻煩。概括起來要點如下:
如果要用wcout,需要在使用之前按語句①將其locale設定為本地語言; 
如果要用ofstream或wofstream,要在開啟檔案之前按語句②將全域性locale設為本地語言並儲存初始的全域性locale。然後在開啟檔案之後,按語句③將全域性locale恢復為初始值; 
不要混用iostream和printf/wprintf。如果要混用,只用printf/wprintf輸出MultiByte字串; 
單獨使用printf/wprintf時,如果要輸出Unicode字串,需要按語句⑧設定C語言的全域性locale。如果只輸出MultiByte字串,則不需設定。 

最後再加上轉帖者(本站站長)的一點話:
  一個程式,一般不會用兩種字串, 要麼用多位元組字串, 要麼用寬字串. 這樣,問題其實就很簡單, 沒作者說得那麼複雜.. 就算有時候需要轉換, 也有專門的函式
(例如,多位元組字元版本的程式,使用COM元件, COM元件需要寬字串. 則可以利用 _bstr_t, CString)..

相關推薦

C char/wchar_t之間的互轉 位元組(MultiByte)和字元(Unicode)互轉

wchar_t wstr[100]=L"wstr"; char str[100]; wcstombs(str,wstr,100);//寬字元轉多位元組 mbstowcs(wstr,str,100);//多位元組轉寬字元 也可以使用:MultiByteToWide

C++輸出中文字元 C/C++位元組字元字元輸出

使用C++標準庫的iostream,可以方便地將控制檯、檔案、字串以及其它可擴充的外部表示作為流來處理,但要處理中文,卻會碰到很多問題。本人原來沒怎麼用過這個iostream,這幾天嘗試用這個寫點東西,一會兒不能輸出中文,一會兒不支援中文檔名的,搞得頭大。網上搜了搜,沒有發現適用於所有情況的解決方案。不過後來

位元組字元字元

多位元組字符集——每個字元的編碼寬度不一,可為一個位元組或多個位元組。  (1)ASCII字元只佔一個位元組  (2)對於中文、日文等用兩個位元組  (3)一個字串中,如何區分哪個是中文字元,那個是ASCII字元呢?  “Windows程式設計”16進

Linux 位元組字元的相互轉化(類似MultiByteToWideChar和WideCharToMultiByte)

Linux下面的沒有命名為 WideCharToMultiByte() 和 MultiByteToWideChar() 函式,WideCharToMultiByte,MultiByteToWideChar是windows下的函式,在linux下也有類似的兩個函式:mbs

帶你玩轉Visual Studio——帶你理解位元組編碼Unicode碼

轉自:http://blog.csdn.net/luoweifu/article/details/49382969 多位元組字元與寬位元組字元 char與wchar_t 我們知道C++基本資料型別中表示字元的有兩種:char、wchar_t。  char叫多位

Windows中兩種字元字元的轉換方法

在Windows中經常需要用到多字元與寬字元的轉換方法,所以多字元(MultiChar)也就是ANSI編碼的方式,而寬字元(WideChar)也就是Unicode編碼的方式。 首先是兩種傳統的轉換方法,分別是MutiByteToWideChar和WideCharToM

C++位元組位元組間的轉換(wchar_tchar轉換)

轉載:https://www.cnblogs.com/zhwl/archive/2012/11/23/2784282.html C++多位元組與寬位元組間的轉換(wchar_t與char轉換) 最近在C++程式設計中經常遇到需要多位元組字元與寬位元組字元相互轉換的問題,一直自己貼那幾句程

C語言輸出中文

#include <stdio.h> #include <wchar.h> #include <locale.h> int main() { wchar_t str[] = L"中文文字解決方案"; setlocale(LC_ALL,"Ch

Linux C語言環境下如何輸出字元 -- 轉載

                自己整理如下C++#include <iostream>#include <string>#include <locale>using namespace std;int main(void) {  wstring w = L"Out中文";

C++ wchar_t 輸出中文問題

本人自學c++,看的是範磊老師的<零起點學通C++> 一書中在第四章 4.5小節中 使用wchar_t輸出中文字無法顯示 書中原始碼如下 #include<iostream> <span style="color:#ff0000;">#

C語言---VS2017---輸出中文亂碼問題解決方案

 今天會員【HiroLCS】提到一個問題,就是在VS2017新建的C/C++控制檯程式顯示的中文竟然是亂碼,效果圖如下:            出現亂碼,必然是編碼問題。而編碼問題就要考慮到多方面的因素,大致分為:檔案編碼、程式碼編碼、輸出結果顯示的編碼。我們只要以此來檢查這

.NET(C#):字元編碼(Encoding)和位元組順序標記(BOM)

什麼是字元順序標記(BOM) 計算機內部資料儲存都是二進位制的,只有知道一段資料的二進位制儲存格式,這段資料才有意義。所謂的文字檔案其實就是用一種特定的字元編碼來將二進位制源資料轉換成文字。多數文字編輯器都可以編輯不同編碼的文字檔案,那麼文字編輯器是怎樣通過源二

c++ UTF8編碼轉為位元組編碼

// UTF8編碼轉為多位元組編碼 string ThriftCommon_ThriftCommonOpt_presult::UTF8ToGBK(const char* strUTF8) { i

VS2017 輸出中文時候亂碼 vs2017 c語言輸出中文亂碼 解決辦法

Visual Studio提供高階儲存選項功能,它能指定特定程式碼檔案的編碼規範和行尾所使用的換行符。在Visual Studio 2017中,該命令沒有預設顯示在“檔案”選單中。使用者需要手工設定,才能顯示該命令。操作方法如下:(1)單擊“工具”|“自定義”命令,彈出“自定義”對話方塊。(2)單擊“命令”

C++字串之間轉化——位元組字符集

一、字串之間轉化 1.string、char*與 const char* <1>string->char* char *ctr = new char[str.length()+1]; strcpy(ctr,str.c_st

c語言一個字元變數儲存字元

#include<stdio.h> int main() { char s; char a = 'a'; scanf("%s",&s); printf("input word is:%s, %c\n",&a

c#輸入一個字串,並把字串的第一個字元變為大寫,如果字串中有空格則把空格的下個字元變為大寫之後輸出

using System; using System.Collections.Generic; using System.Text.RegularExpressions; delegate int MyDelegate();//相當於c函式指標 namespace c

C++位元組位元組 轉換

  wsprintf要求的第一個引數是LPTSTR,假設環境是UNICODE的,那麼LPTSTR相當於就是wchar_t* 就是寬字元指標,在非Unicode環境下就是char*。   有關格式化字串的函式還有如下,詳細用法各位可以檢視MSDN,和上面所介紹的都差不多:     sprintf 單位元組版本

C語言中printf函式對個引數的計算順序和輸出順序

例: [cpp] view plain copy print?#include<stdio.h> void main()   {       int i=2;       printf(”%d,%d,%d,%d,\n”,i++,++i,i,i++);       printf(”%d\n”,

C語言基本資料型別對應位元組大小及printf函式輸出格式

補充說明:4位元組:int(%d),unsigned=unsigned int(%u),long=long int(%ld),unsigned long(%lu),float(%f)8位元組:double(%lf),unsigned long long(%llu),long