Другое > Hard'n'Soft
Вспоминаем Turbo Pascal и решаем задачи на нём
<< < (2/15) > >>
Fly:
Объясню кусок кода.
s:=0; i:=1;
  repeat
    s:=s+sin(i);
    inc(i)
  until i>n;Обнуляем сумму s, счётчику i присваиваем 1.
Далее цикл. Предположим, n = 3.
1. К переменной s прибавляем значение sin(i). Поскольку i = 1, прибавляется sin(1).
2. Увеличиваем i на единицу. Теперь i = 2.
3. Проверяем условие выхода. 2 не больше 3, значит, цикл продолжается.
4. К переменной s прибавляем значение sin(i). Поскольку i = 2, прибавляется sin(2).
5. Увеличиваем i на единицу. Теперь i = 3.
6. Проверяем условие выхода. 3 не больше 3, значит, цикл продолжается.
7. К переменной s прибавляем значение sin(i). Поскольку i = 3, прибавляется sin(3).
8. Увеличиваем i на единицу. Теперь i = 4.
9. Проверяем условие выхода. 4 больше 3, цикл закончен.
HardWareMan:
Циклы.
FOR ... TO/DOWNTO ... DO
Цикл FOR организует счетчик. Поэтому, переменная управления должна быть числовая целая. Обычно, задается начальное значение числовой переменной и конечное. Шаг фиксирован и равен +1 при использовании TO и -1 при использовании DOWNTO. Пример:

--- Код: ---var a:integer;
    b:byte;
...
for a:=0 to 3 do //Код

for b:=5 downto 2 do //Код

--- Конец кода ---
В конце цикла переменная-счетчик всегда будет иметь значение, указанное в поле TO/DOWNTO. Для досрочного выхода из цикла можно применить уже известный BREAK и тогда значение переменной-счетчика буде то, на котором цикл был прерван. Можно так же внутри цикла сразу задать значение переменной-счетчика конечному значению и цикл прервется сам, но это уже из разряда дурного тона, ибо тяжело отслеживается.

WHILE ... DO
Цикл WHILE позволять крутить кусок кода, пока выполняется требуемое условие. Если на момент входа условие не было выполнено - этот цикл не выполнится. Этот цикл гибче, чем FOR, потому как условие может быть любым. Примеры:

--- Код: ---// Условие по счетчику
var a,b:integer;
...
a:=0; b:=0;
while a<5 do begin
  b:=b*a;
  inc(a); // Если этого не сделать, то цикл станет вечным
  end;

// Условие по значению
var a,b:integer;
...
a:=1; b:=1;
while b<1000 do begin
  b:=b*a;
  inc(a); // Если этого не сделать, то цикл станет вечным
  end;

// Или можно организовать ожидание семафора / синхронизацию событий и потоков
var WaitEvent:boolean;
... // Код
while WaitEvent do sleep(100); // Ждем события, поток спит не нагружая процессор
... // Продолжение кода
// А в другом потоке или прерывании делать присвоение значений WaitEvent

--- Конец кода ---

REPEAT ... UNTIL
Цикл REPEAT позволять крутить кусок кода, пока не выполняется требуемое условие. Он имеет свойства цикла WHILE, но отличается тем, что один раз он выполняется всегда (при первом входе), а потом зацикливается, пока не выполнится условие в поле UNTIL. Примеры с WHILE, адаптированные под REPEAT (условие выхода требуется инвертировать по логике):

--- Код: ---// Условие по счетчику
var a,b:integer;
...
a:=0; b:=0;
repeat
  b:=b*a;
  inc(a); // Если этого не сделать, то цикл станет вечным
until a>5;

// Условие по значению
var a,b:integer;
...
a:=1; b:=1;
repeat
  b:=b*a;
  inc(a); // Если этого не сделать, то цикл станет вечным
until b>1000;

// Или можно организовать ожидание семафора / синхронизацию событий и потоков
var WaitEvent:boolean;
... // Код
repeat
  sleep(100);
until not WaitEvent; // Ждем события, поток спит не нагружая процессор
... // Продолжение кода
// А в другом потоке или прерывании делать присвоение значений WaitEvent

--- Конец кода ---
Вот как-то так, если говорить в кратце.
gepar:
Fly, большое спасибо за подробное разъяснение  :)
Прочитал о массивах и типе char и снова что-то много вопросов появилось притом не пойму почему в книге даются такие упражнения , задать которые прочитав инфу только этой книги я бы сказал просто невозможно .
Теперь возникшие вопросы о char :
1)В одном из заданий задано мол нужно найти символы '+' и '*' введённые с клавиатуры , но так как последний символ не указан то мне нужно задать причину чтобы цыкл повторялся со всеми символами до нажатия enter , как это сделать ?Я задал что последний символ '/' и всё работает , но я хочу узнать как всё же задать что последним будет нажатия кнопки enter , у неё ведь и кода то нет в таблице символов .Код программы
program proga1;  //программа считает сколько раз среди данных символов попадаеться символ + и символ *//
uses crt;
var
   a:char;
   b,c:integer;
   i:integer;
Begin
     write('enter a');
     read(a);
     b:=0;c:=0;
     while a<>'/' do
     Begin
     if a='*' then b:=b+1
     else if a='+' then c:=c+1;
     read(a);
     end;
     write(b);
     writeln;
     write(c);
end.2)Задание : Дана последовательность из n символов .Выяснить имеются ли в последовательности два подряд идущих символа ',-'
Вопрос : как сделать так чтобы при выполнении цикла считывалось по 2 символа ?
3)Задание :Дана последовательность из n символов , известно что в ней есть хотя-бы одна запятая .Найти номер первой и последней запятой .Вопрос: как определять номера введённых символов , в частности  тех отдельных символов (запятых) что найдет программа ?
4)Задание :Вывести на экран изображение всех возможных символов вместе с их номерами
Вопрос : как это сделать то ?Просто вывести все символы я могу вот так :
var
i:byte;
Begin
for i:=1 to 255 do
write (chr(i));
end.
а вот как ещё и номера приписать перед каждым символом ...
HardWareMan:
Длина строки будет length(). Или нулевой элемент в строке (Дельфи не дает туда обращаться).
Твой код:

--- Код: ---var l:string;
    a,b,c:integer;
    s:char;
begin
     writeln('Input line, confirm input by <ENTER> key:');
     readln(l);
     if length(l)>0 then begin
        a:=0; b:=0;
        for c:=1 to length(l) do begin // Стринги идут от 1!!! 0й элемент - длинна
            s:=l[c];
            case s of
              '*' : inc(a);
              '+' : inc(b);
              end;
            end;
        writeln('* = ',a,', +',b);
        end else writeln('Zero length string are not allowed!');
end.
--- Конец кода ---
Вывод всех ASCII:

--- Код: ---var c:byte;
begin
     for c:=$20 to $FF do write('<',chr(c),'> = ',c); // Символы менее 20H (32) являются служебными
end.

--- Конец кода ---
Про 3е задание надо покурить хелпик пасовский. Там ЕМНИП есть функция поиска символа (типо LEFT/RIGHT/MID), которая и укажет на позицию требуемого символа. Касаема 2го задания, то я вижу это примерно так:

--- Код: ---var l:string;
    c:integer;
begin
     writeln('Input string:');
     readln(l);
     if length(l)>2 then begin
        for c:=1 to Length(l)-1 do
            if (l[c]=',') and (l[c+1]='-') then writeln('Match "',l[c],l[c+1],'" found at position ',c);
        end else writeln(String must have at least 2 symbols!');
end.
--- Конец кода ---
gepar:

--- Цитата: HardWareMan ---if length(l)>0 then begin
--- Конец цитаты ---
А можно в двух словах что за length и с чем его едят ну или ссылку на соответствующую инфу , ато в первых 17 пунктах той книги о паскале о такой штуке ни слова .
P.S по логике я так понял что это типа лента чисел ну или что-то типа массива , я правильно понял или есть ещё какието особенности в отличии от массива ?

Добавлено позже:
Ну и по-поводу массивов :
1)Задание: напишите программу которая сначала вводит десять чисел в одномерный массив , а затем складывает отдельно все положительные элементы и выдаёт полученные результаты.Проблема заключается в том что  как заставить паскаль ввести 10 чисел "от себя" не написано да и как рассортировать  отдельно положительные и отрицательные числа я тоже пока что не знаю (ну не забивать же если 1 элемент больше 0 знать прибавлять к a , в ином случае прибавлять к b и так 10 раз  :)  ).

Добавлено позже:
HardWareMan, большое спасибо за помощ , сейчас буду разбираться с  написанными тобой остальными кодами .
HardWareMan:
Стринги - это массив чаров. В TP его длина равняется 255 символам. Стало быть, массив состоит из 256 байт, первый байт которого является его длиной, а остальные  - непосредственно символами. Отличие стринга от обычного массива в том, что у стрингов есть сервис, для поиска, фильтрования, обрезания и т.д. Ну и выводить их легко: write()/writeln() и все. Функция length() возвращает текущую длину стринга (при задании стрингу значения '' - два апострофа, то длина равна 0). В TP7 и BP7 значение функции length() равно нулевому элементу стринга. Дельфи запрещает прямое обращение к нулевому элементу стринга.

Добавлено позже:

--- Цитата: gepar от 30 Октябрь 2009, 13:57:13 ---Ну и по-поводу массивов :
1)Задание: напишите программу которая сначала вводит десять чисел в одномерный массив , а затем складывает отдельно все положительные элементы и выдаёт полученные результаты.Проблема заключается в том что  как заставить паскаль ввести 10 чисел "от себя" не написано да и как рассортировать  отдельно положительные и отрицательные числа я тоже пока что не знаю (ну не забивать же если 1 элемент больше 0 знать прибавлять к a , в ином случае прибавлять к b и так 10 раз  :)  ).
--- Конец цитаты ---

--- Код: ---var c,n,e:integer;
    l:string;
    num:array[1..10] of integer;
begin
     c:=1;
     repeat
       write('#',c,' Input integer decimal number '); readln(l);
       val(l,n,e); //Преобразовываем число
       if e=0 then begin
          num[c]:=n; inc(c);
          end else writeln('Error in number, repeat input.');
     until c>10;
     n:=0;
     for c:=1 to 10 do
         if num[c]>=0 then begin
            writeln('Found positive number ',num[c],' at position ',c);
            n:=n+numc[c];
            end;
     writeln('Total summ of positive numbers are ',n);
end.

--- Конец кода ---
Как-то так.
gepar:
Cлегка попроще задание , вот только немогу догадаться в чём именно здесь хитрость .
Переменная X содержит трехзначное число .Поместить в переменную S сумму цифр этого числа .
Как определить второе и третее числа ?Первое я могу разделив на 100 и откинув остаток , а остальные как ? :)
BaNdiT:
div - целочисленное деление (результат деления без учёта остатка).
mod - остаток от деления.
Соответственно, первая цифра числа = <число> div 100 (или 1 000, или 10 000... - смотря сколько цифр в числе). Последняя цифра = <число> mod 10. Все остальные находятся комбинацией div и mod (например, вторая с конца = (<число> mod 100) div 10 - т.е. сначала выделяешь две последние цифры, а потом отсекаешь самую последнюю).
gepar:
BaNdiT,спасибо за разъяснение .

Добавлено позже:
Задание Напишите программу калькулятор , позволяющую вычислять по выбору одну из четырёх основных арифметических операций .
Я тут планировал все сделаать через case , но что-то лыжи не едут , а именно как я понял case и char  несовместимы  :
program proga101;
uses crt;
label 1;
var
a,b,d:real;
c:char;
Begin
    writeln('Enter a');
    read(a);
    writeln('Enter symbol (/,*,+,-)');
    read(c);
    writeln('Enter b');
    read(b);
    case c of
    /: d:=a/b
    Задание вообще как я понял относиться к лёгким , но что-то мне оно таковым не показалось .
UPD: При выполнении другого задания вспомнил что символы же нужно брать в скобки , и как я мог это забыть .В итоге получилось вот что :
program proga101;
uses crt;
label 1;
var
a,b,d:real;
c:char;
Begin
    1: writeln('Enter a');
    read(a);
    writeln('Enter symbol (/,*,+,-)');
    read(c);
    writeln('Enter b');
    read(b);
    case c of
    '/': d:=a/b;
    '*': d:=a*b;
    '+': d:=a+b;
    '-': d:=a-b;
    end;
    writeln('summa=',d,' ');
    writeln('Continue ?Y/N ?');
    read(c);
    if c='y' then goto 1;
end.
 Программа работает что радует , хотя я почему то уверен что эту программу можно сделать как-то проще /быстрее/лучше/всё вместе(и проще и быстрее и лучше) если я прав то вдруг кому не лень напишите пожалуйста как это задание было бы лучше выполнить .И вообще хотелось бы узнать у специалистов по паскалю нормально ли я  сам код программы пишу , или есть какието замечания ?Не хочеться же в итоге индусский код писать то . :)
aUruM:
1. Считать два операнда и символ операции, выбрать требуемую операцию, посчитать значение результата и вывести на экран - я не вижу, что тут можно сократить. Ну разве что можно сэкономить одну строчку вот таким способом:

--- Код: ---    '/': writeln('summa=',a/b,' ');
    '*': writeln('summa=',a*b,' ');
    '+': writeln('summa=',a+b,' ');
    '-': writeln('summa=',a-b,' ');
--- Конец кода ---
То есть, не помещать результат вычислений в отдельную переменную, а сразу вывести на экран.

2. От goto неплохо бы избавиться, например, использовав цикл until.
gepar:

--- Цитата: aUruM ---2. От goto неплохо бы избавиться, например, использовав цикл until.
--- Конец цитаты ---
Ну я goto использую на даный момент только для повтора (чтобы с конца в начало кинуть ) или же при исключениях , но постараюсь перейти на repeat until , спасибо за совет .

Добавлено позже:
Задание:Напишите программу , которая возводит действительно число , введённое с клавиатуры, в степень, введённую с клавиатуры, в диапазоне от 2 до 9.Исключите несуществующие (меньше 2 и больше 9) степени, и снабдите программу запросом об окончании работы .
Моё решение вот такое :
program proga105;
uses crt;
label 1,2;
var
a,b:integer;
c:char;
Begin
     1: writeln('Vvedite 4islo');
     read(a);
     writeln('Vvedite stepen" ');
     read(b);
     case b of
     2: a:=a*a;
     3: a:=a*a*a;
     4: a:=a*a*a*a;
     5: a:=a*a*a*a*a;
     6: a:=a*a*a*a*a*a;
     7: a:=a*a*a*a*a*a*a;
     8: a:=a*a*a*a*a*a*a*a;
     9: a:=a*a*a*a*a*a*a*a*a
     else
     Begin
     writeln('Vvedenno chislo >9 ili <2');
     goto 2;
     end;
     end;
     writeln(a);
     2: writeln('Continue ? Y/N');
     read(c);
     if c='y' then goto 1;
end.
И здесь мне тоже почемуто кажеться что можно сделать както по другому так как уж больно всё получилось привязано к тому что граница возможной степени дана , а если бы её не было ... Вообщем можно как-то по другому без привязки к граници степени сделать такое упражнение ?

Добавлено позже:
P.S В решении данного примера используется goto так как решал я даный пример ещё до прочтения замечания по поводу употребления goto .
aUruM:

--- Код: ---     2: a:=a*a;
     3: a:=a*a*a;
     4: a:=a*a*a*a;
     5: a:=a*a*a*a*a;
     6: a:=a*a*a*a*a*a;
     7: a:=a*a*a*a*a*a*a;
     8: a:=a*a*a*a*a*a*a*a;
     9: a:=a*a*a*a*a*a*a*a*a
--- Конец кода ---
Вот это - действительно индусский код. Во-первых, если мы возводим число в целую степень, то имеет смысл воспользоваться, к примеру, циклом for.

Потом, вас же просят возвести в степень действительное, а не целое число. Почему переменная a у вас имеет тип Integer?

Кроме того, если a - только положительное, то можно воспользоваться известной формулой:



В вашем случае это будет выглядеть примерно так:

--- Код: ---a:=exp(x*ln(a));
--- Конец кода ---
AnXIouS:
Ну и я вспомню немного что-ли, первый мой курс института.

--- Цитата ---program proga105;
uses crt;
var
   a,x: real;
   b: integer;
   z: char;
BEGIN
repeat
   write('Vvedite 4islo = ');
   readln(a);
   x := a;
   write('Vvedite stepen = ');
   readln(b);
   if (b >= 2) and ( b <= 9) then  // если убрать отсечение, то любая степень,
   begin                                   // в пределах возможностей компилятора или переменной
      while b > 1 do
      begin
         a := a * x;
         dec(b);
      end;
   end
   else
      writeln('Vvedenno chislo >9 ili <2');
   writeln(a:2:4);
   writeln('Continue ? Y/N');
   readln(z);
until z <> 'y';
END.
--- Конец цитаты ---
gepar:

--- Цитата: AnXIouS ---until z <> 'y';
--- Конец цитаты ---
Так там же знак не равно в итоге получиться пока будет нажиматься любая другая кнопка кроме 'y' будет повторяться цикл , или я что-то не так понял ?

Добавлено позже:

--- Цитата: aUruM ---В вашем случае это будет выглядеть примерно так:Код:a:=exp(x*ln(a));
--- Конец цитаты ---
Сейчас постараюсь с этим всем разобраться .
AnXIouS:

--- Цитата: gepar от 21 Ноябрь 2009, 15:48:59 ---Так там же знак не равно в итоге получиться пока будет нажиматься любая другая кнопка кроме 'y' будет повторяться цикл , или я что-то не так понял ?

--- Конец цитаты ---

--- Цитата ---
--- Цитата ---repeat  statement   until   expession;
--- Конец цитаты ---
Здесь вначале выполняется оператор statement, а затем вычисляется значение логического выражения expression. Процесс повторяется, пока выражение expression принимает значение «ложь». Как только это значение станет истинным, выполнение цикла прекращается.
--- Конец цитаты ---
gepar:
AnXIouS, понял , что-то затупил я с repeat until'ом .

Добавлено позже:
у меня в учебнике по турбо паскалю (посоветованному в прошлой теме) в многих заданиях типа этого : напишите программу для вычисления функции y=x^2-16x + 32 для x от 1 до 10 с шагом 0,25 , есть вот такое 'x^2', вопрос возможно глупый но что это в программировании ?Степень ? И ещё вопрос как делать шаг не 1 (for a=1 to 10) , а именно 0,25 ну или какоето другое число ?
AnXIouS:
Да, "^", это степень, не совсем в программировании...
Цикл For в некоторых Паскалях имеет ширину шага, кажется так " for i=1 to 10 step 2 do "
А чтобы шагать дробно, использовать проще цикл while.
Fly:

--- Цитата: gepar ---И ещё вопрос как делать шаг не 1 (for a=1 to 10) , а именно 0,25 ну или какоето другое число ?
--- Конец цитаты ---
Можно сделать цикл с шагом 1, а потом делить переменную на 4.

--- Код: ---for a:=1 to 10 do b:=b+a/4
--- Конец кода ---
gepar:
AnXIouS, сейчас попробую и с указанным шагом , но я пока что сделал вот так :
program proga107;
uses crt;
var
x,y:real;
Begin
     x:=1;
     while x<=10 do
     Begin
     y:=(sqr(x))-(16*x)+32;
     write ('x=',x,' y=',y,' ');
     writeln;
     x:=x+0.25;
     end;
end.
Не все результаты правда влезли в экран (да можно их в одну строчку подряд писать с пробелами , но результаты както всё равно сливаются), а можно ли в паскале както прикрутить полосу для навигации справа чтобы можно было листать результаты ?

Добавлено позже:

--- Цитата: AnXIouS ---Цикл For в некоторых Паскалях имеет ширину шага, кажется так " for i=1 to 10 step 2 do "
--- Конец цитаты ---
В некоторых в каком смысле ?Тоесть не у всех , ну тогда уже наверное действительно лучше пользоваться циклом while . У меня после 10 сразу пишет ожидалось do , у меня паскаль ABC .

Добавлено позже:
Fly, если не лень и есть время напиши пожалуйста свой вариант , ато что-то я не понял как с таким алгоритмом оно будет работать ,а вернее правильно работать , код частично скопируй у меня для экономии времени  :)
AnXIouS:

--- Цитата: gepar от 21 Ноябрь 2009, 19:02:25 ---а можно ли в паскале както прикрутить полосу для навигации справа чтобы можно было листать результаты ?

--- Конец цитаты ---
Никак, разрешение текстовых режимов в DOS три - 80х25, 40х25 и 80х50 символов.
Вывод нужно форматировать writeln(a:1:2); Первая цифра количество символов после запятой, вторая - общее кол-во (кажется †). А потом в цикле делать проверку: if i div 10 = 0 then WriteLn; (если остаток от деления ноль, то перевести строку. выводя при этом write'ом).
Навигация
Главная страница сообщений
Следующая страница
Предыдущая страница

Перейти к полной версии