Помощь - Поиск - Пользователи - Календарь
Полная версия: Задача Паскаль АБС
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
liverpool85
Здравствуйте! Напишите программу, выводящую все трехзначные номера (от 001 до
999), сумма цифр которых равна N (значение N вводит пользователь).

Мой код-
var i,a,b,c,w:integer;
n,p:string;
begin
writeln('Vvedite chislo ot 0 do 999: ');
readln(n);
begin
for i:=1 to 999 do
a:=i div 100;
b:=i div 10 mod 10;
c:=i mod 10;
w:=a+b+c;
p:=IntToStr(w);
if p=n then writeln(p,' ');
end;
end.


И еще один -
uses crt;
var n,i,a,b,c,w,k:integer;
s:string;
begin
write('Сумма цифр n=');
readln(n);
writeln('Номера с суммой цифр, равной ',n);
k:=0;
for i:=1 to 999 do
begin
a:=i div 100;
b:=i div 10 mod 10;
c:=i mod 10;
w:=a+b+c;
if w=n then
begin
k:=1;
str(i,s);//чтобы на всех Паскалях шло
//s:=IntToStr(i); //для АВС
if i<10 then s:='00'+s
else if i in [10..99] then s:='0'+s;
write(s:4);
end;
end;
if k=0 then write('Таких номеров нет')
end.


Почему то не выводит все номера)))
IUnknown
Во-первых, не надо вводить число от 0 до 999 (я о первой программе, если что). Максимальная сумма цифр = 27, вот и вводи число 0 .. 27.

Второе: зачем ты ввод пользователя воспринимаешь как строку? Вводишь число - так опиши n как Integer, тут же избавишься от необходимости преобразовывать постоянно Integer -> String (или обратно) для сравнения.

Третье - у тебя не в том месте стоит begin. Надо поменять 6 и 7 строки местами.

Ну, и четвертое - не то печатаешь. Надо напечатать число, а не сумму цифр, сумма тебе и так известна, ты ж ее сам и вводил.

Итого:
var
i, a, b, c, w: integer;
n: integer;
begin
writeln('Vvedite chislo ot 0 do 27: ');
readln(n);

for i:=1 to 999 do
begin
a:=i div 100;
b:=i div 10 mod 10;
c:=i mod 10;
w:=a+b+c;
if n=w then writeln(i,' ');
end;
end.
Это если не менять алгоритм решения, а править только реализацию.
liverpool85
good.gif Спасибо тебе огромное! Задачи делал сегодня ночью (около 4-х утра)), намутил сам не разберу че)) Теперь все как по нотам!))
liverpool85
Упс, а нужно выводить не 1,2,3 а 001,002,003!!!
IUnknown
Цитата
//чтобы на всех Паскалях шло
- проще всего сделать так:
      if n=w then
begin
if a = 0 then write(0); // Первая цифра - 0? Выводим этот 0...
if (a + b = 0) then write(0); // Первая И ВТОРАЯ - нули: добавляем еще один 0
writeln(i,' '); // А потом уже выводим само число...
end;
liverpool85
var
k, n, i, a, b, c, w: integer;
s: string;
begin
writeln('Vvedite chislo ot 0 do 27: ');
readln(n);

for i:=1 to 999 do
begin
a:=i div 100;
b:=i div 10 mod 10;
c:=i mod 10;
w:=a+b+c;
if n=w then
begin
k:=1;
str(i,s);
if i<10 then s:='00'+s
else if i in [10..99] then s:='0'+s;
writeln(s:4,' ');
end;
end;
if k=0 then write ('Takih nomerov net');
end.



Теги ставь, пожалуйста
Lapp
Lapp
Цитата(IUnknown @ 8.09.2011 12:45) *
- проще всего сделать так:
      if n=w then
begin
if a = 0 then write(0); // Первая цифра - 0? Выводим этот 0...
if (a + b = 0) then write(0); // Первая И ВТОРАЯ - нули: добавляем еще один 0
writeln(i,' '); // А потом уже выводим само число...
end;

IUnknown, что-то это не похоже на тебя.. Не выспался? ))
Почему не так:
      WriteLn(a,b,c);
- ? smile.gif

2 liverpool85:
Не забывай инициализировать переменные - я имею в виду k в данном случае. Кстати, лучше ее сделать типа boolean, раз уж на используется для проверки.
Переменная w - абсолютно лишняя, сумму можно находить прямо в if.
Все числовые параметры задавай константами. Например:
const
n1= 1;
n2= 999;
...
for i:=n1 to n2 do ...

И совет: по возможности избегай слова "таких" в выводе результатов. Пиши полностью, не ленись:
WriteLn('Чисел с суммой цифр ',n,' в диапазоне от ',n1,' до ',n2,' не найдено');

Иначе ты запустишь эту прогу через неделю, и ни фига не поймешь, что это она такое сделала )). И твой преп тебе скажет спасибо - у него много студентов, много групп, много вариантов. Ему проще, когда видно, что делает прога.
liverpool85
Спасибо за дельные советы!!
Подправил малость

const
n1=1;
n2=999;
var
n, i, a, b, c: integer;
s: string;
k: boolean;
begin
writeln('Vvedite chislo ot 0 do 27: ');
readln(n);

for i:=n1 to n2 do
begin
a:=i div 100;
b:=i div 10 mod 10;
c:=i mod 10;
if n=a+b+c then
begin
k:=true;
str(i,s);
if i<10 then s:='00'+s
else if i in [10..99] then s:='0'+s;
writeln(s:4,' ');
end;
end;
if k=false then write ('Chisel s summoj zifr ',n,' v diapazone ot ',n1,' do ',n2,' net');
end.
Lapp
Цитата(liverpool85 @ 9.09.2011 22:27) *
Подправил малость

Однако, приятно, когда советы не игнорируются! Тогда пойдем до конца )).
Я тоже подправил, смотри комментарии по тексту.
const
n1=1; { сдвигай! }
n2=999;
var
n, i, a, b, c: integer;
{ s не нужна, убери
s: string; }
k: boolean;
begin
{ я бы убрал диапазон.. ну, выдаст, что нет таких - что такого? это тоже результат }
{ вставил "целое" }
writeln('Vvedite celoe chislo ot 0 do 27: ');
readln(n);
k:= false; { обязательно инициализируй! не полагайся на компилятор }
for i:=n1 to n2 do begin
a:= i div 100;
b:= i div 10 mod 10;
c:= i mod 10;
if n=a+b+c then begin { привыкай ставить begin в конце строки, если преп не против )) }
k:=true; { после begin - сдвигать, однозначно}
WriteLn(a,b,c) { не нужно никаких ухищрений, у тебя же уже есть цифры (см. мой коммент на пост IUnknown) }
end; { end стоит точно в той позиции, где начинается строка с begin }
end;
{ не k=false, а not k }
if not k then write ('Chisel s summoj zifr ',n,' v diapazone ot ',n1,' do ',n2,' net');
end.
IUnknown
Цитата
{ я бы убрал диапазон.. ну, выдаст, что нет таких - что такого? это тоже результат }
Таких не просто "нет", их "быть не может", так что я бы как раз и добавил диапазон:

var
n : 0 .. 27; // или 1 .. 27
, и если введено не то значение - пусть программа сразу вылетает (или обрабатывать ошибку до тех пор, пока не будет введено правильное значение, попадающее в интервал).

var
n : 0 .. 27;
Ok : boolean;
begin
writeln('Введите число от 0 до 27:');
repeat
Ok := true;
try
readln(n);
except
writeln('Нет, число должно быть 0 .. 27');
Ok := false;
end;
until Ok;

// Всё, число введено, едем дальше...
writeln('n = ', n);
end.

Правда, позволяет ли это PascalABC - сказать сложно (не помню, а проверять негде). Но всегда можно заставить вводить пользователя значение из заданного интервала. Хотя бы даже и так:

var n : integer;
begin
repeat
{$I-} Readln(n); {$I+}
until (IOResult = 0) and (n > 0) and (n <= 27);
end.


P.S.
Ну, или совсем просто: не делая никаких проверок при вводе - сразу же проверять введенное число на 1 .. 27. Если принадлежит этому интервалу - то что-то можно начинать вычислять. Иначе сразу выдавать сообщение, что, мол, "при таких входных данных - какие вы хотите получить результаты? Вот, вы их и получили. Ничего нет и быть не может"
liverpool85
Если делать согласно последнему комменту, то отпадает потребность в булеан :

const
n1=1;
n2=999;
var
n: 0 .. 27;
i, a, b, c: integer;
begin
writeln('Vvedite chislo ot 0 do 27: ');
repeat
readln(n);
until (n>0) and (n<=27);
for i:=n1 to n2 do begin
a:=i div 100;
b:=i div 10 mod 10;
c:=i mod 10;
if n=a+b+c then begin
writeln(a,b,c);
end;
end;
end.
-Lapp-
Цитата(IUnknown @ 10.09.2011 9:13) *
Таких не просто "нет", их "быть не может", так что я бы как раз и добавил диапазон:

Немного странно мне это.. 27 - это же жесткая привязка к диапазону. А завтра преп скажет: сделай мне для диапазона 0000 - 9999. Менять 27 на 36? Хорошо, а если скажет от 015 до 456? Если 27 появляется в программе и зависит от диапазона - оно должно вычисляться по диапазону. А как вычислять для диапазона 03 - 12? Да вот так и вычислять - прогнать через цикл..

Предложи способ вычисления диапазона ввода для произвольного диапазона чисел - отстану smile.gif.
sheka
Цитата
привыкай ставить begin в конце строки
А это еще почему?
-TarasBer-
Потому что если строка начинается с ключевого слова (if,for,while), то это слово и так выглядит ярко, оно отлично (в паре с закрывающим ендом) выделяет блок кода, поэтому лишний раз переносить бегин не надо.
А если его переносить, то будут отвратительные заборы из ключевых слов, долгое смотрение на которые может привести к эпилепсии.
liverpool85
Цитата(-TarasBer- @ 10.09.2011 15:55) *

Потому что если строка начинается с ключевого слова (if,for,while), то это слово и так выглядит ярко, оно отлично (в паре с закрывающим ендом) выделяет блок кода, поэтому лишний раз переносить бегин не надо.
А если его переносить, то будут отвратительные заборы из ключевых слов, долгое смотрение на которые может привести к эпилепсии.

good.gif ))
Lapp
Цитата(sheka @ 10.09.2011 14:30) *
А это еще почему?
лучше 1 раз попробовать, чем 10 раз спросить ))


Добавлено через 7 мин.
liverpool85, со сдвигами у тебя еще бардак..
Цитата(liverpool85 @ 10.09.2011 12:51) *
const
n1=1;
n2=999;
...
if n=a+b+c then begin
writeln(a,b,c);
end;
end;
end.

Даже если вносишь заведомо врЕменное изменение в прогу - все равно не ленись форматировать. Лучше сдвинуть нескобко раз туда-сюда, чем оставить неправильно и запутаться в двух строчках.
И уж тем более, если показываешь свой код другим..
volvo877
Цитата
лучше 1 раз попробовать, чем 10 раз спросить ))
Пробовали. Вернулись к варианту исходников VCL, то есть

if cond then
begin
expr1;
end
else
begin
expr2;
end;


Цитата
лишний раз переносить бегин не надо.
А если его переносить, то будут отвратительные заборы из ключевых слов, долгое смотрение на которые может привести к эпилепсии.
Лично мне гораздо проще читать исходники той же VCL, чем FPC-шные (и Лазарусовские, кстати) исходники, где begin-ы в основном не переносятся smile.gif
liverpool85
Огромное спасибо всем!
Гость
Цитата(liverpool85 @ 9.09.2011 21:27) *

Спасибо за дельные советы!!
Подправил малость

const
n1=1;
n2=999;
var
n, i, a, b, c: integer;
s: string;
k: boolean;
begin
writeln('Vvedite chislo ot 0 do 27: ');
readln(n);

for i:=n1 to n2 do
begin
a:=i div 100;
b:=i div 10 mod 10;
c:=i mod 10;
if n=a+b+c then
begin
k:=true;
str(i,s);
if i<10 then s:='00'+s
else if i in [10..99] then s:='0'+s;
writeln(s:4,' ');
end;
end;
if k=false then write ('Chisel s summoj zifr ',n,' v diapazone ot ',n1,' do ',n2,' net');
end.


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