![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Проверить ASCII строку [D7, XP]
writebuf(nil); © (2007-08-31 17:10:00)Как проверить ansi-строку на предмет того что она состоит только из символов ASCII, а не является юникодовой, UTF8?
Единственная моя идея - это в цикле проверять:
for i := 0 to Len(str) do
if Ord(str[i]) > $7F then notascii
Но это мне кажется моя ересь. Что-то есть нормальное?
Sha (2007-09-03 21:01:00) [1]Ну и, наконец, размер цикла можно уменьшить до 18 байт,
если перед ним маску поместить в переменную:
m:=$80808080;
Sha (2007-09-03 20:44:00) [2]Кстати, тут почти даром дается развертывание цикла,
в итоге обрабатываем по 8 символов за один проход цикла
function IsAsciiString(const s: string): boolean;
var
p: pIntegerArray;
q: pWordArray;
label
NotASCII;
begin;
p:=pointer(s);
if p<>nil then begin;
q:=@pchar(p)[-SizeOf(integer)]; //Pointer to string length
inc(pchar(q),(pInteger(q)^-1) and -2); //Pointer to the last word - 4
if (q[2] and $8080)<>0 then goto NotASCII; //Test the last word
if (pinteger(q)^ and $80808080)<>0 then goto NotASCII; //Test the previous dword
while pchar(p)<pchar(q) do begin;
if (p[0] and $80808080)<>0 then goto NotASCII; //Test the first dword
if (p[1] and $80808080)<>0 then goto NotASCII; //Test the second dword
inc(pchar(p),2*SizeOf(integer)); //Pointer to the next pair of dwords
end;
end;
Result:=true;
exit;
NotASCII:
Result:=false;
end;
Anatoly Podgoretsky (2007-09-03 19:31:00) [3]> Sha (03.09.2007 18:04:13) [13]
А мне телепатировал, что US
Sha (2007-09-03 19:00:00) [4]> Anatoly Podgoretsky © (03.09.07 18:00) [12]
> ... я понимаю, что это как направление.
тогда как-то так :)
function IsAsciiString(const s: string): boolean;
var
p, q: pchar;
label
NotASCII;
begin;
p:=pointer(s);
if p<>nil then begin;
q:=@p[-SizeOf(integer)]; //Pointer to string length
q:=q+((pInteger(q)^+ (SizeOf(integer)-1)) and -2); //Pointer to the last word
if (pWord(q)^ and $8080)<>0 then goto NotASCII; //Test the last waord
if p<>q then repeat;
if (pInteger(p)^ and $80808080)<>0 then goto NotASCII; //Test current dword
p:=p+SizeOf(integer); //Pointer to the next dword
until p>=q;
end;
Result:=true;
exit;
NotASCII:
Result:=false;
end;
procedure TForm1.Button2Click(Sender: TObject);
const
Captions: array[boolean] of string= ('false', 'true');
begin;
Label1.Caption:=Captions[IsAsciiString(Edit1.Text)];
end;
Sha (2007-09-03 18:04:00) [5]> Anatoly Podgoretsky ©
> Теперь я понял, что ты имел ввиду, ну написал бы 'z'
> А то глаз зацепился за рускую букву
Русская, потому что мне автор телепатировал,
что по умолчанию он собирался сделать результат ASCII )
Anatoly Podgoretsky (2007-09-03 18:00:00) [6]Ну это не единственная проблема, но я понимаю, что это как направление.
Теперь я понял, что ты имел ввиду, ну написал бы 'z'
А то глаз зацепился за рускую букву
Sha (2007-09-03 17:52:00) [7]> Anatoly Podgoretsky ©
> Что смущает...
смущает то,
что в [5]-[6] цикл проверки не выполнится ни разу,
и результат функции останется неопределенным.
Anatoly Podgoretsky (2007-09-03 17:44:00) [8]
> А как быть со строкой 'я' ?
Что смущает, код равен FF или для OEM другой, но все равно выше 7F
Автор сделал уточнение
АП> ASCII какой, us или extended?
>
>
> US
Anatoly Podgoretsky (2007-09-03 17:42:00) [9]Ну то что неверно, это мягко сказано
ANSI никак не может быть ни юникодом, ни UTF8, иначе это не ANSI или ASCII
umbra (2007-09-03 17:30:00) [10]
> Как проверить ansi-строку на предмет того что она состоит
> только из символов ASCII, а не является юникодовой, UTF8?
>
по-моему, вопрос поставлен неверно. Содержимое некоего буфера (строки) нельзя интрепретировать, не зная, что туда попало. UTF-8 и Unicode Определеяются по BOM, но опять таки, ВОМ стоит в началефайла, а не буфера. В общем, задача в такой постановке, по-моему, неразрешима.
Sha (2007-09-03 17:15:00) [11]> Slym ©
А как быть со строкой 'я' ?
Slym (2007-09-03 14:24:00) [12]if (p^ and $80808080)<>0 then notascii
Slym (2007-09-03 14:23:00) [13]для быстроты (оптимизация) можно по 4 байта проверять
var p:PInteger;
begin
p:=pointer(PChar(str));
for i := 0 to Len(str) div 4 do
begin
if (p^ and $80)<>0 then notascii
inc(p)
end;
Anatoly Podgoretsky (2007-08-31 19:05:00) [14]> writebuf(nil); (31.08.2007 18:47:03) [3]
Тогда в него входят символы с кодами 32-127, плюс некоторое неодназначное подмножество из 0-31
Если подмножество не волнует, тогда можешь считать, что если встретился символ с кодом более $7F это уже не ASCII
writebuf(nil); (2007-08-31 18:47:00) [15]
> ASCII какой, us или extended?
US
Anatoly Podgoretsky (2007-08-31 18:43:00) [16]> writebuf(nil); (31.08.2007 17:10:00) [0]
ASCII какой, us или extended?
Reindeer Moss Eater (2007-08-31 17:18:00) [17]Проверить то, что строка состоит только из какого-то множества символов - это значит убедиться, что в ней нет ни одного другого символа.
поэтому это не ересь:
Единственная моя идея - это в цикле проверять: