Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 20.08.2016, 18:48   #1
Shouldercannon
Участник клуба Подтвердите свой е-майл
 
Аватар для Shouldercannon
 
Регистрация: 26.01.2008
Сообщений: 1,893
Вопрос Собираем URL

Есть функция, которая собирает URL перебирая все символы в строке
Код:
function GetUrl(txt: String): String;
var
  I: Integer;
  Passed: Boolean;
begin
  Result := '';

  for I := 1 to Length(txt) do
  begin
    Passed := False;
    if not Passed then if ((Ord(txt[I]) >= 33) and (Ord(txt[I]) <= 47)) then Passed := True; // ! - /
    if not Passed then if ((Ord(txt[I]) >= 58) and (Ord(txt[I]) <= 64)) then Passed := True; // : - @
    if not Passed then if ((Ord(txt[I]) >= 91) and (Ord(txt[I]) <= 96)) then Passed := True; // [ - `
    if not Passed then if ((Ord(txt[I]) >= 123) and (Ord(txt[I]) <= 126)) then Passed := True; // { - ~
    if not Passed then if ((Ord(txt[I]) >= 48) and (Ord(txt[I]) <= 57)) then Passed := True; // 0 - 9
    if not Passed then if ((Ord(txt[I]) >= 65) and (Ord(txt[I]) <= 90)) then Passed := True; // A - Z
    if not Passed then if ((Ord(txt[I]) >= 97) and (Ord(txt[I]) <= 122)) then Passed := True; // a - z
    if not Passed then if ((Ord(txt[I]) >= 192) and (Ord(txt[I]) <= 223)) then Passed := True; // А - Я
    if not Passed then if ((Ord(txt[I]) >= 224) and (Ord(txt[I]) <= 255)) then Passed := True; // а - я
    if Passed then Result := Result + txt[I] else Break;
  end;
end;
Так как это делается в Delphi XE10, то сразу возникает проблема с кириллицей. В данном случае символы кодировки ASCII от а до я (224 - 255) и от А до Я (192 - 223) не совпадают. От а до я (1072 - 1103) и от А до Я (1040 - 1071). ё - 1105 и Ё - 1025. Как поправить функцию, чтобы Delphi получал Ord кириллицы по таблице

Это просто пример, который работает верно, но как его применить к функции?
Код:
procedure TForm5.Button1Click(Sender: TObject);
var
  A: AnsiChar;
begin
  A := 'а';
  ShowMessage('а = ' + IntToStr(Ord(A)));
end;

Последний раз редактировалось Shouldercannon; 20.08.2016 в 18:51.
Shouldercannon вне форума Ответить с цитированием
Старый 20.08.2016, 19:24   #2
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

замените свои магические цифра на коды символа:
33=Ord('!')
и тп
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 20.08.2016, 19:50   #3
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 19,042
По умолчанию

Не считая магических цифирей всю ту конструкцию можно заменить одной командой:
Код:
  Passed:=((Ord(txt[I]) >= 33) and (Ord(txt[I]) <= 47)) or
          ((Ord(txt[I]) >= 58) and (Ord(txt[I]) <= 64)) or
          ((Ord(txt[I]) >= 91) and (Ord(txt[I]) <= 96)) or
          ((Ord(txt[I]) >= 123) and (Ord(txt[I]) <= 126)) or и т.д.
или IN использовать вместо двух сравнений. И Ord(txt[I]) вычислить только один раз. И вообще можно без ord обойтись
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию

Последний раз редактировалось Аватар; 20.08.2016 в 19:54.
Аватар вне форума Ответить с цитированием
Старый 20.08.2016, 20:38   #4
Shouldercannon
Участник клуба Подтвердите свой е-майл
 
Аватар для Shouldercannon
 
Регистрация: 26.01.2008
Сообщений: 1,893
По умолчанию

Цитата:
Сообщение от Аватар Посмотреть сообщение
Не считая магических цифирей всю ту конструкцию можно заменить одной командой:
Код:
  Passed:=((Ord(txt[I]) >= 33) and (Ord(txt[I]) <= 47)) or
          ((Ord(txt[I]) >= 58) and (Ord(txt[I]) <= 64)) or
          ((Ord(txt[I]) >= 91) and (Ord(txt[I]) <= 96)) or
          ((Ord(txt[I]) >= 123) and (Ord(txt[I]) <= 126)) or и т.д.
или IN использовать вместо двух сравнений. И Ord(txt[I]) вычислить только один раз. И вообще можно без ord обойтись
Можете набросать часть варианта без Ord?
Shouldercannon вне форума Ответить с цитированием
Старый 20.08.2016, 21:04   #5
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 19,042
По умолчанию

txt[I] in ['a'..'z','0','>']
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию

Последний раз редактировалось Аватар; 20.08.2016 в 21:08.
Аватар вне форума Ответить с цитированием
Старый 20.08.2016, 22:28   #6
Shouldercannon
Участник клуба Подтвердите свой е-майл
 
Аватар для Shouldercannon
 
Регистрация: 26.01.2008
Сообщений: 1,893
По умолчанию

Код:
function GetUrl(txt: String): String;
var
  I: Integer;
  Passed: Boolean;
begin
  Result := '';

  for I := 1 to Length(txt) do
  begin
    Passed := False;
    if not Passed then if (AnsiChar(txt[I]) in ['!', '"', '#', '$', '%', '&', '''', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', ']', '^', '_', '`', '{', '|', '}', '~']) then Passed := True;
    if not Passed then if (AnsiChar(txt[I]) in ['0'..'9', 'a'..'z', 'A'..'Z', 'а'..'я', 'А'..'Я']) then Passed := True;
    if Passed then Result := Result + txt[I] else Break;
  end;
end;

procedure TForm5.Button1Click(Sender: TObject);
var
  s: String;
begin
//  s := 'ya.ru';
//  s := 'abcdefghijklmnopqrstuvwxyz';
//  s := 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
//  s := 'абвгдеёжзийклмнопрстуфхцчшщъыьэюя';
//  s := 'АБВГДЕЁЗЖИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ';
//  s := '0123456789';
  Edit2.Text := GetUrl(Edit1.Text);
  Self.Caption := IntToStr(Length(Edit2.Text));
end;
Сначала была проблема с буквой ё, всё что после неё просто отрезалось. Добавил эту букву и всё стало норм, но потом убрал и опять всё норм. Но теперь кириллица в верхнем регистре выводится на половину - СТУФХЦЧШЩЪЫЬЭЮЯ. Если есть любая буква кириллицы в верхнем регистре перед С, то в поле ничего не выведется, при этом кириллица в нижнем регистре и всё остальное не мешают выводу.
Shouldercannon вне форума Ответить с цитированием
Старый 20.08.2016, 23:08   #7
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 19,042
По умолчанию

WideCharToMultiByte
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 21.08.2016, 00:55   #8
northener
ПШП
Участник клуба
 
Регистрация: 15.07.2013
Сообщений: 1,859
По умолчанию

Цитата:
Сообщение от Аватар Посмотреть сообщение
txt[I] in ['a'..'z','0','>']
Какой in в юникодной версии Дельфи для национальных кодировок?
northener вне форума Ответить с цитированием
Старый 21.08.2016, 07:46   #9
Shouldercannon
Участник клуба Подтвердите свой е-майл
 
Аватар для Shouldercannon
 
Регистрация: 26.01.2008
Сообщений: 1,893
По умолчанию

Цитата:
Сообщение от northener Посмотреть сообщение
Какой in в юникодной версии Дельфи для национальных кодировок?
Какие будут предложения?
Shouldercannon вне форума Ответить с цитированием
Старый 21.08.2016, 09:18   #10
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию

Код:
const
 PS:WideChar=#$2029;
 LS:WideChar=#$2028;
 TB:WideChar=#09;
 NL:String=#13#10;
...
  
function IsAlfa(const ch:WideChar):Boolean;
begin
Result:=(('А'<=Ch) and (CH<='Я') ) or (Ch='Ё') or
        (('а'<=Ch) and (CH<='я') ) or (Ch='ё') or
        (('A'<=Ch) and (CH<='Z') ) or
        (('a'<=Ch) and (CH<='z') );
end;

function isUpAlfa(const ch:WideChar):Boolean;
begin
Result:=(('А'<=Ch) and (CH<='Я') ) or (Ch='Ё') or
        (('A'<=Ch) and (CH<='Z') );
end;


function IsWordAlfa(const ch:WideChar):Boolean;
begin
Result:=IsAlfa(ch);
result:=Result or ('_'=Ch) or ('-'=Ch) or ('¬'=Ch);
end;

function IsNumber(const ch:WideChar):Boolean;
begin
Result:=CharInSet(Ch, ['0'..'9']);
end;

function IsNewLineChar(const ch:WideChar):Boolean;
begin
Result:=CharInSet(Ch, [#10, #13]);
Result:= Result or (Ch=LS) or (Ch=PS);
end;

function IsSpace(const ch:WideChar):Boolean;
begin
Result:=CharInSet(Ch, [#9, #10, #11, #12, #13, #32]);
Result:= Result or IsNewLineChar(ch);
end;

function IsPunctuation(const ch:WideChar):Boolean;
begin
Result:=CharInSet(Ch, ['!', '"', '#', '$', '%', '&', '''', '(', ')', '*',
                       '+', ',', '-', '.', '/', ':', ';', '<', '=', '>',
                       '?', '@', '[', '\', ']', '^', '`', '{', '|', '}',
                       '~']);

end;

function IsOther(ch:WideChar):Boolean;
begin
Result:=Not (IsNumber(ch) or IsWordAlfa(ch) or IsSpace(ch) or IsPunctuation(ch));
end;

function IsUri_gen_delims(ch:WideChar):Boolean;
begin
Result:=CharInSet(Ch, [':', '/', '?', '#', '[', ']', '@']);
end;

function IsUri_sub_delims(ch:WideChar):Boolean;
begin
Result:=CharInSet(Ch, ['!', '$', '''', '(', ')', '*', '+', ',', ';', '=']);
end;

function IsUri_reserved(ch:WideChar):Boolean;
begin
Result:=IsUri_gen_delims(ch) or IsUri_sub_delims(ch);
end;

function IsUri_unreserved(ch:WideChar):Boolean;
begin
Result:=IsAlfa(Ch) or IsNumber(Ch);
Result:=Result or CharInSet(Ch, ['-', '.', '_', '~']);
end;

function IsUriChar(ch:WideChar):Boolean;
begin
Result:=IsUri_unreserved(Ch) or
        CharInSet(Ch,['%', ';', '?', ':', '@', '&', '=', '+', '$', ',', '/']);
end;
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .
Pavia вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Собираем глюки MS Word Вождь Microsoft Office Word 21 12.02.2019 20:15
Собираем компьютер за 30 минут mihali4 Компьютерное железо 24 08.04.2009 19:11