0 / 0 / 0
Регистрация: 05.09.2011
Сообщений: 3
1

Создание универсального стека

05.09.2011, 01:14. Показов 1667. Ответов 6
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Прошу помощи в создании универсального стека. Вообще в реализации стека хранящего определенный тип (например : integer, char и т.д.) нет ни каких проблем. Вот пример:
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
type
  pIntStack = ^tIntStack;
 
  tIntStack = record
    value : integer;
    prev  : pIntStack;
  end;
 
function push(top : pIntStack; value : integer) : pIntStack;
var
  ptmp : pIntStack;
begin
  new(ptmp);
  if top = nil then ptmp^.prev := nil
  else ptmp^.prev  := top;
  ptmp^.value := value;
  push := ptmp;
end;
 
function pop(top : pIntStack) : pIntStack;
begin
  pop := top^.prev;
  dispose(top);
end;
А вот с реализацией универсального стека возникают проблемы.

Pascal
1
2
3
4
5
6
pStack = ^tStack;
 
  tStack = record
    addr : pointer;
    prev : pStack;
  end;
Тогда функция push вторым параметром будет принимать адрес.

Pascal
1
function push(top : pStack; addr : pointer) : pStack;
Отсюда вытекает несколько вопросов:

1 Как получит значения по адресу addr?
2 Как выделить необходимое количество памяти для хранения значения находящегося по адресу addr?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
05.09.2011, 01:14
Ответы с готовыми решениями:

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

Создание статического стека с удалением значений равных последнему
Кто-нибудь может помочь посмотреть программу ,нужно что-бы ответ выводил не в leable а в memo , при...

Задан указатель P1 на вершину непустого стека. Создать два новых стека
Добрый вечер, у меня возникла проблемка с такой программкой. Вывести в компонент Label. ...

Стек: Переместить все элементы из первого стека во второй и вывести адрес новой вершины стека
Даны указатели P1 и P2 на вершины двух непустых стеков. Переместить все элементы из первого стека...

6
1904 / 1015 / 123
Регистрация: 08.12.2009
Сообщений: 2,792
Записей в блоге: 2
05.09.2011, 04:47 2
Цитата Сообщение от _Pasha_ Посмотреть сообщение
1. Как получит значения по адресу addr?
Вот так: addr^
Delphi
1
my_value := addr^;
Цитата Сообщение от _Pasha_ Посмотреть сообщение
2 Как выделить необходимое количество памяти для хранения значения находящегося по адресу addr?
Delphi
1
2
3
4
5
6
7
8
9
10
type
  PMyType = ^TMyType;
  TMyType := String;
var
  sss: PMyType;
begin
  New(sss); // выделили память
  sss^ := 'dcdcdc';
  addr := sss;
end;
0
0 / 0 / 0
Регистрация: 05.09.2011
Сообщений: 3
05.09.2011, 06:20  [ТС] 3
Цитата Сообщение от deathNC Посмотреть сообщение
Delphi
1
2
3
4
5
6
7
8
9
10
type
  PMyType = ^TMyType;
  TMyType := String;
var
  sss: PMyType;
begin
  New(sss); // выделили память
  sss^ := 'dcdcdc';
  addr := sss;
end;
Не с этим я полностью согласен, но это код не подойдет для pointer.
Немного пошевелив мозгами у меня вышло вот это:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
type
 
  pStack = ^tStack;
 
  tStack = record
    addr : pointer;
    size : integer;
    prev : pStack;
  end;
 
function push(top : pStack; addr : pointer; size : integer) : pStack;
var
  ptmp : pStack;
begin
  new(ptmp);
  getMem(ptmp^.addr, size);
  move(addr^, ptmp^.addr^, size);
 
  if top = nil then ptmp^.prev := nil
  else ptmp^.prev := top;
  push := ptmp;
end;
 
function pop(top : pStack; size : integer) : pStack;
begin
  freeMem(top^.addr, size);
  pop := top^.prev;
  dispose(top);
end;
С типами integer, char, byte и т.д. работает отлично, но с типом string беда.

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var
  top : pStack;
  s1 : string;
  ps : ^string;
 
begin
  s1 := 'Hello World';
  top := nil;
  top := push(top, @s1, sizeOf(s1) * length(s1));
  WriteLn('s1 = ', s1);
  ps := top^.addr;
  WriteLn('ps^ = ', ps^);
 
  s1 := 'Hello Moto';
  WriteLn('ps^ = ', ps^);
  WriteLn('s1 = ', s1);
  top := pop(top, top^.size);
  readln;
end.
Не понимаю в чем тут дело.
Миниатюры
Создание универсального стека  
0
1904 / 1015 / 123
Регистрация: 08.12.2009
Сообщений: 2,792
Записей в блоге: 2
05.09.2011, 06:34 4
PChar - вот тебе стринг
PWideChar, PAnsiChar...

Добавлено через 6 минут

Не по теме:

Указатель в смысле на стринг...

1
0 / 0 / 0
Регистрация: 05.09.2011
Сообщений: 3
05.09.2011, 06:37  [ТС] 5
Цитата Сообщение от deathNC Посмотреть сообщение
PChar - вот тебе стринг
PWideChar, PAnsiChar...
Спасибо. С этими типами все работает.
Ну, а все таки, что не так с типом string.
0
1904 / 1015 / 123
Регистрация: 08.12.2009
Сообщений: 2,792
Записей в блоге: 2
05.09.2011, 06:39 6
Ну, точно не помню. Я двое суток снова не спамши
Может, потому что стринг не фиксированного размера...
0
13095 / 5876 / 1706
Регистрация: 19.09.2009
Сообщений: 8,808
05.09.2011, 09:02 7
Цитата Сообщение от _Pasha_ Посмотреть сообщение
С типами integer, char, byte и т.д. работает отлично, но с типом string беда.
Да - с типом String и с динамическими массивами и с вариантами (Variant) тот код не будет работать. Потому что String - это динамический тип с механизмом подсчёта ссылок.
Когда мы объявляем строковый тип:
Delphi
1
2
var
  S : String;
то, на самом деле, S - это указатель на первый байт области памяти, начиная с которого расположены текстовые данные. По смещению -4 расположено целое число, показывающее длину строки в виде количества символов. По смещению -8 - целое число, означающее количество ссылок на строку. По смещению -12 - целое число, показывающее сколько байт памяти выделено под все данные строки. - Это число относится уже к механизму менеджера памяти.
Пример, показывающий устройство строк:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
procedure TForm1.Button1Click(Sender: TObject);
var
  P, PSize, PRefCnt, PLen : ^Integer;
  i : Integer;
  Str1 : String;
begin
  SetLength(Str1, 20);
  for i := 1 to Length(Str1) do Str1[i] := '1';
  P := Pointer(Str1);
  PSize := Pointer( Integer(P) - 12 );
  PRefCnt := Pointer( Integer(P) - 8 );
  PLen := Pointer( Integer(P) - 4 );
  ShowMessage(
    'Строка: "' + Str1 + '"' + #10
    + 'Общий объём памяти (байт), выделенной для строки = ' + IntToStr(PSize^) + #10
    + 'Длина (количество символов) без учёта терм. нуля = ' + IntToStr(PLen^) + #10
    + 'Количество ссылок на строку = ' + IntToStr(PRefCnt^) + #10
  );
end;
За количеством ссылок следит менеджер памяти. Как только оказывается, что количество ссылок на строку равно нулю - в этом случае, менеджер памяти удаляет такую строку из памяти. Поэтому, когда выполняется код:
Delphi
1
2
3
function push(top : pStack; addr : pointer; size : integer) : pStack;
...
  move(addr^, ptmp^.addr^, size);
то копируется только указатель на текстовые данные строки, но счётчик ссылок на строку не изменяется. И как только внешняя строковая переменная, на которую ссылается addr, например, обнуляется, то менеджер памяти уменьшает её счётчик ссылок. И если этот счётчик оказывается равным нулю, то эта строка удаляется из памяти. В результате, та копия указателя на строку, которая добавлена в стек, оказывается недействительной. - Т. к., строки уже нет в той области памяти.
2
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
05.09.2011, 09:02
Помогаю со студенческими работами здесь

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

Создание универсального шаблона
Не понимаю програмную реализацию задания. Создайте класс MyClass<T>, содержащий статический...

Создание универсального триггера
Добрый вечер. Есть вопрос по Transact-SQL Итак, есть задание написать триггер на некоторую...

Создание универсального конвертора!!
Здраствуйте все, я разработал конвертер. Но мне нужно ваша помощь!!! ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru