Помощь - Поиск - Пользователи - Календарь
Полная версия: Кольцевой список и простые числа
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
Buch
Не знаю как лучше, создать отдельную тему или написать в эту....
Отдельную тему я бы назвал "Кольцевой список и простые числа"
Есть задачка на динамическую память... Необходимо составить программу, которая каждый элемент кольцевого однонаправленного списка с заглавным элементом увеличивает на 3, а затем вычеркивает те из них, которые будут простыми.
Так вот проблема в поиске простых чисел (удаление пока не трогаю, хотя оно тоже криво работает, выдает ошибку "ссылка на не существующий указатель). До 14и она работает нормально, а с 15и начинается дребедень:
1. 15 - простое, дальше правильно, 21 - опять считает простым, потом 25, потом 35, дальше не проверял...
2. Если в списке присутствует 1 (кроме случая, когда она последняя), то система проверки на простые числа вообще не работает.
Вот код:

program kos;

{$APPTYPE CONSOLE}

uses
SysUtils;

Type pe=^el; {Указатель на элемент списковой структуры}
el=record {Элемент списка}
inf:integer; {Информационное поле типа integer}
next:pe {Указатель на следующий элемент}
end;


//функция вывода на экран списка P
function vivod(p:pe):boolean;
var lastp:pe;
begin
lastp := p^.next;
while lastp <> p do
begin
Write(lastp^.inf, ' ');
lastp := lastp^.next;
end;
WriteLn(' ]');
vivod := true;
end;


Var
temp, lastp, p: pe;
i, n, k: integer;



Begin

//контроль значения количества элементов
{$I-}
Write('Vvedite kolichestvo elementov: ');
ReadLn(n);
Writeln;
while (n<=0) or (ioresult<>0) do
begin
Writeln('Kolichestvo elementov dolgno bit` celim CHISLOM, HE men`she i HE ravno `0` ');
Write('Vvedite kolichestvo elementov: ');
ReadLn(n);
Writeln;
end;
{$I+}

//построения КОС с включенным заглавным элементом
Writeln('Vvedite ', n, ' celih chisel!');
new(p);
p^.next:=p;
lastp:=p;
For i:=1 to n do
begin
new(lastp^.next);
lastp:=lastp^.next;
Write('Vvedite ',i,' element spiska: ');
ReadLn(lastp^.inf);
end;
lastp^.next:=p;


//вывод списка P на экран
Write('Spiska P = [ ');
vivod(p);


//удаление элементов, являющихся простыми числами
lastp := p^.next;
while lastp <> p do
begin
if (lastp^.inf=2) or (lastp^.inf=3) then
begin
writeln('prostie (2 ili 3) - ', lastp^.inf);
{ temp := lastp^.next;
dispose(lastp);
lastp := temp;
break; //удаление тоже криво работает }
end
else
if lastp^.inf<2 then
begin
break;
end
else
for k:=2 to trunc(sqrt(lastp^.inf)) do
if lastp^.inf mod k = 0 then
begin
break;
end
else
begin
writeln('prostie - ', lastp^.inf);
{ temp := lastp^.next;
dispose(lastp);
lastp := temp;
break; //удаление тоже криво работает }
break;
end;
lastp := lastp^.next;
end;


Write('It`s FINISH');
readln

end.


Подскажите плиз, в чем ошибка!? unsure.gif
arhimag
15 - простое я всегда думал что 15= 3 * 5
volvo
Ты бы читал повнимательнее (а не просто SPAM-mode включал dry.gif ), тогда бы увидел, что:
Цитата
Так вот проблема в поиске простых чисел (удаление пока не трогаю, хотя оно тоже криво работает, выдает ошибку "ссылка на не существующий указатель). До 14и она работает нормально, а с 15и начинается дребедень:
1. 15 - простое
, дальше правильно, 21 - опять считает простым, потом 25, потом 35, дальше не проверял...
volvo
Bush, проблема у тебя - вот в этом цикле:

for k:=2 to trunc(sqrt(lastp^.inf)) do
if lastp^.inf mod k = 0 then
begin
break;
end
else ... { <--- Вот тут !!! }

Смотри, что происходит: Как только число НЕ 2 и НЕ 3, и оно НЕ делится нацело на 2, срабвтывает отмеченная мной ветка Else, гда и печатается, что число - простое... Я бы переделал весь цикл While вот так:

  lastp := p^.next;
while lastp <> p do begin

if (lastp^.inf=2) or (lastp^.inf=3) then begin
writeln('prostie (2 ili 3) - ', lastp^.inf);
{
temp := lastp^.next;
dispose(lastp);
lastp := temp;
break;
}
end
else
if lastp^.inf<2 then begin
break;
end

else begin
is_simple := true;
for k:=2 to trunc(sqrt(lastp^.inf)) do
if lastp^.inf mod k = 0 then begin
is_simple := false; { <--- Нашел делитель, и выходишь }
break;
end;

{ Если делитель не был найден - то печатать сообщение о простоте числа }
if is_simple then begin
writeln('prostie - ', lastp^.inf);
{
temp := lastp^.next;
dispose(lastp);
lastp := temp;
break;
}
break;
end;
end;
lastp := lastp^.next;
end;
Buch
Спасибо volvo, теперь поиск простых чисел работает, правда если искать по одному... smile.gif
А не посмотришь что не так с проходом по списку... Цифра 1 в начале списка по прежнему все сбивает, да и вааще из всего списка выписывает только первое найденное простое число...)
мисс_граффити
     if is_simple then begin
writeln('prostie - ', lastp^.inf);
break; {как думаешь, какой цикл прерывается?}
volvo
Я бы сделал вот так:
program kos;

uses
SysUtils;

Type
pe=^el;
el = record
inf: integer;
next: pe;
end;

function vivod(p:pe):boolean;
var lastp: pe;
begin
lastp := p^.next;
while lastp <> p do begin
Write(lastp^.inf, ' ');
lastp := lastp^.next;
end;
WriteLn(' ]');
vivod := true;
end;


Var
T, lastp, p, pp: pe;
i, n, k: integer;

is_simple: boolean;

Begin

{$I-}
Write('Vvedite kolichestvo elementov: '); ReadLn(n);
Writeln;
while (n<=0) or (ioresult<>0) do begin
Writeln('Kolichestvo elementov dolgno bit` celim CHISLOM, HE men`she i HE ravno `0` ');
Write('Vvedite kolichestvo elementov: ');
ReadLn(n);
Writeln;
end;
{$I+}

Writeln('Vvedite ', n, ' celih chisel!');
new(p);
p^.next:=p;
lastp:=p;

For i:=1 to n do begin
new(lastp^.next);
lastp:=lastp^.next;
Write('Vvedite ',i,' element spiska: ');
ReadLn(lastp^.inf);
end;
lastp^.next:=p;


Write('start list: [ '); vivod(p);


{ inc every, 3 }
lastp := p^.next;
while lastp <> p do begin
inc(lastp^.inf, 3);
lastp := lastp^.next;
end;

write('after inc: ['); vivod(p);

lastp := p^.next;
while lastp <> p do begin

if (lastp^.inf > 0) and (lastp^.inf <= 3) then begin

if lastp^.inf > 1 then begin
writeln('prostie (2 ili 3) - ', lastp^.inf);
is_simple := true;
end;

end
else begin

is_simple := true;
for k:=2 to trunc(sqrt(lastp^.inf)) do
if lastp^.inf mod k = 0 then begin
is_simple := false;
break;
end;

if is_simple then begin
writeln('prostie - ', lastp^.inf);
end;

end;

if is_simple then begin

T := lastp;
pp := p^.next;
while pp^.next <> T do pp := pp^.next;
pp^.next := T^.next;
lastp := lastp^.next;
dispose(T);
end
else lastp := lastp^.next;

end;

write('finally: ['); vivod(p);

Write('It`s FINISH');
readln

end.

Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.