Сравнение строк
От: edvin  
Дата: 24.10.02 09:04
Оценка:
Здравствуйте!
Есть следующий код, подключен Unicode:


FILE *file;
FILE *file1;
#define BUF_SIZE 1024
WCHAR buf[BUF_SIZE];
char* file_name = "C:\\WINNT\\sclog\\login.txt";
char* file_name1 = "C:\\WINNT\\sclog\\admin.txt";
char buf1[6];
char buf2[6]="admini";
file = fopen( file_name, "r" );         
fwscanf( file, L"%s", buf);
fclose( file );

file1 = fopen( file_name1, "r" );         
fscanf( file1, "%s", buf1); 
fclose( file1 );
if (buf1==buf2)
{
    SetDlgItemTextW(hDlg, IDD_DOMAIN, buf);
}
else
{
    SetDlgItemTextW(hDlg, IDD_USER_NAME, buf);
}


По идее должно срабатывать прямое условие, потому что в файле admin.txt
прписана строка admini, но все время срабатывает обратное условие.
В чем тут дело
Re: Сравнение строк
От: __Nicolay Россия  
Дата: 24.10.02 09:19
Оценка:
Здравствуйте edvin, Вы писали:

E>По идее должно срабатывать прямое условие, потому что в файле admin.txt

E>прписана строка admini, но все время срабатывает обратное условие.
E>В чем тут дело

В данном случае сравниваются указатели на первый элемент массива, они всегда различны,
используй strcmp, wstrcmp
Re: Сравнение строк
От: unintruder  
Дата: 24.10.02 09:19
Оценка: 3 (1)
Здравствуйте edvin, Вы писали:

E>Здравствуйте!

E>Есть следующий код, подключен Unicode:

E>char buf1[6];

E>char buf2[6]="admini";

E>if (buf1==buf2)

E>{
E>}
E>else
E>{
E>}
E>[/code]

E>В чем тут дело


Дело в том что это указатели и сравнивать их нужно например так

if(StrCmp(buf1,buf2)!=0)
Re: Сравнение строк
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 24.10.02 09:26
Оценка:
Здравствуйте edvin, Вы писали:

E>Здравствуйте!

E>Есть следующий код, подключен Unicode:

E>

E>
E>if (buf1==buf2)
E>


готовься, за такое сравнение строк будут больно и долго пинать
Re: Сравнение строк
От: Bell Россия  
Дата: 24.10.02 09:27
Оценка:
Здравствуйте edvin, Вы писали:

...

Во-первых строка
char buf2[6]="admini";

содержит ошибку: размер массива меньше требуемого (на что ксати VC60SP5 справедливо заявляет "error C2117: 'admini' : array bounds overflow")

Во-вторых, как уже справедливо заметили выше, для сравнения строк надо использовать соответствующие функции (ту же wstrcmp)
Любите книгу — источник знаний (с) М.Горький
Re[2]: Сравнение строк
От: edvin  
Дата: 24.10.02 09:56
Оценка:
Здравствуйте Odi$$ey, Вы писали:

O$>Здравствуйте edvin, Вы писали:

E>>Здравствуйте!

E>>Есть следующий код, подключен Unicode:

E>>

E>>
E>>if (buf1==buf2)
E>>


O$>готовься, за такое сравнение строк будут больно и долго пинать
Дас со строками в С++ у меня вечная головная боль а еще плюс Unicode.
К сожалению не встречал исчерпывающей документации по строкам
Re[3]: use <string> :)) (-)
От: jazzer Россия Skype: enerjazzer
Дата: 24.10.02 10:14
Оценка:
Здравствуйте edvin, Вы писали:

E>Здравствуйте Odi$$ey, Вы писали:


O$>>Здравствуйте edvin, Вы писали:

E>>>Здравствуйте!

E>>>Есть следующий код, подключен Unicode:

E>>>

E>>>
E>>>if (buf1==buf2)
E>>>


O$>>готовься, за такое сравнение строк будут больно и долго пинать :))
E>Дас со строками в С++ у меня вечная головная боль а еще плюс Unicode.
E>К сожалению не встречал исчерпывающей документации по строкам

не будет голова болеть :)
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: Сравнение строк
От: Кодт Россия  
Дата: 24.10.02 12:06
Оценка:
Здравствуйте edvin, Вы писали:

<skipped>

Сравнивать юникодные и ансишные строки — удовольствие вдвойне.

0) сравнивать надо не адреса буферов, а содержание (ну, об этом ты уже узнал)

1) WCHAR не адекватен char — поэтому нужно побиться. Например, так:
int mixcmp(const WCHAR* ws, const char* cs)
{
  while(*ws && *cs)
  {
    WCHAR w = *(ws++);
    unsigned char c = *(cs++); // WCHAR - беззнаковый, char тоже желательно привести
    if(w < u) return -1;
    if(w > u) return  1;
  }
  if(*cs) return -1;
  if(*ws) return  1;
  return 0;
}

либо приводить WCHAR->char, либо char->WCHAR,
либо с самого начала строку-образец делать юникодной:
WCHAR buf2[] = L"admini";


2) юникодные файлы часто предваряются сигнатурой порядка байтов в WCHAR. Это либо FF,FE — Low-Endian (младший байт вперед) — cовместимый с платформой Intel), либо FE,FF — Big Endian (старший байт вперед) — совместимый с платформой DEC.

Поэтому неплохо бы проверить первый символ, считанный из файла, на предмет сигнатуры.
Если равен WCHAR(0xFEFF) — то это low-endian, и дальше все хорошо.
Если равен WCHAR(0xFFFE) — то big-endian, придется повозиться либо с конверсией в low-endian (переставлять байты местами), либо со сравнением. Впрочем, можно послать на.
Если не равен — считать по умолчанию.
Перекуём баги на фичи!
Re[2]: Сравнение строк
От: Аноним  
Дата: 24.10.02 12:11
Оценка:
Здравствуйте Кодт, Вы писали:

К> WCHAR w = *(ws++);

К> unsigned char c = *(cs++); // WCHAR — беззнаковый, char тоже желательно привести
К> if(w < u) return -1;
К> if(w > u) return 1;

И какую же кодовую таблицу имеете в виду, товарищ?
Re[2]: Сравнение строк
От: __Nicolay Россия  
Дата: 24.10.02 12:24
Оценка:
Здравствуйте Кодт, Вы писали:

Да так, по моему не очень хорошо сравнивать UNICODE и ANSI строки, мне нравится использовать макросы из <atlcov.h>

A2W, W2A, A2T, W2T, ... и тому подобные, они правда выделяют память на стеке, так что не рекомендую их использовать в блоке catch например, а так довольно удобно:


wstrcmp(A2W(ansistr), unicodestr);
Re[3]: Сравнение строк
От: Аноним  
Дата: 24.10.02 12:30
Оценка:
Здравствуйте __Nicolay, Вы писали:

N>A2W, W2A, A2T, W2T, ... и тому подобные, они правда выделяют память на стеке, так что не рекомендую их использовать в блоке catch например, а так довольно удобно:


Есть еще одна известная проблема с ними: использующих их код уязвим, если ему подсунут чрезмерно большую строку (можно элементарно грохнуть программу, переполнив стек!).
Re[4]: Сравнение строк
От: __Nicolay Россия  
Дата: 24.10.02 12:39
Оценка:
Здравствуйте Аноним, Вы писали:

А>Есть еще одна известная проблема с ними: использующих их код уязвим, если ему подсунут чрезмерно большую строку (можно элементарно грохнуть программу, переполнив стек!).


Да, если конвертить строки с ручным выбором кодировки, то похоже только WideCharToMultiByte и MultiByteToWideChar,
или есть еще что-нибудь?
Re[3]: Сравнение строк
От: Кодт Россия  
Дата: 24.10.02 13:20
Оценка:
Здравствуйте Аноним, Вы писали:

А>Здравствуйте Кодт, Вы писали:


К>> WCHAR w = *(ws++);

К>> unsigned char c = *(cs++); // WCHAR — беззнаковый, char тоже желательно привести
К>> if(w < u) return -1;
К>> if(w > u) return 1;

А> И какую же кодовую таблицу имеете в виду, товарищ?


Со всей очевидностью, Win-1252 (Western).

Для задачи сравнения строк сие великого значения не имеет (тем более, если эталонная строка вообще ANSI).
Перекуём баги на фичи!
Re[5]: Сравнение строк
От: Кодт Россия  
Дата: 24.10.02 13:23
Оценка:
Здравствуйте __Nicolay, Вы писали:

N>Да, если конвертить строки с ручным выбором кодировки, то похоже только WideCharToMultiByte и MultiByteToWideChar,

N>или есть еще что-нибудь?

С кодировкой Western (Win-1252) все просто: WCHAR wc = (WCHAR)(unsigned char)(c).
ASCII, будучи подмножеством всех кодировок, в том числе и Western — то же самое.
Перекуём баги на фичи!
Re[6]: Сравнение строк
От: __Nicolay Россия  
Дата: 24.10.02 13:30
Оценка:
Здравствуйте Кодт, Вы писали:

К>С кодировкой Western (Win-1252) все просто: WCHAR wc = (WCHAR)(unsigned char)(c).

К>ASCII, будучи подмножеством всех кодировок, в том числе и Western — то же самое.

Речь идет обо всех остальных кодировках например Win-1251
Re[7]: Сравнение строк
От: Кодт Россия  
Дата: 24.10.02 13:56
Оценка: 4 (1)
Здравствуйте __Nicolay, Вы писали:

N>Речь идет обо всех остальных кодировках например Win-1251

Завести табличку.
WCHAR wc1251[256]; // заполняется 1 раз - неважно, из файла или еще как

void makeTable(UINT cp, WCHAR table[256])
{
  int i;

  for(i = 0; i < 128; i++) table[i] = i;

  for(i = 128; i < 256; i++)
  {
    char cs[2] = { (char)i, 0 };
    MultiByteToWideChar(cp, cs, 1, &table[i], 1, NULL, NULL);
  }
}

int compare(const WCHAR* ws, const char* cs, const WCHAR table[256])
{
  while(*ws && *cs)
  {
    WCHAR w = *ws++;
    WCHAR c = table[(unsigned char)*cs++];
    if(w > c) return  1;
    if(w < c) return -1;
  }
  if(*ws) return  1;
  if(*cs) return -1;
  return 0;
}
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.