Проблема с вариантными записями и строками

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Проблема с вариантными записями и строками

Сообщение Jordan » 19.12.2013 09:52:52

Приветствую.

Идея такова, хранить в одной записи, разные записи через вариантную запись в pascal. Вот код.

Код: Выделить всё
{$mode objfpc}{$H+}

program main;

type
  Attr = (Button, CheckBox);
 
type
  PButton = ^TButton;
  TButton = record
    Id    : integer;
    PosX  : integer;
    PosY  : integer;
    SizeX : integer;
    SizeY : integer;
    Name  : string;
  end;

type
  PCheckBox = ^TCheckBox;
  TCheckBox = record
    Id    : integer;
    PosX  : integer;
    PosY  : integer;
    SizeX : integer;
    SizeY : integer;
    Stat  : boolean;
    Name  : string;
  end;

type
  PWidget = ^TWidget;
  TWidget = record
    Next: PWidget;
      case Tag: Attr of
        Button  : (Button :TButton);
        CheckBox: (CheckBox :TCheckBox);
    end;
var
  Table: PWidget;
  Ids: integer;
  i  : PWidget;
 
function ButtonCreate(Name: string): integer;
var
  P: PWidget;
begin
  New(P);
  P^.Tag := Button;
  Inc(Ids);
 
  P^.Button.Id := Ids;
  P^.Button.Name := Name;
 
  P^.Next := Table;
  Table := P;
 
  ButtonCreate := P^.Button.Id;
end;

function CheckBoxCreate(Name: string): integer;
var
  P: PWidget;
begin
  New(P);
  P^.Tag := CheckBox;
  Inc(Ids);

  P^.CheckBox.Id := Ids;
  P^.CheckBox.Name := Name;

  P^.Next := Table;
  Table := P;

  CheckBoxCreate := P^.CheckBox.Id;
end;


begin
  Ids := -1;


ButtonCreate('1');
CheckBoxCreate('2');
  i := table;
 
  while (i <> NIL) do
  begin
    if (i^.Tag = Button) then
    begin
      writeLn(i^.Button.Name);
    end;
   
    if (i^.Tag = CheckBox) then
    begin
      writeLn(i^.CheckBox.Name);
    end;

    i := I^.Next;
  end;


end.


Всё работает за исключение динамических строк. Если вписать директиву {$H+}
Компилятор выдаёт ошибку

Error: Data types which require initialization/finalization can'
t be used in variant records

Не хотелось бы отказываться от строк длиннее 255.

Добавлено спустя 58 минут 19 секунд:
Заменил string на PString

Код: Выделить всё
{$mode objfpc}{$H+}

program main;

type
  Attr = (Button, CheckBox);
 
type
  PButton = ^TButton;
  TButton = record
    Id    : integer;
    PosX  : integer;
    PosY  : integer;
    SizeX : integer;
    SizeY : integer;
    Name  : pstring;
  end;

type
  PCheckBox = ^TCheckBox;
  TCheckBox = record
    Id    : integer;
    PosX  : integer;
    PosY  : integer;
    SizeX : integer;
    SizeY : integer;
    Stat  : boolean;
    Name  : pstring;
  end;

type
  PWidget = ^TWidget;
  TWidget = record
    Next: PWidget;
      case Tag: Attr of
        Button  : (Button :TButton);
        CheckBox: (CheckBox :TCheckBox);
    end;
var
  Table: PWidget;
  Ids: integer;
  i  : PWidget;
 
function ButtonCreate(Name: string): integer;
var
  P: PWidget;
begin
  New(P);
  P^.Tag := Button;
  Inc(Ids);
 
  P^.Button.Id := Ids;
  P^.Button.Name := Pstring(Name);
 
  P^.Next := Table;
  Table := P;
 
  ButtonCreate := P^.Button.Id;
end;

function CheckBoxCreate(Name: string): integer;
var
  P: PWidget;
begin
  New(P);
  P^.Tag := CheckBox;
  Inc(Ids);

  P^.CheckBox.Id := Ids;
  P^.CheckBox.Name := Pstring(Name);

  P^.Next := Table;
  Table := P;

  CheckBoxCreate := P^.CheckBox.Id;
end;


begin
  Ids := -1;


ButtonCreate('1');
CheckBoxCreate('2');
  i := table;
 
  while (i <> NIL) do
  begin
    if (i^.Tag = Button) then
    begin
      writeLn(i^.Button.Name);
      writeLn(i^.Button.id);
    end;
   
    if (i^.Tag = CheckBox) then
    begin
      writeLn(i^.CheckBox.Name);
      writeLn(i^.CheckBox.id);
    end;

    i := I^.Next;
  end;


end.


теперь проблемы с writeln

Error: Can't read or write variables of this type

Ошибка: не удается прочитать или записать переменные этого типа

Объясните в чём проблема.
Jordan
новенький
 
Сообщения: 13
Зарегистрирован: 19.12.2013 09:44:54

Re: Проблема с вариантными записями и строками

Сообщение Лекс Айрин » 19.12.2013 11:01:54

Jordan писал(а):Заменил string на PString


PString это же указатель на String... попробуй воспользоваться оператором взятия значения т.е.
Код: Выделить всё
writeLn(i^.Button.Name);
превратится в
Код: Выделить всё
writeLn(i^.Button.@Name);
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: Проблема с вариантными записями и строками

Сообщение Jordan » 19.12.2013 11:05:04

Эпопея завершена. :)

Для writeln нужно приводить в string

writeLn(string(i^.Button.Name));
writeLn(string(i^.CheckBox.Name));

Теперь всё робит.

Добавлено спустя 1 минуту 3 секунды:
Лекс Айрин писал(а):
Jordan писал(а):Заменил string на PString


PString это же указатель на String... попробуй воспользоваться оператором взятия значения т.е.
Код: Выделить всё
writeLn(i^.Button.Name);
превратится в
Код: Выделить всё
writeLn(i^.Button.@Name);


Выдаёт синтаксическую ошибку. Работает через приведение к string
Jordan
новенький
 
Сообщения: 13
Зарегистрирован: 19.12.2013 09:44:54

Re: Проблема с вариантными записями и строками

Сообщение VirtUX » 19.12.2013 11:06:41

В виде костыля:
Используйте PString. В записи храните адрес по типу integer (или int64 для x64).
Код: Выделить всё
...
type
anyRecord: record
...
{$IFDEF cpu64}
anyString: int64;
{$ELSE}
anyString: integer;
{$ENDIF}
...
end;
...
var
  s: PString;
  ar: ^anyRecord;
...
s := PString(ar^.anyString);
...
Аватара пользователя
VirtUX
энтузиаст
 
Сообщения: 880
Зарегистрирован: 05.02.2008 10:52:19
Откуда: Крым, Алушта


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 6

Рейтинг@Mail.ru