2012-07-11 1 views
3

У меня возникла небольшая проблема с попыткой реализовать определенное задание, основанное на том, какая строка argv [1] равна.Невозможно сравнить аргументы командной строки Visual C++, wchar_t *?

int _tmain(int argc, _TCHAR* argv[]) //wchar_t 
{ 
    if (argc != 2) 
     exit(1); 

    if (argv[1] == L"-foo") 
     printf("Success!\n"); 

    wprintf(argv[1]); 
    printf("\n"); 

    system("pause"); 
    return 0; 
} 

Если я запустить исполняемый файл с аргументом "-foo", я получаю следующий результат:

-foo 

Оно должно быть:

Success! 
-foo 

Строка в точности, как я хотите, чтобы это было, но if-condition остается ложным. Строки wchar_t просто не сопоставимы с использованием оператора ==? Если да, то как мне их правильно сравнивать?

+0

1. Строки нельзя сравнивать таким образом. 2. См. Это: http://www.codeproject.com/Articles/76252/What-are-TCHAR-WCHAR-LPSTR-LPWSTR-LPCTSTR-etc – Ajay

ответ

4

Предварительное замечание: Unicode и символов Unicode в этом ответе, учитывая контекст самого вопроса, относится к UCS-2 (до XP) и UTF-16 (начиная с XP), которые взаимозаменяемы с широким символом, wchar_t, WCHAR и другими терминами в контексте Win32 API. Стандарты Unicode предлагают несколько кодировок, таких как UTF-8, UTF-16 и UTF-32 для кодирования одинакового количества символов - разные воплощения стандарта имеют разную область. Суррогатные коды используются для выхода из базовой многоязычной плоскости (BMP), примерно первых 64K кодовых точек, и, следовательно, кодируют более, чем могут быть закодированы с 16-битными символами и одним символом для кодовой точки. Суррогатные расширения были разработаны для стандарта Unicode 2.0, который был принят в течение года, когда был выпущен NT 4.0, но в некоторые годы после была выпущена первая версия Unicode для Windows, NT 3.51. Это первоначальный стандарт не учитывает больше символов, чем в BMP и поэтому Unicode символов или широкий характер даже сейчас используется синоним Unicode в контексте API Win32, хотя это неточно.

Чтобы ответить на вопрос, который вы основной поднятую:

ли wchar_t строки просто не сравнимы с использованием "==" оператор?

Нет, они не являются ни строками, ни ANSI, то есть в качестве основы используется тип char. Помните, что строка C (как wchar_t, так и char) является указателем. Это означает, что с == вы сравнивали два значения указателя, которые были определенно не равны. В конце концов, это буквальная строка (т. Е. Внутри вашего образа программы), а другая - где-то в куче. Таким образом, они определенно являются двумя разными сущностями.

Если вы хотите использовать == вам придется использовать язык, такие как C++ с STL класса std::string (или std::basic_string<_TCHAR>) или (в Windows) в АТЛ класса CString (или скорее CStringT). Эти классы иногда называются классами умных строк и используют средство C++ для переопределения operator==(). Однако вы должны иметь в виду, что семантика отличается в зависимости от реализации, поэтому не каждый класс умной строки будет сравнивать содержимое строки. Некоторые могут просто сравнить равенство this (т. Е. Это один и тот же экземпляр), в то время как другие могут сравнивать содержимое строки, нечувствительное к регистру или чувствительное к регистру по своему усмотрению.

Для сравнения строк C у вас есть следующие функции, доступные для вашего сценария использования:

  • Для "ANSI" символы (char) строк: strcmp, _stricmp (и "подсчитанная" варианта: _strncmp, _strnicmp ... есть больше)
  • Для символов Unicode (wchar_t) строк: wcscmp, _wcsicmp (и "насчитали" варианты: _wcsncmp, _wcsnicmp ... есть больше)
  • Для переменного символа "типа" (TCHAR) строк: _tcscmp, _tcsicmp (и "учтенных" вариантов: _tcsncmp, _tcsnicmp ... есть больше)

Вы можете запомнить эти префиксы:

  • str -> строка
  • wcs -> широкий символьная строка
  • tcs - строка> T символов

Примечание стороны: с #include <tchar.h> и windows.h макросы TEXT и _T эквивалентна и используются, чтобы объявить строковый литерал, который будет либо «ANSI» или Unicode в зависимости от определяю, в наращивании времени. То же самое справедливо и для _TCHAR и TCHAR, в то время как последнее, по-видимому, выступает в контексте Win32 API.

Таким образом, сборка Unicode расширит _T("something") до L"something", в то время как сборка «ANSI» расширит ее до "something".

Как TCHAR, рассмотрим чтение через аргументы, изложенные в: Is TCHAR still relevant? (указал rubenvb) Есть действительные пункты за и против TCHAR/_TCHAR использования, и вы должны принять решение и придерживаться его - т.е. быть последовательным.

+0

'wchar_t' не Unicode, несмотря на то, что MS хочет, чтобы вы считали. – rubenvb

+0

@ rubenvb: Я не знаю, что вы даже пытаетесь сказать с этим утверждением или как это оправдывает нисходящее движение, но что бы то ни было. «Юникод» и термин «символ Юникода», несмотря на то, что * другие * хотят, чтобы вы верили, в контексте Win32 API ссылаются на широкие символы, и там, в частности, на разновидности 'wchar_t' (определяемые компилятором) и' WCHAR' (заголовок определенный). Тот факт, что используемая кодировка для Unicode здесь UTF-16 и используется для UCS-2, больше, чем большинство людей хотят знать или знать, и, кроме того, это не имеет отношения к этому ответу. – 0xC0000022L

+0

Unicode имеет несколько кодировок, и я это очень хорошо знаю. Существует только одна кодировка, нейтральная по Endianess (UTF-8), существует более старая кодировка (и подмножество UTF-16) под названием UCS-2, которая первоначально использовалась Microsoft, начиная с Windows NT, с использованием 16-битного символьного типа (ограниченный BMP). Начиная с XP они перешли на UTF-16. В отличие от UTF-16 UCS-2 не было кодовых точек, которые позволяли вам кодировать больше, чем первые 64K символов (BMP). UTF-16 и UTF-32, с другой стороны, имеют кодовые точки, подобные UTF-8, чтобы допускать больше символов, чем может предложить BMP. – 0xC0000022L

0

Невнимательно, понял.

if (wcscmp(argv[1], L"-foo") == 0) 
+0

На самом деле ваше решение было неправильным, оно должно быть '_tcscmp() 'вместо' wcscmp', так как вы используете '_TCHAR'. Исправлено это. – 0xC0000022L

+0

@ Hans Passant: можете ли вы объяснить, почему вы отменили мои изменения?Мне действительно любопытно, потому что я думаю, что это очень * плохая привычка * иметь '_tmain' и все остальное, установленное для условной компиляции как ANSI vs. Unicode, а затем вставлять ** Unicode или ANSI-специфический код ** как это сделал ОП. Поэтому, пожалуйста, мне любопытно, что такое обоснование, учитывая контекст вопроса (использование '_tmain' и' _TCHAR'). Благодарю. – 0xC0000022L

+2

@ 0xc0 - TCHAR является архаичным, нет текущей версии Windows, которая не является Unicode по своему ядру. _tmain производится по шаблону проекта. –