Основы программирования на языке Паскаль
p align="left"> Program Prim3; Label M; Var x:real; BEGIN x:=0; M: writeln('x=',x,'cos x = ',cos(x)); x:=x+0.01; goto M; readln; END. Программа будет работать следующим образом: х присвоится значение 0; writeln выведет на экран текст, который указан в первых кавычках х =, далее извлечет из ячейки х значение и выведет его на экран; затем снова выведет текст cos х =, затем вычислит значение cos х и выдаст его на экран, т.е. машина выведет первую строку в виде x = 0.0000000000Е + 00 cos х = 9.9999999999Е - 01. После этого возьмется то х, которое было извлечено из ячейки памяти х (прежнее значение х), т.е. 0.0, к нему прибавляется величина 0.01 и результат снова занесется в ячейку памяти х так, что в х будет 0.01, после этого оператор goto m; передаст управление оператору, помеченному меткой м, т.е. оператору writeln, и машина выдаст новую строку: x = 1.0000000000Е - 02 cos х = 9.9995000041Е - 01; - выполнит оператор х: =x + 0.01, получит х = 0.02; - выведет строку x = 2.0000000000Е - 02 cos х = 9.9980000666Е - 01; - сделает х = 0.03 и т.д., до бесконечности, так как в данном алгоритме окончание работы не предусмотрено. Для завершения работы следует применить оператор if. 3.3. Оператор if Общий вид: If булевское выражение then оператор else оператор; Работа оператора: вначале вычисляется булевское выражение, значение которого в конечном итоге может быть только TRUE или FALSE. Если булевское выражение TRUE, то выполняется оператор, следующий за словом then, а затем происходит переход к оператору, следующему за if. Если булевское выражение false, то выполняется оператор, следующий за словом else, затем происходит переход к оператору, следующему за оператором if. Замечание: после оператора, следующего за then, перед else символ ';' не ставится, так как оператор if еще здесь не закончен, а ';' ставится после окончания оператора. Возможно применение сокращенного оператора if: If булевское выражение then оператор; Здесь, если булевское выражение true, выполняется оператор, следующий за словом then, и происходит переход к оператору, следующему за оператором if. Если булевское выражение false, то оператор if игнорируется (вообще не выполняется), а выполняется оператор, следующий за if. Переделаем "бесконечную" программу п. 3.2. в такую, которая остановится тогда, когда х станет равным 0.1. Program Prim4; Label M; Var x:real; BEGIN x:=0; M: writeln('x=',x,' cos x = ',cos(x)); x:=x+0.01; if x<=0.1 then goto M; readln; END. Программа выдает результаты вычислений cos(x) для х = 0.01, 0.02, 0.03 и т.д., до 0.01. В последней программе булевское выражение х < = 0.1. Какие бывают булевские выражения? Вообще говоря, булевское выражение после вычисления всегда истинно или ложно, т.е. TRUE или FALSE. Действительно, выражение х < = 0.1 может быть истинно, если х меньше или равно 0.1, и ложно - в противном случае. Вообще булевское выражение может строиться из булевских констант TRUE и FALSE; переменных булевского типа (в которых могут храниться TRUE или FALSE); обращений к функциям, которые возвращают TRUE или FALSE и отношений, соединенных между собой булевскими операциями и круглыми скобками. Здесь следует расшифровать, что такое отношения и булевские операции. Примером отношения может быть приведенное выше х < = 0.01, т.е. в общем случае отношение - это два арифметических выражения, соединенных между собой операциями отношения. Операции отношения: = (равно), < > (неравно), > (больше), > = (больше или равно), < (меньше), < = (меньше или равно). Пример отношений: а + b < = sin(c) exp(p) > (cos(i) - a)/sgr(b). Как мы уже говорили, эти отношения могут быть истинны или ложны в зависимости от конкретного значения величин, в них входящих, на момент вычисления. Логические операции - это нам уже известные. Напомним, как они работают: or (или), and (и). Имеется описание Var A,B: boobean; Or - логическое сложение, читается как "или". Результат операций - истина, если или А, или В - истина, и ложь, если А и B ложны. Например: А В А ог В true true true true false true false true true false false false Замечание: данная операция аналогична арифметической OR, если TRUE заменить 1, а FALSE - 0. АND - логическое умножение, читается "и". Результат операции - истина только тогда, когда и А, и В - истина, в остальных случаях результат - ложь. А В A and B true true true true false false false true false false false false Кроме того, удобно применять однокомпонентную операцию Not, которая вводится следующим образом: если А есть TRUE, то Not А есть FALSE и если А есть FALSE, то Not А есть TRUE. С помощью этих операций можно построить условия любой сложности. Например, пусть необходимо решить задачу: Напишем программу: Program Prim5; Var a,x:real; BEGIN writeln('введите а,х'); readln(a,x); if (a>0) and (x>0) and (x<=0.5) then writeln('z=',a*sqr(x)/sin(x)) else if (a>0) and (x>=0.5) and (x<3) then writeln('z=',exp(x)) else if (a<=0) or (x<=0) then writeln('z=',sqrt(a)*sqrt(x)/sin(x)) else writeln('z=0'); readln; END. Замечание: в последнем примере мы видим, что операторы if могут быть вложены друг в друга. Вкладывать их можно неограниченное количество раз, причем новый if может начинаться как после слова then, так и после слова else. Еще один пример: пусть дана область (заштрихованная на рис. 3.3). Мы вводим с клавиатуры координаты точки. Машина должна определить, принадлежит ли данная точка этой области или нет. Разобьем область рис. 3.3 на несколько простых: 1. Внутренняя часть сектора, ограниченного отрицательной частью оси OX, положительной OY и окружностью с центром в начале координат и радиусом, равным 2. 2. Прямоугольник, ограниченный осями OX, OY и прямыми x=4, y=2. 3. Прямоугольник, ограниченный осями OX, ОУ и прямыми x=-2, y=-4. 4. Внутренняя часть сектора, ограниченного положительной частью оси OX, отрицательной OY и окружностью с центром в начале координат и радиусом, равным 3. 5. Внутренняя часть квадрата, ограниченного прямыми линиями x=2, x=3, y=-3, y=-4. 6. Область, лежащая внутри окружности с центром x=5, y=-3 и радиусом= 1,5. Программа: Program Prim6; Label N,K,L; Var x,y:real; f:char; BEGIN N: writeln('введите координаты точки'); readln(x); writeln('x=',x); readln(y); writeln('y=',y); if (x<=0) and (y>=0) and (sqr(x)+sqr(y)<=4) {1-я область} or (x>=0) and (x<4) and (y>=0) and (y<=2) {2- я область} or (x<=0) and (x>=-2) and (y<=0) and (y>=-4) {3- я область} or (x>=0) and (y<=0) and (sqr(x)+sqr(y)<=9) {4- я область} or (x>=2) and (x<=3) and (y<=-3) and (y>=-4) {5- я область} or (sqr(x-5)+sqr(y+3)<=2.25) {6- я область} then writeln('точка с координатами х=',x,' y=',y, 'принадлежит области') else writeln('точка с координатами х=',x,' y=',y, 'не принадлежит оласти); L: writeln('будем ли ещё вводить координаты точки?, Y, N'); readln(f); if (f='Y') or (f='y') then goto N else if (f='N') or (f='n') then goto K else writeln('неправильно нажали клавишу, попробуйте ещё раз'); goto L; K: readln; End. Замечание: для того, чтобы построить область, необходим здравый смысл и элементарные знания аналитической геометрии. Так, х>=0 определяет область (рис. 3.4) x>=0 and x<=4 определяет полосу (рис. 3.5) Вспомнив, что уравнение окружности с центром в начале координат x2+y2=r2, имеем x2+y24 (рис. 3.6), x 0 является полуплоскостью (рис. 3.7), y 0 определяет полуплоскость (рис. 3.8), x 0 and y 0 есть квадрант (рис. 3.9) и, наконец, x 0 and y 0 and sqr(x)+sqr(y)4 есть сегмент (рис. 3.10) 3.4. Оператор case (оператор выбора) Общий вид: Case выражение - селектор of Список констант выбора 1: оператор 1; Список констант выбора 2: оператор 2 ; - - - - - - - - - - - - - - - - - - - - - - - - - - Список констант выбора n оператор n; else оператор end; Здесь выражение-селектор есть выражение, которое после выполнения имеет любое скалярное значение, кроме вещественного (типы данных; разд. 2.6.), т.е. выражение-селектор может быть байтового, целого, логического, символьного, перечисляемого и интервального типов. Список констант выбора состоит из перечня констант, разделенных запятыми, либо из констант, заданных интервалом, либо из комбинаций перечня констант и интервалов. Тип констант в списках Case должен соответствовать типу выражения селектор. Значения констант в списках не должны повторяться. Работа оператора. вначале вычисляется выражение-селектор, затем полученное значение сравнивается с константами выбора, и, если значение выражения-селектора совпадает с какой-либо константой выбора, то выполняется оператор, стоящий после списка констант, в котором есть константа, совпадающая со значением выражения-селектора. если значение выражения-селектора не совпадает ни с одной из констант выбора, то выполняется оператор, следующий за else. Else может в Case отсутствовать, тогда в случае несовпадения констант оператор Case игнорируется. Примеры: 1. Селектор целого типа, список констант представлены перечнем констант:
Program Prim7;Var i,z:integer;BEGIN writeln('введите целое i'); readln(i); Case i of 1,2,5: writeln('i=',i,' z=',i+10); 12,16: writeln('i=',i,' z=',i+100); 31,35,46: writeln('i=',i,' z=',i+1000); else writeln('неправильно задано i'); end; readln; END. 2. Селектор целого типа - список констант представлен диапазоном. вводится целое i, определить, находится ли оно в диапазоне 1-10 или 11-100, или 101-1000, либо вне этих диапазонов. Program Prim8;Var i:integer;BEGIN writeln('введите целое i'); readln(i); Case i of 1..10: writeln(' число в диапазоне 1-10'); 11..100: writeln(' число в диапазоне 11-100'); 101..1000: writeln(' число в диапазоне 101-1000'); else writeln(' число вне диапазона 1-1000'); end; readln; END. 3. Селектор целого типа, список констант представлены перечнем констант и диапазоном: Program Prim9; Var i:integer; x,m,a,b,c,d:real; BEGIN writeln('введите значение i'); readln(i); writeln('введите значения x,m,a,b,c,d'); readln(x,m,a,b,c,d); Case i of 1,2,4,8,11..20,24,28,30: writeln('y=',(x+1)/(sqr(x)+2)-ln(m)+2a/b); 31,45..55: writeln('y=',(sqr(a)+m)/sqrt(b+m)-3ab/c+d); 58,60,63..76,78,93,100: writeln('y=',sqr(x)-ax+sqr(sin(ax)-exp(x)) /(1-ln(sqr(x)-exp(х/2)))); else writeln('неправильно задано i'); end; readln; END. 4. Селектор знакового типа: Program Prim10; Var name:char; BEGIN writeln('введите шифр'); readln(name); Case name of 'S','s': writeln(' факультет самолето- и вертолетостроения'); 'D','d': writeln(' факультет авиадвигателестороения'); 'Y','y': writeln(' факультет систем управления'); 'L','l': writeln(' факультет летательных аппаратов'); 'R','r': writeln(' факультет радиотехнический '); 'M','m': writeln(' факультет инженерно - менеджерский'); 'Z','z': writeln(' факультет заочного обучения'); else writeln('введенный шифр не соответствует ни одному ', 'из факультетов ХАИ'); end; readln; END. 5. Селектор перечисляемого типа: Program Prim11; Var season:(winter,spring,summer,autumn); rez:integer;BEGIN season:=spring; Writeln('результат ord(season)=',ord(season)); case season of winter: writeln('winter'); spring: writeln('spring'); summer: writeln('summer'); autumn: writeln('autumn'); end; readln; END. 4. Циклические программыНаиболее часто в практике программирования встречаются циклические программы. В циклических программах какой-либо алгоритм повторяется многократно, при этом один из параметров изменяется. Например, описанная в п. 3.3 программа Рrim 4 является классическим примером циклического алгоритма. Операторов цикла в Паскале три: for, repeat, while.
4.1. Оператор for Оператор состоит из заголовка, в котором определяется порядок изменения переменной параметра цикла и тела цикла, являющегося многократно повторяющимся алгоритмом. Общий вид оператора: for - параметр цикла: = начальное значение to, конечное значение do {заголовок}; оператор; {тело цикла}. Этот оператор применяется, если начальное значение < конечного значения; for - параметр цикла:=начальное значение downto, конечное значение do; оператор; применяется, если начальное значение > конечного значения. Пример: найти сумму квадратов целых чисел от 8 до 1.24. Program Prim12; Var i,s:integer; BEGIN s:=0; for i:= 8 to 124 do s:=s+sqr(i); writeln('s=',s); readln; END. Работа программы. В разделе Var выделяется ячейка памяти с именем i и s для хранения величин. Поскольку в S мы должны накапливать сумму, то вначале занесем в S ноль. Затем заголовок цикла присваивает i=8. далее выполняется тело цикла: извлекается содержимое ячейки S (а там у нас 0) и к этому содержимому прибавляется sgr(i), т.е. i2=82. Результат присваивается ячейке S, т.е. в S теперь 82. Проверяется, не стал ли параметр цикла больше конечного значения параметра 128. Это не произошло, поэтому i присваивается следующее значение равное 9 и вновь выполняется тело цикла, т.е. S:=82+92. Можно сказать так: S присвоить тому S, которое было раньше, + следующее i2. Так как цикл еще не закончился, то i станет равным 10, а S присвоится тому S, которое было раньше, т.е. 82+92, и к нему прибавится еще текущее i2, т.е. 102. Этот процесс повторяется до тех пор, пока параметр цикла не станет равным 124. Тогда в последний раз 1242 прибавляется к накапливаемой сумме. Итак: выполнение цикла значения i значения S 1 8 82 2 9 82+92 3 10 82+92+102 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 116 117 82+92+102+…+1232 117 124 82+92+102+…+1232 +1242 При i=125 происходит выход из цикла и переход к оператору writeln ('S=' ,S); Эта, казалось бы, правильно написанная программа дает результат S=-12250. Как может получиться отрицательный результат при суммировании квадратов - заведомо положительных чисел? Такой результат мы получаем путем суммирования и занесения результатов в ячейку S типа integer, а в integer могут быть помещены числа в диапазоне -32768 +32767, поэтому после переполнения ячейки памяти в знаковый разряд переносится 1, которая интерпретируется машиной как '-'. Чтобы этого избежать, можно описать S как longint. Тогда результат работы программы будет правильный и равен 643110. Program Prim12a; Var i,s:longint; BEGIN s:=0; for i:= 8 to 124 do s:=s+sqr(i); writeln('s=',s); readln; END. Можно также описать S как real. Program Prim12b; Var i:integer; s:real; BEGIN s:=0; for i:= 8 to 124 do s:=s+sqr(i); writeln('s=',s); readln; END. Результат работы этой программы будет равен 6.4311000000E+05, что то же самое, что и 643110, если считать, что запись 6.4311000000E+05 равносильна математической записи 6,431110+5. Правила применения оператора цикла for 1.Тело цикла - всегда один оператор. Если нужно, чтобы тело цикла состояло из нескольких операторов, то их объединяют в один с помощью операторных скобок begin, end. for i:=l to n do Begin S:=S+sin(x)/cos(x); x=x+0.01; writeln('S=' ,S) end. Операторы, взятые в операторные скобки begin, end, считаются одним составным оператором. 2. Начальное и конечное значения параметра цикла в общем случае являются выражениями. Тип этих выражений и тип параметра цикла должны совпадать. Здесь допускается применение любых типов, которые упорядочены с каким-либо фиксированным шагом, это может быть любой скалярный тип, кроме вещественного, т.е. байтовый, целый, символьный, перечисляемый, интервальный, булевский. на практике чаще всего применяют целочисленный тип. 3. В теле цикла параметр цикла не должен изменяться. 4. Нельзя с помощью оператора перехода goto войти в тело цикла, минуя заголовок. 5. Выйти из тела цикла в программу можно по if..goto, не дожидаясь полного перебора параметров цикла. Пример: написать программу, выводящую буквы латинского алфавита в одну сторону, с пробелом между ними. Применяем здесь в качестве параметра цикла символьную переменную, в качестве начального значения параметра - константу 'A', конечного - 'Z'. Program Prim13; Var i:char; BEGIN for i:='a' to 'z' do write(' ',i); readln; END. Пример: вычислить значение определенного интеграла на участке a,b для функции cos х, т.е. определить площадь, заштрихованную на рис. 4.1. Применим метод трапеций, суть которого заключается в том, что область делится на ряд трапеций, площади которых вычисляются и суммируются. Чем на большее количество трапеций мы разделим область, тем точнее получим результат (см.рис.4.2). Program Prim14; Var i,n:integer; a,b,x,h,s:real; BEGIN writeln(' введите к-во точек разбиения n и величины а, b'); readln(n,a,b); h:=(b-a)/n; s:=0; x:=a; for i:=1 to n do Begin s:=s+(abs(cos(x))+abs(cos(x+h)))/2*h; x:=x+h; end; writeln('s=',s); readln; END. Замечание: при вычислении S (так как функция пересекает ось OX) часть площадей может иметь отрицательное значение, поэтому мы берем abs(f(x)). Усложним задачу: пусть нужно найти площадь криволинейной трапеции (интеграл), где функция от точки а до b sin(x), а после b до с cos(x). Program Prim15; Var i,n:integer; a,b,c,x,h,s,fxpred,fxposl:real; BEGIN writeln('введите к-во точек разбиения n и величины а, b, c'); readln(n,a,b,c); h:=(c-a)/n; s:=0; x:=a; for i:=1 to n do Begin { определимся, по какой из функций считать стороны трапеций } if (x>=a) and (x<=b) then fxpred:= abs(sin(x)) else fxpred:=abs(cos(x)); if (x+h>=a) and (x+h<=b) then fxposl:= abs(sin(x+h)) else fxposl:=abs(cos(x+h)); s:=s+(fxpred+fxposl)/2*h; x:=x+h; end; writeln('s=',s); readln; END. В последних двух программах мы заменяем площадь криволинейной трапеции (интеграл) суммой трапеций. При этом нам неизвестно, какую ошибку мы допустим; знаем, что чем больше точек разбиения, тем точнее будет результат. Поставим задачу: совершенно точно знать, что мы посчитаем интеграл с точностью не менее заданной, например, что разность между площадью криволинейной трапеции и суммой прямоугольных трапеций будет не больше Е = 0.01. Для этого нам нужно посчитать результат для количества точек, например 10, затем - 100. Сравнить величины площадей, и, если их разность будет меньше Е, то можно с уверенностью сказать, что площадь для разбиения на 100 интервалов будет найдена с точностью не менее Е. Если разность между расчетами на 10 и 100 интервалов больше Е, то следует разбить область интегрирования на 1000 интервалов и сравнить сумму для 100 интервалов с суммой для 1000 интервалов, и если их разница будет меньше Е, то за результат принять площадь, посчитанную для 1000 разбиений и т.д. рано или поздно мы получим искомый результат. Сравнения сумм площадей трапеций будем производить с помощью оператора if. Пусть функция будет cos(x). Напишем программу: Program Prim16; Label NAH,KON; Var i,n:integer; a,b,x,h,spred,spos,e:real; BEGIN writeln('введите точность е и границы a, b'); readln(e,a,b); spred:=9.9e+10; h:=0; n:=10; NAH: spos:=0; h:=(b-a)/n; x:=a; for i:=1 to n do Begin spos:=spos+(abs(cos(x))+abs(cos(x+h)))/2*h; x:=x+h; end; if abs(spos-spred)<=e then Begin writeln('s=',spos,' n=',n); goto KON; end else spred:=spos; n:=n*10; x:=a; goto nah; KON: readln; END. Работа программы: for i: = i to n do, в первый раз оператор Spоs: = spos+(abs(cos(x))+abs(cos(x+h)))/2h посчитает значение интеграла для 10 точек разбиения. Затем if сравнит полученное значение spos с 9.9Е+10. Конечно, разница между этими величинами не будет меньше е, тогда мы забудем число 9.9Е+10, так как присвоим spred: = spоs, чтобы при следующем выполнении if сравнивать предыдущее и последующее значения интеграла. После этого увеличим количество точек разбиения n: = n10 и вернемся на начало вычисления spos, т.е. интеграла для 100 интервалов goto nach. После нового вычисления spos сравним 100 интервалов для 10 интервалов spred. Если разность между ними не меньше Е, то забудем значение s для 10 интервалов и занесем в spred значение для 100 интервалов. Затем вычислим значение интеграла для разбиения 1000 и результат занесем в spos, сравним spred и spos и т.д.
4.2. Оператор repeat. Общий вид В отличие от for, оператор repeat (а также while) применяют тогда, когда неизвестно точно, сколько раз будет выполняться тело цикла. Общий вид оператора repeat оператор; оператор; - - - - - - - - оператор until булевское выражение; Работа оператора. Сначала выполняются операторы, составляющие тело цикла, затем выполняется булевское выражение, и если оно ложно, вновь выполняется тело цикла. Выход из цикла происходит, когда булевское выражение станет истинным. Явного перебора параметров в repeat не предусмотрено, поэтому изменение параметров осуществляется в теле цикла. Здесь же мы должны позаботиться , чтобы рано или поздно булевское выражение стало истиной. Замечания: 1.Тело оператора repeat выполняется по меньшей мере один раз. Оператор repeat еще называют циклом с послеусловием. 2. Перед until ';' не ставится. Пример: найти сумму четных чисел в интервале от 0 до 100. Program Prim17; Var i,s:integer; BEGIN i:=0; s:=0; repeat i:=i+2; s:=s+i until i>100; writeln('s=',s); readln; END. Пример: найти ток в цепи переменного тока в зависимости от частоты тока. Известно, что при последовательном соединении активной, емкостной и индукционной нагрузок сила тока может быть вычислена по формуле Пусть U = 220, R = 100, L = 0.57, С = 3.210-3, Fначальное=10; F будем менять с шагом 0.5. Печатать все результаты. Результаты, когда i3, нас не интересуют. Program Prim18; Var i,r,f,l,c,u:real; BEGIN writeln(' введите значения u r l c'); readln(u,r,l,c); f:=50; repeat i:=u/sqrt(sqr(r)+sqr(2*pi*f*l-1/(2*pi*f*c))); f:=f-1; writeln('f=',f,' i=',i) until i>3; readln; END.
4.3. Оператор While Оператор While цикла с предусловием. While - булевское выражение; do - тело цикла. Работа оператора. Вначале вычисляется булевское выражение, и если оно истинно, то выполняется тело цикла; если оно ложно, то происходит выход из цикла. Тело цикла - один оператор, как правило, составной. Мы должны позаботиться о том, чтобы булевское выражение в теле цикла на каком-то этапе стало ложным, иначе цикл никогда не закончится. Цикл можно сделать умышленно бесконечным, написав: while true do оператор; Мы будем применять эту конфигурацию при написании программ обработки файлов. Пример: найти сумму четных чисел в интервале от 0 до 100. Program Prim19; Var i,s:integer; BEGIN i:=0; s:=0; while i<100 do Begin i:=i+2; s:=s+i; end; writeln('s=',s); readln; END. Пример: в цепи переменного тока найти ток в зависимости от его частоты. Program Prim20; Var i,r,f,l,c,u:real; BEGIN writeln('введите значения u,r,l,c'); readln(u,r,l,c); f:=50; while i<3 do Begin i:=u/sqrt(sqr(r)+sqr(2*pi*f*l-1/(2*pi*f*c))); f:=f-1; writeln('f=',f,' i=',i); end; writeln('i>3, i=',i); readln; END.
4.4. Вложенные циклы Поскольку тело любого цикла состоит из операторов или составного оператора, то ничто не помешает в теле цикла располагать другие операторы цикла. Рассмотрим работу программы: Program Prim21; Var i,j:integer; BEGIN for i:=1 to 5 do Begin writeln; for j:=20 to 23 do write('i=',i,' j=',j); end; readln; END. Для цикла for i:=1 to 5 do телом цикла является begin for j:=20 to 23 do write(' i= ', i, ' , j = ', j); writeln; end; Назовем этот цикл внешним. Кроме того, имеется внутренний цикл for j: = 20 to 23 do с телом write (' i = ', i , j =', j); Работа программы. Вначале машина встречает внешний цикл и начинает его выполнять: присваивает i=l, затем переходит к его телу, а здесь встречает внутренний цикл и присваивает j значение 20, после чего выполняет тело внутреннего цикла, т.е. выводит на экран i=l, j=20. Так как внутренний цикл еще не окончен, то машина продолжает его выполнять, т.е. присваивает j значение 21 и добавляет к уже выведенной строке i=l, j=21.
Страницы: 1, 2, 3, 4, 5, 6, 7
|