Можно ли использовать Unicode «argv»?

Я пишу небольшую оболочку для приложения, которое использует файлы в качестве аргументов.

Оболочка должна быть в Unicode, поэтому яЯ использую wchar_t для символов и строк, которые у меня есть. Теперь я нахожусь в проблеме, мне нужно иметь аргументы программы в массиве wchar_t 's и в строке wchar_t.

Является ли это возможным? Я'м, определяющийmain функционировать как

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

Должен ли я использовать wchar_t 'с?argv

Большое спасибо, я не вижу полезной информации о том, как правильно использовать Unicode в C.

Ответы на вопрос(6)

GetCommandLineW() а такжеCommandLineToArgvW() производить в стиле argvwchar_t[] массив, даже если приложение не скомпилировано для Unicode.

которые будут превращены в wmain, если символ _UNICODE определен во время компиляции, или main в противном случае. TCHAR * argv [] также будет расширен до WCHAR * argv [], если определен юникод, и char * argv [], если нет.

Если вы хотите, чтобы ваш основной метод работал кроссплатформенно, вы можете определить свои собственные макросы с таким же эффектом.

TCHAR.h содержит несколько удобных макросов для преобразования между wchar и char.

Решение Вопроса

но стандарт C говорит, что аргументыглавный()' должно быть 'main (int argc, char ** argv) ' или эквивалентный, поэтому если char и wchar_t не имеют одинаковый базовый тип, вы можете 'не делай этого.

Сказав это, вы можете получить в программу строки аргументов UTF-8, преобразовать их в UTF-16 или UTF-32, а затем продолжить жизнь.

На Mac (10.5.8, Leopard) я получил:

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

Тот'Все в кодировке UTF-8. (odx - это программа шестнадцатеричного дампа).

Смотрите также:Почему при взаимодействии со средой UNIX / Linux используется кодировка UTF-8?

что ваша среда Linux использует кодировку UTF-8, следующий код подготовит вашу программу к простой обработке Unicode в C ++:

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

Далее, тип wchar_t является 32-битным в Linux, что означает, что он может содержать отдельные кодовые точки Unicode, и вы можете безопасно использовать тип wstring для классической обработки строк в C ++ (символ за символом). При вызове setlocale, приведенном выше, вставка в wcout автоматически переведет ваш вывод в UTF-8, а извлечение из wcin автоматически переведет ввод UTF-8 в UTF-32 (1 символ = 1 кодовая точка). Единственная проблема, которая остается, состоит в том, что строки argv [i] все еще в кодировке UTF-8.

Вы можете использовать следующую функцию для декодирования UTF-8 в UTF-32. Если входная строка повреждена, она будет возвращать правильно преобразованные символы до тех пор, пока не будут нарушены правила UTF-8. Вы можете улучшить его, если вам нужно больше отчетов об ошибках. Но для данных argv можно смело предположить, что это правильный 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

ает использованиеwmain вместоmain, в этом случае argv передается как широкие символы.

wmain() для UNICODE строит. Не портативный хотя. Я не знаю, если платформы GCC или Unix / Linux предоставляют что-то подобное.

Ваш ответ на вопрос