分享

C語言-curses的UTF-8亂碼解決方案

 紫火神兵 2012-10-18
最後還是不死心,想要在ubuntu下不經過環境設定轉換的方式找出curses對UTF-8的亂碼有一個直接的解決辦法

終於google到幾篇文章
http:///?p=92
http://my./mingfal/blog/show.dml/395261
還有一個英文的(雖然看不懂,但丟到google翻譯倒也知道了個幾分的意思)
http://mail.nl./linux-utf8/2004-08/msg00001.html

裏面所提的重點這裡不在贅述,只是我照著做以後發生了一個問題......
setlocale(LC_ALL,"");
這個函數一加到程式裏面就有了"include不進來?"的問題
http://phorum./index.php/topic,52403.0.html

解決方法呢?靠著一點點運氣,一點點經驗跟很多很多的到google大廟內參拜終於找到一個函數庫,這也就是第1點
1.從[系統]-->[管理]-->[synaptic套件管理程式]-->[搜尋]-->搜尋欄位輸入" locale "..搜尋於欄位選擇"描述及名稱"
這時會出來一大堆套件,不過我們要找的是一個"函數庫"所以只找libxxx名稱的套件,而以lib開頭的函數庫也還滿多的,再把目標縮小到有ubuntu標誌的那幾個
於是終於可以看到一個名為 libicu-dev 的函數庫
其實我也看不懂libicu-dev到底是做啥的!?只是看到其描述最後一句.....for unicode...就把他送到google大廟的偏殿google全文翻譯去....嗯...應該就是他沒錯了

然後呢??還是不行呀,拿出一點點經驗跟一點點想像力...很像跟編碼有關的都歸 locale 管的樣子,那麼是否有一個叫作 locale.h 的含引檔呢?
2.加入含引檔 #include <locale.h>
locale既然是一個在系統下的命令,那他也就是一個程式?既然是一個程式,那他就有可能有一個函數庫可供使用,函數庫..這都要有一個含引檔吧!
而以命名習慣來說你再給人亂取一通不是在找麻煩嘛XD.....(後面這句自己亂加的當沒看到吧XD)
如果第1.沒做直接做這裡說不定也是可以的,只是我所安裝的ubuntu8.04的版本算是一個"很乾淨"的版本,所以一些程式開發的東西可能都還要抓才可以

好了!由上面google到的3篇文章來說可以知道幾個訊息... curses 與 ncurses 是不同的函數庫,而可以處理UTF-8碼的函數庫名稱叫作  ncursesw 所以了
3.原來的#include <curses.h> 或 #include <ncurses.h> 要改成 #include <ncursesw.h> 或是 #include <ncursesw/ncurses.h>
至於該改成怎樣這就要看在您的系統下ncursesw到底是怎麼樣子的,比如我用檔案瀏覽器的搜尋功能去找 ncursesw 他有找到一個資料夾
名字剛好就是ncursesw(不過為何檔案瀏覽器沒辦法顯示點選物件的路徑呀?)所以我的是#include <ncursesw/ncurses.h>

然後在編譯指令也必須聯結到這一個ncursesw
4.原來的編譯指令gcc ..... -lcurses 或 gcc ..... -lncurses 則改成 gcc ..... -lncursesw 表示我們要聯結的是支援UTF-8的ncursesw函數庫不是curses也不是ncurses
xxx.h有可能會因為寫作技巧的關係讓我們叫用curses.h,ncurses.h,ncursesw.h都是一樣的(不過我沒試過,有興趣可以試一下),而且在英文的那個文件
看起來的意思(本人英文很差只能靠google翻出來2266的中文來猜)也是說ncursesw是專為UTF-8寫的一個函數庫所以這一步驟是滿重要的

還有在我實際使用時有一點也是覺得滿重要的
5.在初始化curses函數庫的 initscr() 前必須先叫用 setlocale(LC_ALL,"") 函數,順序不可以弄反了
其實這個也不算重點,就是一個邏輯上的關係而已,只是如果不提出來,又剛好死不死的就是弄錯順序了.那老是在抓前面4個點的錯誤....這不是很冤嗎^^!


最後有一點注意的,就是utf-8的編碼方式是不定長度的,也就是說編出來的一份文件不再是一個英數字型是1Byte一個中文字是2Byte的
這是我昨天寫來算一份文件(字串)要對應到螢幕上座標位置的片段
代碼: [選擇]
  for(n=0,y=dspy;n<size;y++)
  {
    for(bt=128,byt=0;bt>1;(bt/=2),byt++)/*求出這個utf-8編碼共佔多少Byte*/
      if(!(*(str+n) & bt))
        break;
  }

而這兩個函數是昨天想自行重組utf-8後丟進curses的觀察用工具(結果當然是失敗做收啦>"<),不過滿有趣的,跟危機百科的utf-8
http://zh./wiki/UTF-8
相互對照一下,看看倒底UTF-8都在編些啥東東@@!
代碼: [選擇]
/*顯示字串*str共size位元每一個Byte的Bit狀態主要是察看utf-8的狀態*/
int lee_utf8bitdsp(char *str,int size,int dspx,int dspy)
{

  int i,n,b,x,y,bt,byt;

  for(n=0,y=dspy;n<size;y++)
  {
    for(bt=128,byt=0;bt>1;(bt/=2),byt++)/*求出這個utf-8編碼共佔多少Byte*/
      if(!(*(str+n) & bt))
        break;
    if(byt<1)
    {
      lee_bitdsp(str+n,1,dspx,y);
      n+=1;
    }
    else
    {
      lee_bitdsp(str+n,byt,dspx,y);
      n+=byt;
    }
  }
  refresh();
}

/*將從*ptr開始的位置共len個Byte的每一Bit狀態顯示出來*/
int lee_bitdsp(char *ptr,int len,int dspx,int dspy)
{
  int i,x,b;

  for(i=0,x=dspx;i<len;i++)
  {
    for(b=128;b>0;(b/=2),x++)
    {
      if((*(ptr+i) & b))
        mvprintw(dspy,x,"1");
      else
        mvprintw(dspy,x,"0");
    }
    if(len>1)
    {
      mvprintw(dspy,x,",");
      x+=1;
    }
  }
}
主題: 回覆: C語言-curses的UTF-8亂碼解決方案
作者: stlee2008-07-09 17:41
想說有個setlocale()相對的應該會有getlocale()才對!?

結果並沒有=.=

後來在locale.h中看到setlocale()的函數原型
extern char *setlocale (int __category, __const char *__locale) __THROW;

原來這一個函數的返回值是一個*char

代碼: [選擇]
char *tmp;

tmp=setlocal(LC_ALL,"");
printf("tmp=%s \n",tmp);
執行結果
代碼: [選擇]
tmp=zh_TW.UTF-8

看來這個函數雖名為set但其實也有做get的動作^^
主題: 回覆: C語言-curses的UTF-8亂碼解決方案
作者: stlee2008-07-13 18:40
本來以為
代碼: [選擇]
char *tmp;

tmp=setlocal(LC_ALL,"");
printf("tmp=%s \n",tmp);

必須將tmp給free()掉,結果反而發生記憶體溢位(剛測出來),所以多次叫用時千萬不要在函數內將tmp給free()掉

============================================================================================
2008.07.19補充:
剛灌好的ubuntu8.04所要下載的函數庫
 libc6-dev  以此為關鍵字讓套件管理程式做搜尋只出來一個套件,這應該是標準函數庫,如無該函數庫則最簡單的hi程式都無法做編譯
 ncursesw  這是支援utf-8的curses函數庫,以此為關鍵字讓套件管理程式做搜尋時共出來3個但內定只有一個是有被安裝的,以-dbg與-dev結尾的未被安裝(都裝起來吧)
 libicu-dev  以此為關鍵字讓套件管理程式做搜尋只出來一個套件,這就是locale所需的函數庫了
主題: 回覆: C語言-curses的UTF-8亂碼解決方案
作者: stlee2008-07-30 19:38
locale函數庫中關於該編碼所在地的貨幣及數字(應指小數點及進位分隔符號如千位以'號分隔)訊息
可以用localeconv()函數取得

代碼: [選擇]
aaa()
{
struct lconv *lcv;

lcv=localeconv();
printf("symbo=%s symbol=%s \n",lcv->int_curr_symbol,lcv->currency_symbol);
}
執行結果:
代碼: [選擇]
symbo=TWD  symbol=NT$

而更詳細lconv結構則以檔案搜尋找到locale.h內有宣告該結構原型

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多