AnsiPos — Функция Delphi


AnsiPos или Pos не соответствует результату в Delphi

Я не могу понять, почему это произошло. На окнах у меня есть текстовый файл , из которого я прочитал первую строку с текстом ‘[směr:A->B]’ .

Я Термическое мой код с отладчиком. Я использую точки останова , так что я вижу, что результат AnsiPos(line, ‘[sm’) равен 0. Почему? Я suppost получить 1. Но я пытался искать AnsiPos(line, ‘sm’) или просто AnsiPos(line, ‘m’) и по- прежнему не положительный результат. Зачем? Я попытался Pos() тоже. Должен ли я использовать другую функцию? Что я пропустил?

Из System.Pos , говорится , что функции:

Находит подстроку в заданной строке.

Метод Поз возвращает индекс первого вхождения в SubStr Str, начиная поиск по смещению.

Этот метод возвращает нуль, если SubStr не найден или смещения является недействительным (например, если смещение превышает длину строки или меньше, чем 1).

Смещение аргумент является необязательным. Смещение устанавливается в 1 по умолчанию, если значение для смещения не указано, что принимает значение по умолчанию, чтобы начать поиск с самого начала.

В вашем коде, вы перепутали порядок параметров Str и SubStr .

AnsiPos — Функция Delphi

Решил я попробовать FireMonkey (Delphi XE3) и начал писать простенькую программку, столкнулся с такой проблемой, что не понятно почему функция Pos не видит в строке «I» из 1/2 І р.
причем AnsiPos(«1/2 «, Razrad) отрабатывает нормально.
Может кто видит, где я ошибся?
ConvertRazradToStandartFormat(«1/2 І р.»);
ConvertRazradToStandartFormat(«ІІ р. «);

function TRazradSyncGUIForm.ConvertRazradToStandartFormat(
Razrad: string): string;
var
sv: string;
IsJunior: Boolean;
st2: Integer;
begin
sv := «-«;
// Razrad := AnsiUpperCase(Razrad);
st2 := AnsiPos(«I», Razrad);
// Delete(Razrad, AnsiPos(«1/2 «, Razrad), Length(«1/2 «) );
// Delete(Razrad, AnsiPos(«1/2», Razrad), Length(«1/2») );
// Razrad := StringReplace(Razrad, «3», «III», [rfReplaceAll, rfIgnoreCase]);
// Razrad := StringReplace(Razrad, «2», «II», [rfReplaceAll, rfIgnoreCase]);
// Razrad := StringReplace(Razrad, «1», «I», [rfReplaceAll, rfIgnoreCase]);
// IsJunior := (AnsiPos(«юн», Razrad) <> 0) or (AnsiPos(«ю», Razrad) <> 0);
// if IsJunior
// then begin
// if AnsiPos(«III», Razrad) <> 0
// then sv := TEXT_III_JUNIOR
// else if AnsiPos(«II», Razrad) <> 0
// then sv := TEXT_II_JUNIOR
// else if AnsiPos(«I», Razrad) <> 0
// then sv := TEXT_I_JUNIOR;
// end;
// if not IsJunior
// then begin
// if AnsiPos(«III», Razrad) <> 0
// then sv := TEXT_III
// else if (AnsiPos(«II», Razrad) <> 0)
// then sv := TEXT_II
// else if AnsiPos(«I», Razrad) <> 0
// then sv := TEXT_I;
// if AnsiPos(«КМС», Razrad) <> 0
// then sv := TEXT_KMS;
// end;
//
// sv := Trim(sv);
Result := sv;
end;

st2 выдает 0, а вроде как должно 1

В этой строке кириллическая І, а не латинская I.

Операции со строками Delphi

Библиотека языка программирования Delphi включает несколько достаточно полезных процедур и функций, чтобы работать со строками. Какие есть операции со строками Delphi? Подробнее остановимся на каждой из них и приведем их примеры.

Примеры операции со строками Delphi

1) Функция length возвращает длину указанной строки. Данная функция обладает одним параметром, который представляет собой выражение, имеющее строковый тип данных. В качестве значения функции length выступает целое число, обозначающее количество символов, входящих в состав строки.

Примеры

b:=length(‘na beregu’);

В результате выполнения этих инструкций переменная a пример значение 6, а переменная b получит значение 9. 2)

2) Процедура delete. С помощью процедуры delete можно удалить определенную часть строки. Общий вид процедуры delete выглядит следующим образом:

  • строка обозначает переменную или константу с строковым типом данных;
  • n есть номер символа, начиная с которого удаляется заданная подстрока;
  • m представляет собой длину удаляемой впоследствии подстроки.

Пример

При выполнении инструкции

переменная st примет значение-строку ‘Город’. 3)

3) Функция роs. С помощью функции pos возможно определение положения подстроки в указанной строке. Общий вид инструкции функции pos представляется так:

откуда подстрока представляется собой переменную или константу строкового типа, которую необходимо отыскать в строковой переменной или константе строка.

Пример

При выполнении следующей инструкции:

Переменная n примет значение 2. В случае, если строка не содержит искомую подстроку, то функция pos возвращает значение 0. Приведем пример инструкции оператора while, которая позволит удалить начальные пробелы из указанной строки:

Здесь процедура delete(s, 1, 1) удаляет пробелы до тех пор, пока пробел есть начальный символ строки (то есть пока значение функции pos(‘ ‘,s) совпадает с единицей). Проверка условия length(s) > 0 применяется здесь для того, чтобы учесть возможность включения в строку только одних пробелов.

4) Функция copy выделяет фрагмент указанной строки. Общий вид инструкции функции copy представляется следующим образом:

откуда строка обозначает строковое выражение, включающее строку, фрагмент которой необходимо получить; n обозначает номер первого символа, начиная с которого выделяется подстрока; m обозначает длину выделяемой подстроки.

Пример

При выполнении инструкции

town:=copy(s, 7, 12) ;

переменная town примет значение-строку ‘Екатеринбург‘.

AnsiPos или Pos не совпадают с результатом в Delphi [duplicate]

У этого вопроса уже есть ответ:

  • Delphi Pos always returning 0 1 answer
Илон Маск рекомендует:  Что такое код loadmodule

Я не могу понять, почему это происходит. В Windows у меня есть txt-файл, из которого я читаю первую строку с текстом ‘[směr:A->B]’ .

Я использую свой код с отладчиком. Я использую точки останова, поэтому я вижу, что результат AnsiPos(line, ‘[sm’) равен 0. Почему? Я suppost, чтобы получить 1. Но я попытался найти AnsiPos(line, ‘sm’) или просто AnsiPos(line, ‘m’) и все еще не положительный результат. Зачем? Я попробовал Pos() тоже. Должен ли я использовать разные функции? Что я пропустил?

1 ответ

Из System.Pos указано, что функция:

Определяет подстроку в заданной строке.

Метод Pos возвращает индекс первого вхождения Substr в Str, начиная поиск в Offset.

Этот метод возвращает ноль, если Substr не найден или смещение недействительно (например, если смещение превышает длину строки или меньше 1).

Аргумент Offset не является обязательным. Смещение установлено по умолчанию 1, если значение Offset не задано, оно принимает значение по умолчанию, чтобы начать поиск с начала.

В вашем коде вы перепутали порядок параметров Str и SubStr .

AnsiPos Routine

Unit Edit

Description Edit

Definition (Delphi 2009):

Technical Comments Edit

(Known issues / Documentation clarifications / Things to be aware of)

Examples Edit

(Please provide links to articles/source code that show how to use this item.)

See Also Edit

(Please provide links to items specifically related to this item.)

User Comments/Tips Edit

(Please leave your name with your comment.)

О чём не пишут в книгах по Delphi (129 стр.)

Листинг 3.31. Отсутствие побочного изменения переменной S2 при изменении S1

procedure TForm1.Button2Click(Sender: TObject);

В этом случае на экран будет выведено Test, т.е. побочного изменения переменной не произойдёт, хотя переменная S1 по прежнему изменяется в обход стандартных механизмов Delphi.

Вся разница между двумя примерами заключается в том, как получается указатель на строку. В первом примере он является результатом приведения типа строки к PChar , а во втором — операции взятия адреса первого символа строки. По идее, это должно приводить к одинаковому результату, однако компилятор, зная, что указатель получается, возможно, для того, чтобы с его помощью менять содержимое строки, вставляет сюда неявный вызов UniqueString . В результате этого для S1 выделяется в динамической памяти другая область, чем для S2 , и манипуляции с содержимым S1 больше не затрагивают S2 .

Неявный вызов UniqueString при обращении к символу строки по индексу выполняется всегда, когда у компилятора есть основания ожидать изменения строки. Это снижает производительность, т.к. многие вызовы UniqueString оказываются излишними. Например, если выполняется посимвольная модификация строки в цикле, UniqueString будет вызываться на каждой итерации цикла, хотя достаточно одного вызова — перед началом цикла. Поэтому в тех случаях, когда производительность критична, посимвольную модификацию строки лучше выполнять низкоуровневыми методами, обращаясь к символам через указатели и обеспечив уникальность строки самостоятельно. Что же касается скорости получения указателя, то тут наиболее быстрым является приведение переменной типа AnsiString к типу Pointer , т.к. это вообще не приводит к генерации дополнительного кода. Приведение к типу PChar работает медленнее потому, что выполняется неявный вызов функции _LStrToPChar , а получение адреса первого символа снижает производительность из-за неявного вызова UniqueString .

Еще раз напомним, что низкоуровневые операции с указателями небезопасны в том смысле, что компилятор почти не способен указать разработчику на ошибки в коде, если такие будут. Поэтому применять быстрые низкоуровневые средства доступа к отдельным символам строки следует только тогда, когда в этом действительно есть необходимость.

3.3.6. Нулевой символ в середине строки

Хотя символ #0 и добавляется в конец каждой строки AnsiString , он уже не является признаком ее конца, т.к. длина строки хранится отдельно. Это позволяет размещать символы #0 и в середине строки. Но нужно учитывать, что полноценное преобразование такой строки в PChar невозможно — это иллюстрируется примером Zero на компакт-диске (листинг 3.32).

Листинг 3.32. Потеря остатка строки после символа #0

procedure TForm1.Button1Click(Sender: TObject);

S1, S2, S3: string;

В первую метку будет выведено число 9 (длина исходной строки), во вторую — 4. Мы видим, что при копировании одной строки AnsiString в другую символ #0 в середине строки — не помеха (вызов UniqueString добавлен для того, чтобы обеспечить реальное копирование строки, а не только копирование указателя). А вот как только мы превращаем эту строку PChar , информация о ее истинной длине теряется, и при обратном преобразовании компилятор ориентируется на символ #0 , в результате чего строка «обрубается».

Потеря куска строки после символа #0 происходит всегда, когда есть преобразование ShortString или AnsiString в PChar , даже неявное. Например, все API-функции работают с нуль-терминированными строками, а визуальные компоненты — просто обертки над этими функциями, поэтому вывести с их помощью на экран строку, содержащую #0 , целиком невозможно. Но главный «подводный камень», связанный с символом #0 в середине строки, заключается в том, что целый ряд стандартных функций для работы со строками AnsiString на самом деле вызывают API-функции (или даже библиотечные функции Delphi, предназначенные для работы с PChar , что приводит к игнорированию «хвоста» после #0 . Следующий код (листинг 3.33. пример ZeroFind на компакт-диске) иллюстрирует эту проблему.

Листинг 3.33. Некорректная работа функции AnsiPos с символом #0

procedure TForm1.Button1Click(Sender: TObject);

Label1.Caption := IntToStr(AnsiPos(‘Z’, ‘A’#0’Z’));

Хотя символ «Z» присутствует в строке, в которой производится поиск, на экран будет выведен «0», что означает отсутствие искомой подстроки. Это связано с тем, что функция AnsiPos использует функции StrPos и CompareString , предназначенные для работы со строками PChar , поэтому поиск за символом #0 , не производится. Если заменить в этом примере функцию AnsiPos на Pos , которая работает с типом AnsiString должным образом, на экран будет выведено правильное значение «3».

Описанные проблемы заставляют очень осторожно относиться к возможному появлению символа #0 в середине строк AnsiString — это может стать источником неожиданных проблем.

Илон Маск рекомендует:  getimagesize - получает размер изображения

3.3.7. Функция, возвращающая AnsiString

Очень интересный «подводный камень», связанный с типом AnsiString рассмотрен в статье [4]. Проиллюстрируем его следующим кодом (листинг 3.34, пример StringResult на компакт-диске).

AnsiPos — Функция Delphi

559 просмотра

1 ответ

810 Репутация автора

На этот вопрос уже есть ответ здесь:

Я не могу выяснить, почему это произошло. На окнах у меня есть текстовый файл, из которого я читаю первую строку с текстом ‘[směr:A->B]’ .

Я thet мой код с отладчиком. Я использую точки останова, чтобы видеть, что результат AnsiPos(line, ‘[sm’) равен 0. Почему? Я полагаю, чтобы получить 1. Но я пытался искать AnsiPos(line, ‘sm’) или просто AnsiPos(line, ‘m’) и все еще не положительный результат. Зачем? Я Pos() тоже пытался . Должен ли я использовать другую функцию? Что я пропустил?

Ответы (1)

1 плюс

30176 Репутация автора

Из System.Pos указано, что функция:

Находит подстроку в данной строке.

Метод Pos возвращает индекс первого вхождения Substr в Str, начиная поиск со смещения.

Этот метод возвращает ноль, если Substr не найден или смещение недопустимо (например, если смещение превышает длину строки или меньше 1).

Аргумент Offset является необязательным. По умолчанию для параметра «Смещение» установлено значение 1, если значение «Смещение» не задано, для начала поиска требуется значение по умолчанию.

В вашем коде вы перепутали порядок параметров Str и SubStr .

AnsiPos — Функция Delphi

Работа со строками Delphi позволяет извлечь из строки необходимую информацию и представить её в нужном виде. Система предоставляет весь спектр необходимых функций для работы со строками Delphi и преобразования строк Delphi в необходимые форматы:

  • числовой формат, целый и дробный с плавающей точкой;
  • формат времени, даты, даты-времени;
  • преобразование символов к верхнему или нижнему регистру;
  • сравнение строк, поиск в строке и копирование подстроки;
    и многие другие.

Непосредственно сами строки Delphi поддерживают единственную операцию, так называемую операцию конкатенации, то есть присоединения. Несмотря на «научное» название, операция конкатенации выполняет очень простую процедуру. С помощью операции конкатенации одна строка присоединяется к другой:

Результирующая строка S будет суммой двух слагаемых строк. Длина строки, то есть количество символов в строке, возвращается встроенной функцией

function Length(S: String): Integer;

Delphi работает со строками типа String, в котором длина строки записывается в начале строки, перед первым символом. Поэтому индекс первого символа в строке не 0, а 1. То есть, если:

S:=’Строка типа String’;

то S[1] — символ ‘С’, S[2] — символ ‘т’ , последний символ в строке — S[Length(S)], равный ‘g’.

Однако часто приходится иметь дело со строками типа PChar, которые использует операционая система Windows. В строках типа PChar длина строки определяется специальным символом конца строки — #0. Поэтому для использования функций Windows тип String необходимо предварительно переводить в тип PChar. Преобразование типа String в тип PChar выполняет функция

function PChar(S: String): PChar;

Для полноценной работы со строками Delphi используются следующие стандартные процедуры и функции:

Функции преобразования в числовой формат и обратно

Выполняя вычисления, используем для ввода данных и отображения результатов следующие функции, работающие со строками Delphi:

функция IntToStr(N: Integer): String
Преобразует целое число N в строку.
функция StrToInt(S: String): Integer
Преобразует строку S в целое число.
функция FloatToStr(X: Extended): String
Преобразует число с плавающей точкой X в строку.
функция StrToFloat(S: String): Extended
Преобразует строку S в число с плавающей точкой.

Процедуры и функции преобразования дат и времени

Сначала собственно функции, предоставляющие информацию о текущих дате и времени:

функция Now: TDateTime
Возвращает текущую дату и время.
функция Date: TDateTime
Возвращает текущую дату.
функция Time: TDateTime
Возвращает текущее время.

Далее, функции, работающие с составляющими даты и времени (год, месяц, число, день недели, часы, минуты, секунды и даже миллисекунды):

функция DayOfWeek(Date: TDateTime): Integer
Возвращает текущий номер дня недели: 1 — воскресенье, 7 — суббота.
процедура DecodeDate(Date: TDateTime; var Year, Month, Day: Word)
Разбивает дату Date на год — Year, месяц — Month и день — Day.
процедура DecodeTime(Time: TDateTime; var Hour, Min, Sec, MSec: Word)
Разбивает время Time на час — Hour, минуты — Min, секунды — Sec и миллисекунды — MSec.
функция EncodeDate(Year, Month, Day: Word): TDateTime
Объединяет год — Year, месяц — Month и день — Day в значение типа TDateTime.
функция EncodeTime(Hour, Min, Sec, MSec: Word): TDateTime
Объединяет час — Hour, минуты — Min, секунды — Sec и миллисекунды — MSec в значение типа TDateTime.

Наконец, собственно, функции, переводящие дату и время из формата TDateTime в строчный формат:

функция DateTimeToStr(DateTime: TDateTime): String
Преобразует дату и время DateTime в строку.
функция DateToStr(Date: TDateTime): String
Преобразует дату Date в строку.
функция TimeToStr(Time: TDateTime): String
Преобразует время Time в строку.

Следующие функции работают с параметрами возвращаемой строки. Функции с приставкой Ansi работают в том числе и с кириллическими символами. Если символы в строках предполагаются исключительно латинские, то можно использовать аналогичные функции, но без приставки Ansi:

функция AnsiLowerCase(const S: String): String
Возвращает строку S, преобразованную к нижнему регистру.
функция AnsiUpperCase(const S: String): String
Возвращает строку S, преобразованную к верхнему регистру.
функция Length(const S: String): Integer
Возвращает количество символов в строке S.
функция Trim(const S: String): String
Удаляет из строки S начальные и завершающие пробелы и управляющие символы.
функция TrimLeft(const S: String): String
Удаляет из строки S начальные пробелы и управляющие символы.
функция TrimRight(const S: String): String
Удаляет из строки S завершающие пробелы и управляющие символы.

Следующие функции сравнивают две строки между собой:

функция AnsiCompareStr(const S1, S2: String): Integer
Сравнивает две строки S1 и S2 с учётом регистра символов.
Возвращает значение 0 если S1>S2
функция AnsiCompareText(const S1, S2: String): Integer
Сравнивает две строки S1 и S2 без учёта регистра символов.
Возвращает значение 0 если S1>S2

Следующие функции осуществляют поиск в текущей строке подстроки, вставляют, удаляют или заменяют подстроку:

Илон Маск рекомендует:  Работа с сервисами windows nt
функция Pos(Substr: String; Str: String): Integer
Возвращает позицию (индекс) первого вхождения Substr в строке Str. Если Substr нет в Str, возвращает 0.
функция Insert(Source: String; var S: String; Index: Integer): Integer
Вставляет строку Source в строку S, начиная с номера символа, равного Index
процедура Delete(var S: String; Index, Count: Integer)
Удаляет из строки S подстроку, начинающуюся с номера символа, равного Index, и содержащую до Count символов.
функция StringReplace(const S, OldPattern, NewPattern: string; Flags: TReplaceFlags): String
Заменяет в строке S подстроку OldPattern на строку NewPattern с учётом флага TReplaceFlags. Для работы с этой функцией нужно создать переменную типа TReplaceFlags — это множество, и включить в него одно или оба значения из следующих:
rfReplaceAll — будут заменены все вхождения. Если это значение не будет включено во множество, то будет заменено только первое вхождение;
rfIgnoreCase — замена будет без учёта регистра символов. Если это значение не будет включено во множество, то замена будет чувствительна к регистру символов.

Наконец, функция копирования части строки:

функция Copy(S: String; Index, Count: Integer): String
Возвращает подстроку строки S, начиная с номера символа, равного Index и содержащую до Count символов.

Помимо прочего, эту функцию можно использовать для вывода нецелого числа с нужным количеством цифр после запятой. Для этого, сначала получаем строку из числа формата Real, затем находим функцией Pos позицию запятой в этой строке, прибавляем нужное количество и копируем в результат это количество символов. Вот готовая функция:

function RealToStr(X: Real; Count: Integer): String; //Count — количество цифр после запятой
var S: String;
N: Integer;
begin
S:=FloatToStr(X); //после запятой — длинная последовательность цифр
//DecimalSeparator — константа, содержащая истинный разделитель целой и дробной частей числа N:=Pos(DecimalSeparator, S); //позиция запятой в строке
//вычисляем длину строки с нужным количеством знаков после запятой:
if N=0 //если в строке нет запятой — это целое число, и
then N:=Length(S) //тогда просто выводим это число
else N:=N+Count; //иначе вычисляем длину строки
Result:=Copy(S, 1, N); //копируем часть строки в результат
end;

Или вот, к примеру, текст модуля, обеспечивающего ввод в компонент Edit только чисел.

DelphiComponent.ru — бесплатно видеоуроки по Delphi, статьи, исходники

Работа со строками в Delphi

Функция Length языка Delphi

Эта функция возвращает длину строки. У нее есть только один параметр — строка, длину которой надо вернуть. Функция Length выглядит так:

function Length(S): Integer;

Пример использования функции:

В этом примере объявлены две переменные str (строка) и index (целое число). В первой строке кода в переменную str помещается строка «Привет». После этого переменной index присваивается длина строки str. Результат, записанный в пере­менную index, будет равен числу 6 — длина строки.

Функция Сору языка Delphi

Эта функция возвращает указанный отрывок строки. Например, вам нужно по­лучить из строки «Меня зовут Михаил» символы начиная с 5-го по 10-й. Это легко сделать с помощью функции сору. У нее есть три параметра.

  • Строка, из которой нужно получить отрывок текста.
  • Начальный символ.
  • Количество нужных символов.

function Сору(S; Index, Count: Integer): string;

Пример использования функции:

Stri: =’Меня зовут Михаил ‘ ;

Str2:= copy(Stri, 5, 5);

Здесь объявлено две строковых переменных: str1 и str2. В первой строке кода мы присваиваем переменной str1строку «Меня зовут Михаил». В следующей строке происходит копирование в переменную str2 пяти символов из переменной stri, начиная с 5-го символа. Получается, что мы копируем строку с 5-го символа по 10-й. Результатом будет в str2 строка: «зовут».

Функция Delete языка Delphi

Эта функция удаляет кусок текста из указанной строки. У нее есть три параметра.

  • Строка, из которой нужно удалить отрывок текста.
  • Начальный символ, начиная с которого будут удаляться символы.
  • Количество символов для удаления. В общем виде функция выглядит так:

procedure Delete(var S: string; Index, Count:Integer);

Пример использования функции Delete:

Strl:= ‘Меня зовут Михаил’;

В этом примере мы удаляем из строки stri символы, начиная с 5-го по 10-й (пять символов, начиная с 5-й позиции). В результате в переменной str1 останется только строка «Меня Михаил».

Функция Pos языка Delphi

Эта функция ищет указанные символы в строке или, можно сказать, ищет под­строку. Если эти символы найдены, то она вернет порядковый номер, начиная с которого найдена нужная строка. У функции два параметра.

  • Строка, которую надо искать.
  • Строка, в которой надо искать.

Если подстрока не найдена, то функция вернет ноль, function Pos(Substr: string; S: string): Integer; Пример использования функции Pos:

Stri:=’Меня зовут Миша’;

В этом примере мы запускаем поиск строки «Миша» в строке stri. В данном случае строка «Миша» есть в строке переменной и начинается с символа 11. Ре­зультат — в переменной index будет число 11.

Функция Insert языка Delphi

Эта процедура вставляет одну строку в другую, начиная с указанного символа. У нее есть три параметра.

  • Строка, которую надо вставить.
  • Строка, в которую надо вставить.
  • Позиция, куда надо вставить.

В общем виде функция выглядит так:

procedure Insert(Source: string; var S: string; Index: Integer) ;

Пример использования функции insert:

Strl:=’Меня Миша’; Insert(‘зовут’, Strl, б);

Здесь вставляется в строку strl текст «зовут», начиная с 6-го символа. Результа­том будет строка «Меня зовут Миша».

AnsiPos или Pos не соответствуют результату в Delphi

I cannot find out why this happen. On windows I have a txt file from which I read first line with text ‘[směr:A->B]’ .

Я его код с отладчиком. Я использую точки останова, поэтому я вижу, что результат AnsiPos (строка, ‘[sm’) равен 0. Почему? Я suppost, чтобы получить 1. Но я попытался найти AnsiPos (строка, ‘sm’) или просто AnsiPos (строка, ‘m’) и все еще не положительный результат. Зачем? Я попробовал Pos() тоже. Должен ли я использовать разные функции? Что я пропустил?

Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL