PDA

Показать полную графическую версию : [решено] Pascal от новичка (ошибку не вижу)


lenaustkz84
02-12-2011, 13:13
Здравствуйте!

Я только начала изучать Pascal.
Дело очень интересное:)

Но вот моя задача: Мне нужно составить простую программу
на нахождение максимального и минимального значения
из N введенных чисел.

Вроде бы все сделала правильно. И ошибок компилятор не выдает.
Но работает программа не совсем верно.

Максимальное значение определяет безошибочно.

Но минимальное значение находит верно лишь в том случае,
если число отрицательное.

Допустим из 5 введенных чисел: 1 2 -3 7 5
Программа правильно выдает:
max=7
min=-3

Если ввести числа так: 1 2 3 4 5
То программа работает не правильно:
max=5
min=0

Кстати, условие такое, что нужно использовать
конструкцию repeat...until.

Посмотрите, пожалуйста, мой код, наверное, что-то нужно добавить?

{Программа для определения максимального и минимального значения из N введенных чисел}
program max_i_min_iz_N;

uses crt;

var N,min,max,a,i,m:integer;

BEGIN

clrscr;
repeat
write('Введите любую цифру: '); readln(N); writeln();
write('Введите ',N,' чисел(-а) через пробел: ');

i:=1; max:=0; min:=0; a:=0; m:=0;

repeat
read(a);

if (a>max) then max:=a else max:=max;
if (a<min) then min:=a else min:=min;

i:=i+1; a:=0;
until(i>N);

writeln();
writeln('max=',max);
writeln('min=',min);

writeln();
writeln('Для продолжения программы нажмите цифру 1');
writeln('Для завершения программы нажмите цифру 2');
writeln();
readln(m);
writeln();

until(m=2);
END.

CyberDaemon
02-12-2011, 13:42
Максимальное значение определяет безошибочно. »
А если ввести
-1 -2 -3 -4 -5? ;)
Ошибка тут:
max:=0; min:=0;
С чего бы вдруг максимуму и минимуму быть равным нулю?

Hector
02-12-2011, 13:49
lenaustkz84, ошибка в изначальном присвоении min:=0. у тебя выходит 0 всегда меньше положительного числа, т. е. условие a<min при положительном а никогда не выполнится.

и для решения этой задачи лучше использовать массивы

CyberDaemon
02-12-2011, 14:01
и для решения этой задачи лучше использовать массивы »
Почему?

lenaustkz84
02-12-2011, 14:01
Убрала из кода max:=0; min:=0 » все равно программа работает так же не верно.

А если ввести
-1 -2 -3 -4 -5? »

CyberDaemon, после того, как убарала из кода
max:=0; min:=0;
ввела числа -1 -2 -3 -4 -5.

Тогда получается так:
max=0
min=-5

CyberDaemon
02-12-2011, 14:11
Все верно, простым убиранием обнуления преременных задачу не решить.
Думай, думай!
1) -1 -2 -3 -4
2) 1 2 3 4
3) 1 1 2 2

3) 1 1 1 1
4) -1 -1 -1 -1

максимуму и минимуму сначала нужно присвоить значение первого введенного числа.
А потом уже сравнивать все последующие числа.

Hector
02-12-2011, 14:15
CyberDaemon, imho удобней

lenaustkz84
02-12-2011, 14:20
CyberDaemon, ну вот я так и сделала уже.
Добавила еще две переменных.
Но мне код не совсем нравиться.
Хотелось как-то в одной ячейке записывать и значения сравнивать с max и min.
Не хотелось еще задействовать две штуки дополнительно.
Хотя может и нормальный код...
Я еще мало в этом разбираюсь :)


{Программа для определения максимального и минимального значения
из N введенных чисел}
program max_i_min_iz_N;

uses crt;

var N,min,max,a,b,c,i,m:integer;

BEGIN
clrscr;
repeat
write('Введите любую цифру: '); readln(N); writeln();
write('Введите ',N,' чисел(-а) через пробел: ');
read(a,b);

if (a>b) then
begin max:=a; min:=b; end
else begin max:=b; min:=a; end;

i:=3;

repeat
read(c);

if(c>max) then max:=c else max:=max;
if(c<min) then min:=c else min:=min;

i:=i+1; c:=0;

until(i>N);

writeln();
writeln('max=',max);
writeln('min=',min);
writeln();

writeln('Для продолжения программы нажмите цифру 1');
writeln('Для завершения программы нажмите цифру 2');
writeln();
readln(m);
writeln();

until(m=2);
END.

Новый код работает без ошибок.
С вводом любых значений, и положительных, и отрицательных.

CyberDaemon
02-12-2011, 14:26
Hector, это если с введенными числами ещё что-то надо делать, то да. А если задача просто найти максиминимум - тогда самое простое - это обрабатывать введённое число сразу после ввода и больше его не хранить. А то вдруг с размерностью массива не угадаешь :)

lenaustkz84, маньячно :)
И как отработает прога, если в ответ на
"write('Введите любую цифру: '); readln(N); writeln();"
ввести "1"?

lenaustkz84
02-12-2011, 14:46
Ммм... ёлки-палки... только обрадовалась...
Если ввести 1, то... приходиться ввоить 3 значения, из которых программа без ошибки выбирает min и max.
То есть работает не с одним значением, как это нужно, а с тремя.
Это, наверное, потому что я задала i:=3;
Или нет. Наверное, потому что у меня изначально должно сравниваться 3 переменных, иначе программа не работает.

Кстати, для двойки такая же проблема.
Наверное, я сейчас добавлю отдельные операторы именно для значения 1 и 2.
Только, даже если будет работать, вообще муть какая-то получиться, наверное... :o

CyberDaemon
02-12-2011, 15:00
Именно.

Не надо вводить сначала два числа, а потом еще настойчиво ждать третьего.
Нужно просто после ввода первого из чисел - присвоить его и максимуму и минимуму, т.е. max=min=первое введенное число. Одна дополнительная строчка в первом варианте кода. При первом прогоне цикла инициализировать обе переменные введеным числом.

А еще можно поступить маньячно - какой там предел у типа integer? От -32768 до 32767?
Тогда в первом варианте вместо min:=0; max:=0; пишем max:=-32768; min:=32767 - тоже сработает - ибо любое введенное допустимое для integer число окачется внутри этих пределов :lol:


Наверное, я сейчас добавлю отдельные операторы именно для значения 1 и 2. »
Так и подмывает стереть мое сообщение, чтобы посмотреть, насколько монструозно можно решить задачку. Хотя, в плане обучения программированию - даже монстр полезен. Решено - не сотру, но спрячу :)

lenaustkz84
02-12-2011, 15:23
Вот новый код. Теперь, наверное, точно все работает.
И для двойки. И для единицы.
Вот как бы только написать его по-красивее? :)
А то уж больно он мне не кажется таким, как надо.


{Программа для определения максимального и минимального значения
из N введенных чисел}
program max_i_min_iz_N;

uses crt;

var N,min,max,a,b,c,i,m:integer;

BEGIN
clrscr;
repeat
write('Введите любую цифру: '); readln(N); writeln();
write('Введите ',N,' чисел(-а) через пробел: ');

case N of

1 : begin read(a); max:=a; writeln(); writeln('max=',max); end;

2 : begin read(a,b);
if (a>b) then
begin max:=a; min:=b; end
else begin max:=b; min:=a; end;
writeln();
writeln('max=',max);
writeln('min=',min);
end;

else
begin
read(a,b);

if (a>b) then
begin max:=a; min:=b; end
else begin max:=b; min:=a; end;

i:=3;

repeat
read(c);

if(c>max) then max:=c else max:=max;
if(c<min) then min:=c else min:=min;

i:=i+1; c:=0;
until(i>N);

writeln();
writeln('max=',max);
writeln('min=',min);

end; {end else case}

end; {end case}

writeln();
writeln('Для продолжения программы нажмите цифру 1');
writeln('Для завершения программы нажмите цифру 2');
writeln();
readln(m);
writeln();
until(m=2);
END.

lxa85
02-12-2011, 15:24
lenaustkz84, i:=3;
repeat
read(c);
if(c>max) then max:=c else max:=max;
if(c<min) then min:=c else min:=min;
i:=i+1; c:=0;
until(i>N); »
подожди, а здесь то что выполняется? :) Почему условия выхода из цикла такие странные?
i уже равно 3, хотя цифры вводить мы и не начинали. И как правильно указал CyberDaemon, min, max, еще не определены, а мы уже сравниваем с ними вводимое число.
----
Общая реплика: lenaustkz84, молодец, старайся, думай. :) Такие темы приятно читать и приятно помогать. :)

Все что вверху, уже не в счет!


begin
read(a,b);
if (a>b) then
begin max:=a; min:=b; end
else begin max:=b; min:=a; end;
i:=3;
repeat
read(c);
if(c>max) then max:=c else max:=max;
if(c<min) then min:=c else min:=min;
i:=i+1; c:=0;
until(i>N); »
Это хорошо, только напиши еще проще. У тебя уже изначально известно, что переменных больше двух. Соотв. первый if (a>b) не понятен (как следствие не нужен).
Попробуй переписать с использованием цикла for или чуть-исправить repeat until.

begin
read(c);
max:=c;
min:=c;
i:=1;
repeat
i:=i+1;
read(c);
if(c>max) then max:=c;
if(c<min) then min:=c;
until(i>=N);

lenaustkz84
02-12-2011, 15:25
CyberDaemon, загляну теперь в Ваше решение :)

lxa85, как раз в том отрывке кода уже все работает. Только i:=3; потому что это уже третяя переменная, которую начинает сравнивать программа. А предыдущие две - это были сравнения 1 и 2. Если ставить i:=1; то нужно дописывать еще по два значения. Например, нужно найти max и min из 7 значений. Тогда приходиться вводить не 7, а 9 значений. Чтобы убрать эту ошибку, я присвоила переменной i значение 3. Ну вот, что-то такое постаралась объяснить :)

CyberDaemon, по Вашему объяснению кажется все так просто :)
Как же я сама не догадалась?
Напишу программку заново :)

lxa85, сейчас пишу по новому :) Покажу, что получилось :)

lenaustkz84
03-12-2011, 10:20
CyberDaemon, lxa85, спасибо Вам за советы :)
Вот заново написала код.
Опять не слишком им довольна :not-me:
Но думаю, уже лучше, чем было.
Не нравиться этот i:=2;
Без этого условия приходиться вводить на одно значение больше.
Как, по Вашему мнению, уже лучше?
Или тоже сплошной монстр :)


{Программа для определения максимального и минимального
значения из N введенных чисел}
program max_i_min_iz_N;
uses crt;
var N,min,max,a,i,m:integer;

BEGIN
clrscr;

repeat

i:=2;

write('Введите любую цифру: '); readln(N); writeln();
write('Введите ',N,' чисел(-а) через пробел: ');

read(a);

max:=a;
min:=a;

repeat
read(a);
if(a>max)then max:=a else max:=max;
if(a<min)then min:=a else min:=min;
i:=i+1;
until(i>N);

writeln();
writeln('max=',max);
writeln('min=',min);
writeln();

writeln('Для продолжения программы нажмите цифру 1');
writeln('Для завершения программы нажмите цифру 2'); writeln();
readln(m);
writeln();
until(m=2);
END.

Радует только то, что получилось убрать две лишние переменные b и c, и то, что убрала case.
И то, что программа работает во всех случаях... кроме одного...

Если здесь write('Введите ',N,' чисел(-а) через пробел: '); read(a); ввести значение 1, то программа все равно ждет ввода еще одного значения.

Наверное, потому, что у меня считывание переменной a все таки прописано в программе два раза?

При этом я пробовала оставлять только одно считывание переменной двумя вариантами.

Вариант 1

write('Введите любую цифру: '); readln(N); writeln();
write('Введите ',N,' чисел(-а) через пробел: ');

i:=1;

max:=a;
min:=a;

repeat

read(a);

if(a>max)then max:=a else max:=max;
if(a<min)then min:=a else min:=min;

i:=i+1;

until(i>N);


Вариант 1: Переменной i тогда присваиваю 1 и дополнительного значения вводить не надо, в этом плане цикл работает правильно. Но находит из введенных значений правильно только максимальное число. Минимальному присваивает 0. Интересно то, что, если программу не закрыть, а продолжить дальше, то тогда программа начинает находить минимальное и максимальное число правильно. Но не из только что введенных значений, а из всех значений, которые были введены. Наверное, не понятно объясняю. Лучше картинку покажу :)

http://content.foto.mail.ru/mail/hello_lenka/12/i-19.jpg

Вариант 2

write('Введите любую цифру: '); readln(N); writeln();
write('Введите ',N,' чисел(-а) через пробел: ');

i:=1;
read(a);

max:=a;
min:=a;

repeat

if(a>max)then max:=a else max:=max;
if(a<min)then min:=a else min:=min;

i:=i+1;

until(i>N);


Вариант 2: здесь программа присваивает первое значение и max, и min, и следующие значения не сравнивает. При этом цикл на повторение программы не срабатывает. Программа просто закрывается и все. В приниципе, понятно, почему не сравнивает значения, ведь в следующем цикле учавствует только одно и то же значение переменной а, которое было введено первым. А вот почему тогда программа закрывается сама, не считывая переменную m?

В общем так вот...

lenaustkz84
03-12-2011, 14:59
Вот еще по совету lxa85 попробовала написать код с применением FOR.
Что-то тоже не совсем правильно получается.
Нужно вводить больше значений для сравнения, чем требуется.


{Программа для определения максимального
и минимального значения из N введенных чисел}

program max_i_min_iz_N_for;
uses crt;
var N,min,max,a,i,m:integer;

BEGIN

clrscr;

repeat
write('Введите любую цифру: '); readln(N); writeln();
write('Введите ',N,' чисел(-а) через пробел: ');
read(a);
max:=a;
min:=a;

for i:=1 to N do
begin
readln(a);
if(a>max)then max:=a else max:=max;
if(a<min)then min:=a else min:=min;
end;

writeln();
writeln('max=',max);
writeln('min=',min);
writeln();

writeln('Для продолжения программы нажмите цифру 1');
writeln('Для завершения программы нажмите цифру 2'); writeln();
readln(m);
writeln();

until(m=2);
END.

http://content.foto.mail.ru/mail/hello_lenka/12/i-20.jpg

Я уже достала Вас своими вопросами и кодами, наверное.

Но вообще стукаюсь глазами и не вижу, что делаю не так.

Не сочтите за труд, подскажите, где я ошибаюсь.

lxa85
03-12-2011, 15:42
lenaustkz84, а почему ты от case отказалась? Он был вполне не дурен и к месту.
Пусть код будет чуть длиннее, ничего страшного. В условиях про универсальную формулу ничего не сказано. Докажи пользу от использования case и ты будешь молодец.
Дам тебе еще времени помучиться, а завтра напишу свой вариант решения. :)

P.S.
Защита от дурака: Ты уверена, что тебе введут положительную переменную N ? :modesty:

lenaustkz84
03-12-2011, 20:48
Вот и я думала тоже про отрицательное число N и про ноль.
Но "успокоила" себя тем, что никто и не подумает вводить
такие цифры, ведь логично их не вводить.

Но замечание Ваше учла:)
И согласна. Все таки правильно поставить "защиту от дурака" :)

Сначала хотела с while, но тогда нунжно дважды прописывать
предложение ввода переменной N и ее считывание.
Мне показалось это не удобным.

Вот так было вначале:


write('Введите любое положительное число: '); readln(N); writeln();
while (N<=0) do
begin
write('Введите любое положительное число: '); readln(N); writeln();
end;

Потом решила сделать так:


repeat
write('Введите любое положительное число: '); readln(N); writeln();
until(N>0);

С repeat...until удобно оказалось это сделать. Ничего дважды прописывать не надо.

lxa85, спасибо за совет :)
Посижу еще над программкой, подумаю :)

lxa85
04-12-2011, 21:15
Как и обещал, привожу вариант решения в моей доработке.
Решение разумеется
{Программа для определения максимального
и минимального значения из N введенных чисел}

program max_i_min_iz_N_for;
uses crt;
var N,min,max,a,i:integer;

BEGIN
clrscr;
repeat
write('Введите натурально число N: '); readln(N); writeln();
if N>0 then begin
case N of
1: begin
write('Введите ',N,' чисел(-а) через пробел: ');
read(a);
max:=a;
min:=a;
end; //case 1
2: begin
write('Введите ',N,' чисел(-а) через пробел: ');
read(a);
read(max);
if a<max then min:=a
else begin
min:=max;
max:=a;
end;// if a<max
end;// case 2
else: begin
write('Введите ',N,' чисел(-а) через пробел: ');
read(a);
max:=a;
min:=a;
for i:= 2 to N do begin
read(a)
if a>max then max:=a;
if a<min then min:=a;
end; // for i:= 2 to N
end;// case else
end; //case N of

// вывод результатов
writeln();
writeln('max=',max);
writeln('min=',min);
writeln();

end // if N>0 then
else
begin
write('К сожалению, введеное число ',N,' не является натуральным');
end; // if N>0


writeln('Для продолжения программы введите цифру 1 и нажмите Enter');
writeln('Для завершения программы введите цифру 2 и нажмите Enter');
writeln();
readln(a);
writeln(); // ?
until(a=2);
END.
Компилятора под руками нет, "на глаз" ошибок нет.
P.S. у меня табуляция в notepad++ настроена на 4 пробела, звиняйте за длинные строки

lenaustkz84
07-12-2011, 20:10
lxa85, Благодарю!
Как говориться, сколько людей, столько мнений. Сколько программистов - столько и кодов :)

Конечно, Ваша программа работает на все 100% :)
Понравилось то, что Ваш код мне показался более компактным, чем мой.
Ничего лишнего.
Век живи, век учись :)

По поводу моего окончательного кода, который получился в итоге.

По Вашему примеру убрала лишний цикл repeat...until();
который был предназначен для проверки ввода положительного числа.
Оставила прстую конструкцию if...else. Результат тот же, а лишнего ничего нет.
Как говориться, все гениальное просто :)

Все таки получилось оставить цикл repeat...until();
=> просто условие использования именно этого цикла было у меня в задании.

Получилось сделать красивенько i:=1;
=> мне просто так глаз радует, когда переменная i начинается именно с 1 :)

Получилось убрать двойное считывание переменной a,
т.е. раньше было дважды прописано readln(a); Теперь только один.
Просто это двойное считывание переменной a часто
выдавало не правильные результаты работы программы, что меня дико возмущало :o

Ну и просто убрала то, что и так очевидно. Т.е. сократила

if(a>max)then max:=a else max:=max;
if(a<min)then min:=a else min:=min;
на
if(a>max)then max:=a;
if(a<min)then min:=a;

И еще добавила одно условие во внутреннем цикле repeat...until();

if (i=1) then begin max := a; min := a; end;
В этой строчке я нашла решение многих проблем :)

Вот собственно мой код :)

{Программа для определения максимального и минимального
значения из N введенных чисел}
program max_i_min_iz_N;
uses crt;
var N,min,max,a,i,m:integer;

BEGIN
clrscr;
repeat
write('Введите положительное число: '); readln(N); writeln();
if (N<=0) then
writeln('Число ',N,' не положительное.')

else
begin
write('Введите ',N,' число(-ла,-ел) через пробел: ');
i:=1;

repeat
read(a);
if (i=1) then begin max := a; min := a; end;
if(a>max)then max:=a;
if(a<min)then min:=a;
i:=i+1;
until(i>N);

writeln();
writeln('max=',max);
writeln('min=',min);

end; {end else}

writeln(); writeln('Для продолжения программы нажмите цифру 1');
writeln('Для завершения программы нажмите цифру 2'); writeln();
readln(m); writeln();

until(m=2);
END.

CyberDaemon, Кажется теперь код точно не маньячный :lol:




© OSzone.net 2001-2012