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了,这里就不再赘述,如果大家有更好的方法希望指教。