Pascal. Delphi. Реализация строк типа PChar в памяти компьютера. Типы PAnsiChar, PWideChar

Реализация строк типа PChar в памяти компьютера. Типы PAnsiChar, PWideChar. Выделение памяти для строк. Доступ по индексу


Содержание


Поиск на других ресурсах:

1. Представление ASCIIZ-строк в языке Паскаль. Типы PChar, PAnsiChar, PWideChar

Помимо стандартного представления с помощью типа String, в языке Паскаль строки могут быть представлены типами PChar, PANsiChar и PWideChar. Эти типы определяют так называемые ASCIIZ-строки. Каждая ASCIIZ-строка завершается специальным нулевым символом (ноль-терминатором), обозначаемым как ‘\0’ в C-ориентированных языках или #0 в Паскале.

На рисунке 1 отображено представление ASCIIZ-строки в памяти компьютера.

Представление ASCIIZ-строки в памяти компьютераРисунок 1. Представление ASCIIZ-строки в памяти компьютера

Тип PChar описывает указатель на тип Char

type
  PChar = ^Char;

Модификацией типа PChar являются типы PANsiChar и PWideChar, которые являются указателями в соответствии с типами AnsiChar и WideChar. Более подробно о символьных типах в Free Pascal и Delphi описывается здесь.

 

2. Функции для работы с типами PChar, PAnsiChar, PWideChar. Перечень

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

  • StrCat, StrLCat – реализует конкатенацию строк;
  • StrComp, StrIComp, StrLComp, StrLIComp – сравнивают две строки;
  • StrCopy, StrECopy, StrLCopy – копируют значения одной строки в другую;
  • StrDispose – уничтожает строку и память, ранее выделенную для нее;
  • StrEnd – возвращает указатель на символ, завершающий строку;
  • StrLen – возвращает длину строки;
  • StrLower – преобразовывает строку в нижний регистр;
  • StrMove – перемещает одну строку на место другой строки;
  • StrNew – выделяет память для новой строки;
  • StrPas – конвертирует строку типа PChar в строку типа String;
  • StrPCopy – копирует строку типа String в строку типа PChar;
  • StrPos – находит подстроку в строке;
  • StrRScan, StrScan – находит позицию указанного символа в строке;
  • StrUpper – преобразует строку в верхний регистр и возвращает указатель на него.

 

3. Выделение памяти для строк типа PAnsiChar, PWideChar. Функції AnsiStrAlloc, WideStrAlloc

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

function AnsiStrAlloc(Size: Cardinal): PAnsiChar;
function WideStrAlloc(Size: Cardinal): PWideChar;

здесь

  • Size – размер строки в символах. Для строк типа PAnsiChar каждый символ занимает 1 байт. Для строк типа PWideChar каждый символ занимает 2 байта (кодировка Unicode).

Пример.

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

var
  ps1 : PAnsiChar;
  ps2 : PWideChar;
  s : string;

begin
  // Функции AnsiStrAlloc, WideStrAlloc.
  // Демонстрируется ввод строки с клавиатуры консоли
  // и копирование этой строки в типы AnsiStrAlloc, WideStrAlloc

  // 1. Ввести строку типа String с клавиатуры
  Write('s = ');
  Readln(s);

  // 2. Функция AnsiStrAlloc
  // 2.1. Выделить память для строки PANsiChar,
  // размер памяти равен размеру строки s
  ps1 := AnsiStrAlloc(Length(s));

  // 2.2. Скопировать строку s => ps1
  StrPCopy(ps1, s);

  // 2.3. Вывести ps1
  Writeln('ps1 = ', ps1);

  // 3. Функция WideStrAlloc
  // 3.1. Выделить память для строки PWideChar
  ps2 := WideStrAlloc(Length(s));

  // 3.2. Копирование s => ps2
  StrPCopy(ps2, s);

  // 3.3. Вывести ps2
  Writeln('ps2 = ', ps2);

  Readln;
end.

Результат

s = abcdef
ps1 = abcdef
ps2 = abcdef

 

4. Доступ к отдельному символу строки типа PChar, PAnsiChar, PWideChar. Операция доступа по индексу []

Для строк типа PChar, PAnsiChar и PWideChar есть возможность доступа к заданному символу с помощью операции индексирования []. В общем случае доступ к элементу строки выглядит следующим образом:

S[index]

здесь

  • S – строка типа PChar, PAnsiChar, PWideChar;
  • index – позиция символа, которая начинается с 0.

Отдельные символы строк типа PChar, PANsiChar, PWideChar могут изменяться. Это означает, что операция доступа по индексу [] может использоваться как в выражении, так и в левой части оператора присваивания.

Пример.

В примере с помощью доступа по индексу реализуется создание строки типа PAnsiChar и PWideChar.

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

var
  ps1 : PAnsiChar;
  ps2 : PWideChar;
  i : Integer;
  s : string;

begin
  // Доступ по индексу []

  // 1. Создать строку AnsiChar
  // 1.1. Выделить память для строки
  ps1 := AnsiStrAlloc(10);

  // 1.2. Записать слово 'Hello!' в строку ps1
  ps1[0] := 'H';
  ps1[1] := 'e';
  ps1[2] := 'l';
  ps1[3] := 'l';
  ps1[4] := 'o';
  ps1[5] := '!';
  ps1[6] := #0; // символ конца строки

  // 1.3. Вывести строку в цикле
  Write('ps1 = ');
  for i := 0 to StrLen(ps1) do
    Write(ps1[i]);
  Writeln;

  // 2. Создать строку WideChar
  // 2.1. Выделить память для строки
  ps2 := WideStrAlloc(15);

  // 2.2. Записать слово 'BestProg' в строку ps2
  ps2[0] := 'B';
  ps2[1] := 'e';
  ps2[2] := 's';
  ps2[3] := 't';
  ps2[4] := 'P';
  ps2[5] := 'r';
  ps2[6] := 'o';
  ps2[7] := 'g';
  ps2[8] := #0; // конец строки

  // 2.3. Вывести строку
  Writeln('ps2 = ', StrPas(ps2));

  // 2.4. Прибавить к строке '.net'
  ps2[8] := '.';
  ps2[9] := 'n';
  ps2[10] := 'e';
  ps2[11] := 't';
  ps2[12] := #0;

  // 2.5. Изменить 'B'->'b', 'P'->'p'
  ps2[0] := 'b';
  ps2[4] := 'p';

  // 2.6. Вывести ps2 на экран
  Writeln('ps2 = ', StrPas(ps2));

  Readln;
end.

Результат

ps1 = Hello!
ps2 = BestProg
ps2 = bestprog.net

 

5. Функция StrNew и процедура StrDispose. Выделение и освобождение памяти для строк PAnsiChar и PWideChar

Для работы со строками типа PChar, PANsiChar и PWideChar обязательными операциями являются выделение и освобождение памяти в динамической области. Для выполнения этих операций используются функции StrNew и StrDispose.

Функция StrNew создает новую строку на основе существующей и содержит следующие объявления для типов PAnsiChar и PWideChar

function StrNew(const Str: PAnsiChar): PAnsiChar;
function StrNew(const Str: PWideChar): PWideChar;

здесь

  • Str – константная строка, для которой выделяется память.

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

procedure StrDispose(Str: PAnsiChar);
procedure StrDispose(Str: PWideChar);

здесь

  • Str – строка, для которой нужно освободить память.

Пример.

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

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

var
  ps1 : PWideChar;
  s : string;

begin
  // Функция StrNew, процедура StrDispose.
  // Демонстрируется выделение памяти для строки,
  // введенной с клавиатуры. Длина строки неизвестна.

  // 1. Создать исходную строку,
  // строка вводится с клавиатуры в консольном приложении
  Write('s = ');
  Readln(s);

  // 2. Конвертировать s => ps1
  // 2.1. Выделить память для строки ps1 функцией StrNew,
  // размер памяти равен длине строки s
  ps1 := StrNew(WideStrAlloc(Length(s)));

  // 2.2. Скопировать строку s => ps1
  StrPCopy(ps1, s);

  // 3. Вывести строку ps1
  Writeln('ps1 = ', StrPas(ps1));

  // 4. Освободить память, выделенную для строки ps1
  StrDispose(ps1);

  Readln;
end.

Пример.

s = BestProg
ps1 = BestProg

 

6. Функции StrPas и StrPCopy. Преобразование из типа String в тип PChar и наоборот

Полезными при использовании строк в программах являются функции взаимного преобразования между форматами представления строк типа String и PChar. Для общего типа String используются его реализации типов AnsiString и UnicodeString, в которых символ занимает соответственно 1 и 2 байта. Для обобщенного типа PChar также существует разновидности, это типы PANsiChar и PWideChar которые учитывают различные системы кодирования, в которых символы занимают соответственно 1 и 2 байта.

Чтобы преобразовать из типов PAnsiChar и PWideChar в тип String, нужно использовать функцию StrPas, которая имеет следующие объявления

function StrPas(const Str: PAnsiChar): AnsiString;
function StrPas(const Str: PWideChar): UnicodeString;

здесь

  • Str – строка, которую нужно преобразовать соответственно в тип AnsiString или UnicodeString.

Для преобразования из типа String в типы PANsiChar и PWideChar используется функция StrPCopy. Функция имеет следующие реализации

function StrPCopy(Dest: PAnsiChar; const Source: AnsiString): PAnsiChar;
function StrPCopy(Dest: PWideChar; const Source: UnicodeString): PWideChar;

Пример.

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

var
  ps1 : PAnsiChar;
  ps2 : PWideChar;
  s : string;

begin
  // Функции StrPas та StrPCopy

  // 1. Функции StrPas
  // 1.1. Сформировать строку ps1 типа PAnsiChar
  ps1 := 'PAnsiChar';
  Writeln('ps1 = ', StrPas(ps1));

  // 1.2. Сформировать строку ps2 типа PWideChar
  ps2 := StrNew('PWideChar');
  Writeln('ps2 = ', StrPas(ps2));

  // 1.3. Конвертировать PAnsiChar => String - функция StrPas
  s := StrPas(ps1);
  Writeln('StrPas(ps1) = ', s);

  // 1.4. Конвертировать PWideChar => String
  s := StrPas(ps2);
  Writeln('StrPas(ps2) = ', s);

  // 1.5. Освободить ps2
  StrDispose(ps2);

  // 2. Функция StrPCopy
  // 2.1. Создать строку s
  s := 'String';
  Writeln('s = ', s);

  // 2.2. Выделить фрагмент размером 20 символов для типа PAnsiChar
  ps1 := AnsiStrAlloc(20);

  // 2.3. Скопировать String => PAnsiChar
  StrPCopy(ps1, s);
  Writeln('StrPCopy(s) = ', StrPas(ps1));

  // 2.4. Выделить фрагмент для типа PWideChar
  ps2 := WideStrAlloc(20);

  // 2.5. Скопировать String => PWideChar
  StrPCopy(ps2, s);
  Writeln('StrPCopy(s) = ', StrPas(ps2));

  // 2.6. Освободить память, выделенную для строк ps1, ps2
  StrDispose(ps1);
  StrDispose(ps2);

  Readln;
end.

Результат

ps1 = PAnsiChar
ps2 = PWideChar
StrPas(ps1) = PAnsiChar
StrPas(ps2) = PWideChar
s = String
StrPCopy(s) = String
StrPCopy(s) = String

 


Связанные темы