Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум «Всё о Паскале» _ Задачи _ Проблемы с динамической памятью

Автор: ninja 13.01.2010 2:14

Добрый вечер, необходимо написать программу, задание слеудющее:

Создать объект «чтение строки» позволяющий считывать строку введенную с клавиатуры. От объекта чтение строки создать дочерний объект «анализ строки», подсчитывающий частоту, с какой символы встречаются во введенной строке и выводящий результат на экран. От объекта «анализ строки» создать дочерний объект «анализ текста», позволяющий считывать текст из файла и анализировать его.

Код программы:


uses crt;
type
tmas=array[1..255] of char;
read_str=object
str:^string;
mas:^tmas;
h:^integer;
flag:^boolean;
constructor init;
procedure chtenie; virtual;
destructor done; virtual;
procedure run; virtual;
end;
analiz_str=object(read_str)
mas_char_1:array ['a'..'z'] of word;
mas_char_2:array ['A'..'Z'] of word;
constructor init;
procedure analiz; virtual;
procedure run; virtual;
destructor done; virtual;
end;
analiz_text=object(analiz_str)

constructor init;
procedure chtenie; virtual;
procedure analiz_txt; virtual;
procedure run; virtual;
destructor done; virtual;
end;
constructor read_str.init;
begin
New(str);
New(mas);
New(flag);
New(h);
end;

destructor read_str.done;
begin
dispose(str);
dispose(mas);
dispose(flag);
dispose(h);
end;

constructor analiz_str.init;
begin
end;

destructor analiz_str.done;
begin
end;

constructor analiz_text.init;
begin
end;

destructor analiz_text.done;
begin
end;

procedure read_str.run;
begin

end;

procedure read_str.chtenie;
var
i:integer;
k:integer;
stroka_b:string;
begin
clrscr;
for i:=1 to 255 do
{read_s^.}mas^[i]:=' ';
writeln('vvedite stroky:');
readln(stroka_b);
{read_s^.}h^:=0;
{read_s^.}h^:=length(stroka_b);
for i:=1 to {read_s^.}h^ do
begin
{read_s^.}mas^[i]:=stroka_b[i];
end;
{read_s^.}str^:=stroka_b;
end;

procedure analiz_str.run;
var
s:char;
begin
{analiz_s^.}flag^:=false;
analiz;
for s:='a' to 'z' do
begin
if {analiz_s^.}mas_char_1[s]<>0 then writeln(s,'-',{analiz_s^.}mas_char_1[s]);
end;
for s:='A' to 'Z' do
begin
if {analiz_s^.}mas_char_2[s]<>0 then writeln(s,'-',{analiz_s^.}mas_char_2[s]);
end;
end;

procedure analiz_str.analiz;
var
s:char;
i,j,k:byte;
begin
if {analiz_s^.}flag^=false then
begin
for s:='a' to 'z' do mas_char_1[s]:=0;
for s:='A' to 'Z' do mas_char_2[s]:=0;
chtenie;
end;
for j:=1 to {read_s^.}h^ do
begin
case {read_s^.}mas^[j] of
'a'..'z':inc({analiz_s^.}mas_char_1[{read_s^.}mas^[j]]);
'A'..'Z':inc({analiz_s^.}mas_char_2[{read_s^.}mas^[j]]);
end;
end;
end;
procedure analiz_text.chtenie;
Var
f:text;
s:char;
ch:string[1];
i,j,k,p,m:byte;
str2:string;
begin
readkey;
clrscr;
{analiz_s^.}flag^:=true;
Assign(f,'file.txt');
Reset(f);
for s:='a' to 'z' do {analiz_s^.}mas_char_1[s]:=0;
for s:='A' to 'Z' do {analiz_s^.}mas_char_2[s]:=0;
i:=1;
j:=1;
k:=1;
{read_s^.}h^:=0;
while not eof (f) do
begin
while not eoln (f) do
begin
{read_s^.}str^:='';
readln(f,{read_s^.}str^);
k:=1;
for i:=1 to length({read_s^.}str^) do
begin
{read_s^.}mas^[i]:={read_s^.}str^[i];
write({read_s^.}mas^[i])
end;
{read_s^.}h^:=length({read_s^.}str^);
analiz_txt;
end;

readln(f);
end;
writeln;
for s:='a' to 'z' do
begin
if {analiz_s^.}mas_char_1[s]<>0 then writeln(s,'-',{analiz_s^.}mas_char_1[s]);
end;
for s:='A' to 'Z' do
begin
if {analiz_s^.}mas_char_2[s]<>0 then writeln(s,'-',{analiz_s^.}mas_char_2[s]);
end;
writeln;
end;

procedure analiz_text.run;
begin
chtenie;
end;

procedure analiz_text.analiz_txt;
begin
analiz;
end;
var
read_s:^read_str;
analiz_s:^analiz_str;
analiz_t:^analiz_text;
begin
new(analiz_s,init);
new(analiz_t,init);
analiz_s^.run;
analiz_t^.run;
dispose(analiz_t,done);
dispose(analiz_s,done);
readkey;
end.


Трудность заключается в следующем: а именно в процедуре read_str.chtenie; в строчке for i:=1 to 255 do {read_s^.}mas^[i]:=' '; мне необходимо обнулить массив который находится в динамической памяти, т.е. я заменяю все символы пробелом.
Если массив расположить в статической памяти, то все работает корректно.
Задание именно на объекты и динамическую память. Также если обращаться к переменным или к объектам через переменные (закоментированнно), то так же все работает корректно, но преподователь сказал что нужно обращаться напрямую <имя объекта>.<имя переменной>

Помогите разобраться с данной проблемой, заранее блаодарен.

Автор: TarasBer 13.01.2010 2:32

В чём проявляется некорректность, что говорит отладка?

Автор: volvo 13.01.2010 2:34

Цитата
Трудность заключается в следующем: а именно в процедуре read_str.chtenie; в строчке for i:=1 to 255 do {read_s^.}mas^[i]:=' '; мне необходимо обнулить массив который находится в динамической памяти, т.е. я заменяю все символы пробелом.
Трудность у тебя в том, что ты перед инициализацией объекта типа analiz_str не инициализируешь его предка:
constructor analiz_str.init;
begin
inherited init; { <--- Вот этого ты не делаешь... }
end;
, отсюда: под поля, описанные в предке, у тебя память НЕ выделена. Вот тебе и сбой в работе программы. То же самое касается и конструктора второго дочернего объекта, и обоих деструкторов (внутри дочернего деструктора надо вызывать деструктор предка)

Автор: ninja 13.01.2010 2:40

ммм.. Спасибо сейчас попробую исправить.

Отладка ничего не говорит, программа просто закрывается когда я ее компилирую.

Автор: volvo 13.01.2010 2:41

Цитата
программа просто закрывается когда я ее компилирую.
Когда компилируешь - нет. А вот когда запускаешь - верю, может и закрыться...

Автор: ninja 13.01.2010 3:21

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

Добавлено через 2 мин.
Еще маленькая просьба, как специалист есть какие-нибудь замечания по организации объектов и работы с ними?

Автор: volvo 13.01.2010 3:54

Не совсем понятна логика, которой ты руководствовался при проектировании иерархии объектов. Что-то ты там все запутал. Можно было бы сделать чуть проще, если убрать Run из наследников, и оставить ее только в базовом классе... И из нее вызывать другие виртуальные функции, возможно - переопределенные в наследниках. Я бы, по крайней мере, делал именно так.

Автор: volvo 13.01.2010 16:40

И еще: у тебя один и тот же код скопирован дважды в разных методах:

  for s:='a' to 'z' do
begin
if {analiz_s^.}mas_char_1[s]<>0 then writeln(s,'-',{analiz_s^.}mas_char_1[s]);
end;
for s:='A' to 'Z' do
begin
if {analiz_s^.}mas_char_2[s]<>0 then writeln(s,'-',{analiz_s^.}mas_char_2[s]);
end;

, и вот это тоже присутствует два раза:
    for s:='a' to 'z' do mas_char_1[s]:=0;
for s:='A' to 'Z' do mas_char_2[s]:=0;
Ты бы выделил эти 2 фрагмента в отдельные методы, и вызывал бы когда нужно. Глядишь, и общая картина прояснилась бы...

Автор: ninja 14.01.2010 3:32

Большое спасибо, исправил