Порівняння рядків - як правильно
Порівняння рядків - як правильно?
Цікавить таке питання - як потрібно правильно порівнювати між собою на рівність рядки string?
Я зазвичай порівнюю по-старому як S1 = S2. іноді привожу до одного регістру через LowerCase.
Але помітив що в ісходнікак VCL рядки часто порівнювати не з =. а з допомогою функцій CompareStr. AnsiCompareStr. AnsiCompareText і подібних.
Так чим же загрожує порівнювання S1 = S2 і як правильно порівнювати рядки?
AnsiCompareStr порівнює з урахуванням локалі. CompareStr може не працювати на національних алфавітах
> Як правильно порівнювати рядки?
S1 = S2
все інше має відношення до порівняння тексту. бо рядок це тип змінної
Якщо тільки на рівність і без урахування тек.локалі, то варіант S1 = S2 цілком достатній.
CompareStr - регістрочувствітельное порівняння на менше / одно / більше без урахування тек.локалі
CompareText - регістроне чутливе порівняння на менше / одно / більше без урахування тек.локалі
AnsiCompareStr - регістрочувствітельное порівняння на менше / одно / більше з урахуванням тек.локалі
AnsiCompareText - регістроне чутливе порівняння на менше / одно / більше з урахуванням тек.локалі.
Що "правильніше" - це вирішувати тобі в кожному конкретному випадку.
"" ABC і "ABC # XA0; "- це різні або однакові рядки?
Тобто якщо мені потрібно порівнювати на посимвольного рівність - то метод S1 = S2 цілком робочий?
І ще збентежило те, що для CompareStr використовується функція, написана на асемблері, але вже для AnsiCompareStr - функція WinAPI.
> Тобто якщо мені потрібно порівнювати на посимвольного рівність
> - то метод S1 = S2 цілком робочий?
а в чому сумніви? звичайно
> І ще збентежило те, що для CompareStr використовується функція,
> Написана на асемблері, але вже для AnsiCompareStr - функція
> WinAPI
а чого ніяковіти? CompareString - вона як раз з урахуванням локалі може порівнювати
Фокуса немає, тут потрібен ще й TRIM крім регістронезавісімого порівняння.
Ось для прикладу шматок коду:
const
# XA0; PARAM_Username = "user_name";
# XA0; PARAM_Password = "password";
function GetParamValue (Params: TStrings; const ParamName: string; Erase: boolean = false): string;
var
# XA0; i: integer;
begin
# XA0; result: = "";
# XA0; for i: = Params.Count -1 downto 0 do
// а можна написати і ось так
// # XA0; if Params.Names [i] = ParamName
# XA0; # XA0; if # XA0; 0 = AnsiCompareText (Params.Names [i], ParamName)
# XA0; # XA0; then begin
# XA0; # XA0; # XA0; result: = Params.ValueFromIndex [i];
# XA0; # XA0; # XA0; if Erase
# XA0; # XA0; # XA0; then Params.Delete (i);
# XA0; # XA0; # XA0; break;
# XA0; # XA0; end;
end;
Розумію тепер - що даремно я втілити AnsiCompareText - досить було і простого порівняння :)
> Досить було і простого порівняння
досить було і Params.IndexOfName)
а нафіга Erase при цьому - я не розумію, функція повинна повертати значення, а видаляти - окрема процедура (якщо так хочеться видалити з параметрів)
Це пов'язано з тим, що функція AnsiPos використовує функції StrPos і CompareString. призначені для роботи з рядками PChar.
Erase при цьому нафіга - для того щоб відокремити оброблені параметри від необроблених. Наприклад потрібно просто дізнатися з параметрів ім'я користувача - для цього досить і Values [ParamName], але іноді ім'я користувача потрібно занести в одне поле - а інші параметри в мемо.
Пам'ять: 0.75 MB
Час: 0.029 c