http://baike.baidu.com/view/1839401.htm
在linux編寫程序如下
#include #include #include int count=0; void ctrl_c_count(int); main() { int c; void (*old_handler)(int); old_handler=signal(SIGINT,ctrl_c_count); while((c=getchar()!='\n')) ; printf("Ctrl_C count=%d\n",count); signal(SIGINT,old_handler); } void ctrl_c_count(int i) { printf("Ctrl_C\n"); count++; } |
這個程序的功能是研究signal函數的應用.
signal 函數是用于設置信號量的處理函數為自定義的。
SIGINT是用戶在終端上按下ctrl+c的而產生信號量
它的系統默認的處理函數為終止正運行的進程
現在把它改成按ctrl+c后,是全局變量count加1的操作
當用戶在終端輸入回車后該進程結束。
且又把SIGINT的處理函數為默認的。
當我把上述程序保存為t.cpp時
利用gcc -o t t.cpp
產生如下錯誤
/tmp/ccGsoxH2.o(.eh_frame+0x11): undefined reference to `__gxx_personality_v0'
解決方法用 gcc -o t t.cpp -lstdc++
為什么會出現這個錯誤:是因為你用gcc編譯.cpp文件.按系統默認.cpp文件是c++的文件格式
另一個方法是用g++ -o t t.cpp 也是可以的
還有一種方法是把文件保存為.c格式,反正里面全是c的代碼
然后用gcc -o t t.c或者是g++ -o t t.c 都是OK的
比較不錯的方法是:
1、在主線程(運行main函數的線程)中利用SetConsoleCtrlHandler注冊的控制事件處理函數(注意:這個函數將運行在另外的線程, 這點可用GetCurrentThreadId驗證之)7 ^& t" R+ _, D3 [. o
2、控制事件產生后, 在控制線程(運行控制事件處理函數的線程)中設置標志量表明程序開始退出( 主線程檢測到標志量變化后將開始等待其余線程退出).控制線程開始等待工作者線程退出完成.
3、各工作者線程檢測到標志量的變化, 退出. V& E; R' u) M% J s
4、控制線程退出
主線程等待其余線程退出完成,退出3 f; C!
0.現狀,數據是個xml文件,每個節點對應的結構體有10個成員變量,共有2000多條數據,用的std::map<string, struct>來保存,用map的find函數進行搜索時的效率極
其低下,循環搜索30條數據竟然要20s+,搓死。
1.為什么這么慢?
最初懷疑是std::map的效率問題,正考慮是否使用std::hast_map來替換,于是了解下兩者之間的差別:
std::map是個自平衡的紅黑樹,他的效率是平均的
hash_map的是一個hash表,只要你的hash算法足夠唯一,你的效率可以達到O(1)
翻書時大牛就在旁邊,就問了他,把情況和他一說。他立刻點名:
用hash_map的效率確實會比map的高,但你的數據才2000多,兩者在這里數量級上的效率差異應該很小。主要的問題應該在于你的map,你的map的value不是一個指針
,而是一個大結構體,這會導致搜索時的內存頻繁被交換出去,因而導致效率低下。
2.按照大牛的建議,修改,測試,消耗的時間由原來的20s+變成了0
這一篇會比較簡短一點,來大概提一下怎麼用 Boost C++ Libraries 的 Locale(官方文件)這個函式庫,來進行字碼的轉換。Locale 這個函式庫主要是提供 C++ 地區化(localization)的功能、並提供一些 Unicode 的處理能力;而 Heresy 在這邊只會針對字碼轉換的部分做說明。
不過在使用時要注意的一點是,Locale 這個函式庫是在 1.48.0 才加入的,算是相當新的一個函示庫,所以要使用前必須要先確定自己使用的 Boost 的版本,確認是否在 1.48.0 以上;另外,他也是 Boost 中少數需要建置(build)的函式庫,並且可以搭配 ICU(官網)或 iconv(官網)來使用,有需要的話請參考官方的建置說明。(註 1、註 2)
基本上,Locale 所提供的轉碼功能相當地簡單,官方文件請參考《Character Set Conversions》。
基本上,Locale 所提供的字碼轉換都是函式的形式,而且這些函式都在 boost::locale::conv 這個 namespace 下,如果要使用的,則是要引入 boost/locale/encoding.hpp 這個 header 檔。
而他提供用來轉碼的函式,則包括了:
-
不同字碼間的轉換-between()
這個函式是用來將字串在不同的字碼間進行轉換用的,他的介面是:
string between( string const &text,
string const &to_encoding,
string const &from_encoding,
method_type how=default_method)
他基本本上只能針對 string 做處理,不支援 wstring。
使用上相當簡單,第一個參數 text 就是要進行編碼轉換的字串,第二個參數 to_encoding 則是要轉換成什麼編碼,第三個參數 from_encoding 則是描述 text 是用哪種編碼(註 3)。
而最後一個參數 how 則是 Locale 的一個列舉型別,代表在轉換失敗的時候,要做什麼處理;基本上只有兩個選項,skip 和 stop,預設會是 skip,也就是無視無法轉換的字元、其他繼續處理。
下面就次一個簡單的例子,他會把 source 這個字串從 BIG5 轉換到 UTF-8:
string source = "....";
string s = boost::locale::conv::between( source, "UTF-8", "BIG5" );
-
轉換到 UTF-to_utf()
這個函式是將特定編碼的 string,轉換成 UTF 字串用的,它的介面基本上是:
template<typename CharType>
basic_string<CharType> to_utf( string const &text,
string const &charset,
method_type how )
他除了可以輸出 string 之外,也可以支援輸出成 wstring。像下面的例子,就是把 sSource 這個 BIG-5 編碼的字串,依序轉換成 wstring 和 string 的字串。
string sSource = "...";
wstring ws = boost::locale::conv::to_utf<wchar_t>( sSource, "BIG5" );
string ss = boost::locale::conv::to_utf<char>( sSource, "BIG5" );
-
從 UTF 轉成其他編碼-from_utf()
這個函式和上面介紹的 to_utf() 相反,他是把 UTF 字串(string 或 wstring)、轉換為特定編碼的字串用的。它的介面是:
template<typename CharType>
string from_utf( basic_string<CharType> const &text,
string const &charset,
method_type how )
他可以轉換 string 或 wstring 的字串,但是輸出一定是 string。
下面的例子,就是把 sSource 和 wSource 這兩個 UTF 字串,都轉換成 BIG-5 的 string 字串。
string sSource = "...";
wstring wSource = L"...";
string ss1 = boost::locale::conv::from_utf( wSource, "BIG5" );
string ss2 = boost::locale::conv::from_utf( sSource, "BIG5" );
-
Unicode 之間的轉換-utf_to_utf()
這個函式的目的,是在 UTF 的 string 字串和 wstring 字串之間做轉換;他的介面如下:
template<typename CharOut,typename CharIn>
basic_string<CharOut> utf_to_utf( basic_string<CharIn> const &str,
method_type how )
下面的例子,就是把型別是 string 的 sSource 轉換成 wstring、並把型別是 wstring 的 wSource 轉換成 string 了~
string sSource = "...";
wstring wSource = L"...";
wstring wStr = boost::locale::conv::utf_to_utf<wchar_t>( sSource );
string sStr = boost::locale::conv::utf_to_utf<char>( wSource );
這篇就寫到這裡了。基本上,Locale 所提供的字碼轉換的功能,在 Heresy 來看算是相當簡單好用的~至少和直接用 iconv 比起來,真的簡單不少…對於有需要在程式中進行字碼轉換的人來說,Heresy 是覺得可以試試看用 Boost 的 Locale 這個函式庫來做做看啦~
而實際上,Locale 還有許多其他的功能,但是因為 Heresy 還用不太到,所以暫時就不研究了。
不過另外 Heresy 覺得可能比較實用的,是他的《Messages Formatting (Translation) 》的部分~或許等有需要的時候,會來看看這一塊吧。
附註:
-
在 Windows 平臺上,應該是可以不搭配 ICU 和 iconv 來使用的;但是在 POSIX 平臺上,則似乎一定要有 ICU 或 iconv 其中一個。
-
Heresy 有試著想在 Windows 平臺上整合 ICU,不過感覺好像不是很成功…
不過一個經驗是,似乎不能直接下載 ICU 的 binary 來作為 Boost 建置時的 ICU 路徑,而是需要下載 source code 來自己建置 ICU 才可以。但是雖然 Heresy 成功地讓 Boost 抓到 ICU 了,但是在試著轉碼的時候,他似乎還是去用 Windows 內建的 codepage、沒去用 ICU 的…
-
編碼基本上是直接以字串來做輸入,例如中文就是「BIG5」、Unicode 則是使用「UTF-8」; 另外也可以使用 std::locale(參考)來作為指定編碼的參數。
至於有支援那些編碼,則是要看是使用哪種字碼轉換的模組,例如有使用 iconv 和 ICU 的話,就是看 iconv 和 ICU 有支援什麼了~而在 Windows + MSVC 環境下,如果都沒用的話,Boost 會使用 Windows 內建的 code page 來做處理,列表可以參考 Boost 目錄下的 \libs\locale\src\encoding\wconv_codepage.ipp 這個檔案裡的 all_windows_encodings 這個陣列。
-
上述 Locale 所提供的轉換函式,都可以改用 char* 或 wchar_t* 作為輸入的字串。
-
FreeType 的 ft_encoding_unicode 可以使用 wsting 的 UTF 字串。
-
要在 standrad IO 輸出 wstring 這轉寬字元字串,不能使用 cout,而是要使用 wcout;而如果要輸出中文字串的話,則是需要透過 ostream 的 imbue() 這個函式,來做區域的設定。下面是一個例子:
wstring wSource = L"中文";
wcout.imbue( std::locale( "cht" ) );
wcout << wSource << endl;
http://blog.csdn.net/serverxp/article/details/5538017
最近在做一套跨平臺的短信收發開發程序,遇到了一個問題,那就是文字編碼轉換。在windowsg下的轉換有庫函數
MultiByteToWideChar WideCharToMultiByte,這二個,但是我要的是在linux機器下也可以正常使用,所以google了一天,發現了二個解決方案,一個是libiconv,一個就是ICU了,實際使用后,發現還是ICU更好用,下面是一個簡單的例子。
- #include <unicode/ucnv.h>
- #ifdef _WIN32
- #pragma comment(lib, "icuuc.lib")
- #endif
- //返回0為成功,錯誤代碼定義見后面
- int convert(const char * toConverterName,
- const char * fromConverterName,
- char * target,
- int32_t targetCapacity,
- const char * source,
- int32_t sourceLength)
- {
- UErrorCode error = U_ZERO_ERROR;
- ucnv_convert(toConverterName,fromConverterName,target, targetCapacity, source, sourceLength, &error );
- return error;
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- wchar_t aaa[] = L"中國人的系統上123323";
- int alen = wcslen(aaa);
- int blen=alen*2+sizeof(int);
- char *abuff=new char[blen];
- int result = convert( "gb2312", "utf-16le", abuff, blen, (const char *)aaa, alen);
- cout << abuff << endl<<strlen(abuff)<<endl;
- delete []abuff;
- return 0;
- }
utf-8格式的xml指令,存儲在標準的std::string中,怎么把這個string轉化成普通的多字節的string
utf-8編碼中漢字是3個字節或以上的,普通的多字節不是這樣表示的....
#include <stdio.h>
#include <string.h>
// UTF-8的unicode表示方法到unicode的值轉換函數
bool utf82unicode(unsigned int byte[], int index, int count, int& unicode)
{
/* for (int i=index; i < count; ++i) {
printf("byte[%d]:%0Xn",i, byte[i]);
}
printf("byte[index] & 0x80: %0Xn", byte[index] & 0x80);
printf("byte[index] & 0xE0: %0Xn", byte[index] & 0xE0);
printf("byte[index] & 0xF0: %0Xn", byte[index] & 0xF0);
*/
if (index >= count) return false;
if ( (byte[index] & 0x80) == 0x0) // 一位
{
unicode = byte[index];
}
else if ((byte[index] & 0xE0) == 0xC0) // 兩位
{
if (index + 1 >= count ) return false;
unicode = (((int)(byte[index] & 0x1F)) < < 6)
| (byte[ index + 1] & 0x3F);
}
else if ((byte[index] & 0xF0) == 0xE0) // 三位
{
if (index + 2 >= count) return false;
unicode = (((int)(byte[index] & 0x0F)) < < 12)
| (((int)(byte[index + 1] & 0x3F)) < < 6)
| (byte[index + 2] & 0x3F);
}
else if ((byte[index] & 0xF8) == 0xF0) // 四位
{
if (index + 3 >= count) return false;
unicode = (((int)(byte[index] & 0x07)) < < 18)
| (((int)(byte[index + 1] & 0x3F)) < < 12)
| (((int)(byte[index + 2] & 0x3F)) < < 6)
| (byte[index + 3] & 0x3F);
}
else if ((byte[index] & 0xFC) == 0xF8) // 五位
{
if (index + 4 >= count) return false;
unicode = (((int)(byte[index] & 0x03)) < < 24)
| (((int)(byte[index + 1] & 0x3F)) < < 18)
| (((int)(byte[index + 2] & 0x3F)) < < 12)
| (((int)(byte[index + 3] & 0x3F)) < < 6)
| (byte[index + 4] & 0x3F);
}
else if ((byte[index] & 0xFE) == 0xFC) // 六位
{
if (index + 5 >= count) return false;
unicode = (((int)(byte[index] & 0x01)) < < 30)
| (((int)(byte[index + 1] & 0x3F)) < < 24)
| (((int)(byte[index + 2] & 0x3F)) < < 18)
| (((int)(byte[index + 3] & 0x3F)) < < 12)
| (((int)(byte[index + 4] & 0x3F)) < < 6)
| (byte[index + 5] & 0x3F);
}
else
{
return false;
}
return true;
}
然后unicode到多字節
ps. 轉的,代碼上有錯誤的,沒仔細看,只看了下思路思想,很不錯,特別鄙視那種死咬人家錯誤不放的人,嗎的,誰寫代碼沒個錯誤,誰能代碼一寫出來就不用改不用來回推敲. 人家目的是向你介紹思想,思想你明白了不就行了.
=======================================================
最近在用VC++開發一個小工具,平時用慣了.NET,用起VC++最郁悶的就是字符串 處理。當然最最讓人難于琢磨的就是字符集,編碼之間的轉換。通過這幾天的研究,終于明白了Unicode和UTF-8之間編碼的區別。Unicode是一 個字符集,而UTF-8是Unicode的其中一種,Unicode是定長的都為雙字節,而UTF-8是可變的,對于漢字來說Unicode占有的字節比 UTF-8占用的字節少1個字節。Unicode為雙字節,而UTF-8中漢字占三個字節。
網魂小兵 http://xdotnet.cnblogs.com
UTF-8編碼字符理論上可以最多到6個字節長,然而16位BMP(Basic Multilingual Plane
)字符最多只用到3字節長。下面看一下UTF-8編碼表:
U-00000000 - U-0000007F: 0xxxxxxx
U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx xxx 的位置由字符編碼數的二進制表示的位填入, 越靠右的 x 具有越少的特殊意義,只用最短的那個足夠表達一個字符編碼數的多字節串。 注意在多字節串中, 第一個字節的開頭"1"的數目就是整個串中字節的數目。而第一行中以0開頭,是為了兼容ASCII編碼,為一個字節,第二行就為雙字節字符串,第三行為3 字節,如漢字就屬于這種,以此類推。(
個人認為:其實我們可以簡單的把前面的1的個數看成字節數)
網魂小兵 http://xdotnet.cnblogs.com 為了要將Unicode轉換為UTF-8,當然要知道他們的區別到底在什么地方。下面來看一下,在Unicode中的編碼是怎樣轉換成UTF-8的,在UTF-8中,如果一個字符的字節小于0x80(128)則為ASCII字符,占一個字節,可以不用轉換,因為UTF-8兼容ASCII編碼。假如在Unicode中漢字“你”的編碼為“u4F60”,把它轉換為二進制為100111101100000,然后按照UTF-8的方法進行轉換。可以將Unicode二進制從地位往高位取出二進制數字,每次取6位,如上述的二進制就可以分別取出為如下所示的格式,前面按格式填補,不足8位用0填補。
unicode: 100111101100000 4F60
utf-8: 11100100,10111101,10100000 E4BDA0
從上面就可以很直觀的看出Unicode到UTF-8之間的轉換,當然知道了UTF-8的格式后,就可以進行逆運算,就是按照格式把它在二進制中的相應位置上取出,然后在轉換就是所得到的Unicode字符了(這個運算可以通過“位移”來完成)。
網魂小兵 http://xdotnet.cnblogs.com 如上述的“你”的轉換,由于其值大于0x800小于0x10000,因此可以判斷為三字節存儲,則最高位需要向右移“12”位再根據三字節格式的最高位為 11100000(0xE0)求或(|)就可以得到最高位的值了。同理第二位則是右移“6”位,則還剩下最高位和第二位的二進制值,可以通過與 111111(0x3F)求按位于(&)操作,再和11000000(0x80)求或(|)。第三位就不用移位了,只要直接取最后六位(與 111111(ox3F)取&),在與11000000(0x80)求或(|)。OK了,轉換成功!在VC++中的代碼如下所示(Unicode到UTF-8的轉換)。
1 const wchar_t pUnicode = L"你";
2 char utf8[3+1];
3 memset(utf8,0,4);
4 utf8[0] = 0xE0|(pUnicode>>12);
5 utf8[1] = 0x80|((pUnicode>>6)&0x3F);
6 utf8[2] = 0x80|(pUnicode&0x3F);
7 utf8[3] = "\0";
8 //char[4]就是UTF-8的字符“你”了。
當然在UTF-8到Unicode的轉換也是通過移位等來完成的,就是把UTF-8那些格式相應的位置的二進制數給揪出來。在上述例子中“你”為三個字節,因此要每個字節進行處理,有高位到低位進行處理。在UTF-8中“你”為11100100,
10111101,
10100000。從高位起即第一個字節
11100100就是把其中的"0100"給取出來,這個很簡單只要和11111(0x1F)取與(&),由三字節可以得知最到位肯定位于12位之前,因為每次取六位。所以還要將得到的結果左移12位,最高位也就這樣完成了
0100,000000,000000。而第二位則是要把“111101”給取出來,則只需將第二字節
10111101 和111111(0x3F)取與(&)。在將所得到的結果左移6位與最高字節所得的結果取或(|),第二位就這樣完成了,得到的結果為 0100,111101,000000。以此類推最后一位直接與111111(0x3F)取與(&),再與前面所得的結果取或(|)即可得到結果 0100,111101,100000。
OK,轉換成功!在VC++中的代碼如下所示(UTF-8到Unicode的轉換)。
1 //UTF-8格式的字符串
2 const char* utf8 = "你";
3 wchar_t unicode;
4 unicode = (utf8[0] & 0x1F) << 12;
5 unicode |= (utf8[1] & 0x3F) << 6;
6 unicode |= (utf8[2] & 0x3F);
7 //unicode is ok!
網魂小兵 http://xdotnet.cnblogs.com 當然在編程過程中不可能只轉換一個字符,這里需要注意的是字符的長度一定要算清楚,不然會帶來...以上就是我這幾天研究的結果,至于Unicode的轉換為GB2312在MFC中Windows有自帶的API(WideCharToMultiByte)可以轉換。這樣也就能夠將UTF-8格式轉換為GB2312了,這里就不再贅述,如果大家有更好的方法希望指教。