2009-11-03 15 views
11

Ich schreibe einen kleinen Wrapper für eine Anwendung, die Dateien als Argumente verwendet.Ist es möglich, einen Unicode "argv" zu verwenden?

Der Wrapper muss in Unicode sein, daher verwende ich wchar_t für die Zeichen und Zeichenfolgen, die ich habe. Jetzt finde ich mich in einem Problem, ich muss die Argumente des Programms in einem Array von wchar_t und in einer wchar_t Zeichenfolge haben.

Ist es möglich? Ich bin die Definition der main Funktion als

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

Sollte ich wchar_t 's für argv?

Vielen Dank, ich scheine nützliche Informationen nicht zu finden, wie Unicode in C. richtig verwenden

Antwort

9

In der Regel keine. Es hängt vom O/S ab, aber der C-Standard besagt, dass die Argumente für 'main()' 'main (int argc, char ** argv)' oder gleichwertig sein müssen, wenn char und wchar_t nicht vom selben Basistyp sind Du kannst es nicht tun.

Nachdem das gesagt wurde, könnten Sie UTF-8 Argument Strings in das Programm, konvertieren sie in UTF-16 oder UTF-32, und dann weiter mit Leben.

Auf einem Mac (10.5.8, Leopard), ich habe:

Osiris JL: echo "ï€" | odx 
0x0000: C3 AF E2 82 AC 0A         ...... 
0x0006: 
Osiris JL: 

Das ist alles UTF-8 kodiert ist. (odx ist ein Hex-Dump-Programm).

Siehe auch: Why is it that UTF-8 encoding is used when interacting with a UNIX/Linux environment

3

unter Windows wie auch immer, können Sie ein wmain() für UNICODE haben baut. Nicht tragbar. Ich weiß nicht, ob GCC oder Unix/Linux-Plattformen etwas Ähnliches bieten.

9

Portabler Code unterstützt dies nicht. Windows (zum Beispiel) unterstützt die Verwendung von wmain anstelle von main, in welchem ​​Fall argv als breite Zeichen übergeben wird.

2

Unter Windows Sie tchar.h und _tmain verwenden kann, die in wmain gedreht werden, wenn das _UNICODE Symbol bei der Kompilierung definiert ist, oder Haupt anders. TCHAR * argv [] wird in ähnlicher Weise zu WCHAR * argv [] erweitert, wenn Unicode definiert ist, und char * argv [], falls nicht.

Wenn Sie möchten, dass Ihre Hauptmethode plattformübergreifend funktioniert, können Sie Ihre eigenen Makros mit demselben Effekt definieren.

TCHAR.h enthält eine Anzahl von Komfortmakros für die Konvertierung zwischen wchar und char.

3

Unter der Annahme, dass Ihre Linux-Umgebung verwendet UTF-8-Codierung dann der folgende Code Ihr Programm für die einfache Unicode-Behandlung in C++ wird vorbereitet:

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

Als nächstes Wchar_t Typ ist 32-Bit unter Linux, was bedeutet, es kann einzelne Unicode-Codepunkte enthalten, und Sie können den wstring-Typ für die klassische Zeichenfolgenverarbeitung in C++ (Zeichen für Zeichen) verwenden. Mit setlocale call oben wird das Einfügen in wcout automatisch Ihre Ausgabe in UTF-8 übersetzen und das Extrahieren von wcin wird UTF-8-Eingabe automatisch in UTF-32 übersetzen (1 Zeichen = 1 Codepunkt). Das einzige verbleibende Problem besteht darin, dass argv [i] -Strings immer noch UTF-8-codiert sind.

Sie können die folgende Funktion verwenden, um UTF-8 in UTF-32 zu decodieren.Wenn die Eingabezeichenfolge beschädigt ist, werden korrekt konvertierte Zeichen zurückgegeben, bis die UTF-8-Regeln unterbrochen wurden. Sie können es verbessern, wenn Sie mehr Fehlermeldungen benötigen. Aber für argv Daten kann man mit Sicherheit davon ausgehen, dass es richtig UTF-8 ist:

#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

Unter Windows können Sie verwenden GetCommandLineW() und CommandLineToArgvW() Benutzer argv-Stil wchar_t[] Array zu erzeugen, auch wenn die App nicht für Unicode kompiliert .

Verwandte Themen