2009-11-03 4 views
11

私は引数としてファイルを使用するアプリケーション用の小さなラッパーを作成しています。Unicode "argv"を使用することはできますか?

ラッパーはUnicodeである必要があるので、私は文字と文字列にwchar_tを使用しています。今私は自分自身が問題に遭遇しているので、プログラムの引数をwchar_tの配列とwchar_t文字列に入れておく必要があります。

可能ですか?私は

int main(int argc, char *argv[]) 

私はargv用のwchar_tのを使用すべきとしてmain関数を定義していますか?

は、私はとにかくC.

で正しくWindowsで

答えて

9

一般に、これはO/Sに依存しますが、Cの標準では、 'main()'への引数はmain(int argc、char ** argv)または同等のものでなければならないとしていますので、charとwchar_tは同じ基本型、あなたはそれをすることはできません。

あなたは、UTF-8引数の文字列をプログラムに入れて、UTF-16またはUTF-32に変換して、次に生き生きとすることができます。マック(10.5.8、ヒョウ)に

は、私が得た:

すべてUTF-8でエンコードされたのです
Osiris JL: echo "ï€" | odx 
0x0000: C3 AF E2 82 AC 0A         ...... 
0x0006: 
Osiris JL: 

。 (odxは16進ダンプ・プログラムです)。

も参照してください:Why is it that UTF-8 encoding is used when interacting with a UNIX/Linux environment

3

をUnicodeを使用する方法に関する有用な情報を見つけることがないように見える、あなたはUNICODEビルド用wmain()を持つことができ、ありがとうございました。しかし、携帯ではありません。 GCCやUnix/Linuxプラットフォームが何か似たものを提供するのであれば私は気にしません。

9

ポータブルコードではサポートされていません。 Windowsの場合、mainの代わりにwmainを使用できます。この場合、argvはワイド文字として渡されます。

2

はWindowsでは、あなたが_UNICODEシンボルがコンパイル時に定義された、またはメインそうされている場合wmainに変換されますTCHAR.Hと_tmainを使用することができます。 TCHAR * argv []は、同様にunicodeが定義されている場合はWCHAR * argv []に展開され、そうでない場合はchar * argv []に展開されます。

メインメソッドをクロスプラットフォームで使用する場合は、独自のマクロを定義して同じエフェクトにすることができます。

TCHAR.hには、wcharとcharの間の変換用の便利なマクロがいくつか含まれています。次のコードは、C++で簡単にUnicodeの治療のためのプログラムを用意しております、あなたのLinux環境は、UTF-8エンコーディングを使用すると仮定すると

3

int main(int argc, char * argv[]) { 
     std::setlocale(LC_CTYPE, ""); 
     // ... 
    } 

次に、wchar_tの型がそれを意味し、Linuxでは32ビットであります個々のUnicodeコードポイントを保持することができ、C++(文字単位)で古典的な文字列処理に安全にwstring型を使用できます。上記のsetlocale呼び出しを使用すると、wcoutに挿入すると自動的に出力がUTF-8に変換され、wcinから抽出するとUTF-8入力が自動的にUTF-32(1文字= 1コードポイント)に変換されます。残っている唯一の問題は、argv [i]文字列がまだUTF-8でエンコードされていることです。

次の関数を使用して、UTF-8をUTF-32にデコードすることができます。入力文字列が破損していると、UTF-8の規則が破られた場所まで正しく変換された文字が返されます。より多くのエラー報告が必要な場合は、改善することができます。

#define ARR_LEN(x) (sizeof(x)/sizeof(x[0])) 

    wstring Convert(const char * s) { 
     typedef unsigned char byte; 
     struct Level { 
      byte Head, Data, Null; 
      Level(byte h, byte d) { 
       Head = h; // the head shifted to the right 
       Data = d; // number of data bits 
       Null = h << d; // encoded byte with zero data bits 
      } 
      bool encoded(byte b) { return b>>Data == Head; } 
     }; // struct Level 
     Level lev[] = { 
      Level(2, 6), 
      Level(6, 5), 
      Level(14, 4), 
      Level(30, 3), 
      Level(62, 2), 
      Level(126, 1) 
     }; 

     wchar_t wc = 0; 
     const char * p = s; 
     wstring result; 
     while (*p != 0) { 
      byte b = *p++; 
      if (b>>7 == 0) { // deal with ASCII 
       wc = b; 
       result.push_back(wc); 
       continue; 
      } // ASCII 
      bool found = false; 
      for (int i = 1; i < ARR_LEN(lev); ++i) { 
       if (lev[i].encoded(b)) { 
        wc = b^lev[i].Null; // remove the head 
        wc <<= lev[0].Data * i; 
        for (int j = i; j > 0; --j) { // trailing bytes 
         if (*p == 0) return result; // unexpected 
         b = *p++; 
         if (!lev[0].encoded(b)) // encoding corrupted 
          return result; 
         wchar_t tmp = b^lev[0].Null; 
         wc |= tmp << lev[0].Data*(j-1); 
        } // trailing bytes 
        result.push_back(wc); 
        found = true; 
        break; 
       } // lev[i] 
      } // for lev 
      if (!found) return result; // encoding incorrect 
     } // while 
     return result; 
    } // wstring Convert 
6

Windowsでは、アプリがUnicode用にコンパイルされていない場合でも、ARGVスタイルにwchar_t[]配列を生成するためにGetCommandLineW()CommandLineToArgvW()を使用することができます。しかし、argvのデータの一つが安全に正しいUTF-8であると仮定することができます。