КАЛИНИНГРАДСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ
С.А. Григорьев, С.А. Ишанов
СРАВНИТЕЛЬНЫЙ КУРС ЯЗЫКОВ ПРОГРАММИРОВАНИЯ FOR...
175 downloads
321 Views
609KB Size
Report
This content was uploaded by our users and we assume good faith they have the permission to share this book. If you own the copyright to this book and it is wrongfully on our website, we offer a simple DMCA procedure to remove your content from our site. Start by pressing the button below!
Report copyright / DMCA form
КАЛИНИНГРАДСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ
С.А. Григорьев, С.А. Ишанов
СРАВНИТЕЛЬНЫЙ КУРС ЯЗЫКОВ ПРОГРАММИРОВАНИЯ FORTRAN И С
Калининград 1998
3
КАЛИНИНГРАДСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ
С.А. Григорьев, С.А. Ишанов
СРАВНИТЕЛЬНЫЙ КУРС ЯЗЫКОВ ПРОГРАММИРОВАНИЯ FORTRAN И С Учебное пособие
Калининград 1998
4
УДК 681.3. 06 Григорьев С.А., Ишанов С.А. Сравнительный курс языков программирования Fortran и С: Учебное пособие / Калинингр. ун-т; Калининград, 1998. - 94 с. - ISBN 5-88874-097-7. Учебное пособие написано на основе курса лекций “Языки программирования и методы трансляции” и спецкурса “Язык программирования C”, читавшихся авторами на математическом факультете КГУ. Пособие содержит достаточно полное описание языков С и Fortran и сравнение основных конструкций этих языков, а также языка Pascal. Отдельная глава посвящена решению практических задач на языках С, Fortran и Pascal. Учебное пособие предназначено для студентов-математиков и студентов других специальностей, углубленно изучающих программирование.
Рецензент: к.ф.-м.н., доцент кафедры прикладной математики Калининградского государственного технического университета В.М. Смертин.
Печатается по решению редакционно-издательского Совета Калининградского государственного университета.
ISBN 5-88874-097-7 ный университет, 1998
©
Калининградский государствен-
5
Сергей Анатольевич Григорьев, Сергей Александрович Ишанов СРАВНИТЕЛЬНЫЙ КУРС ЯЗЫКОВ ПРОГРАММИРОВАНИЯ FORTRAN И С Учебное пособие Лицензия № 020345 от 14.01.1997 г. Редактор Л.Г. Ванцева. Оригинал-макет Д.В. Голубина. Подписано в печать 25.05.1998 г. Формат 60×90 1/16. Бумага для множительных аппаратов. Ризограф. Усл. печ. л. 5,9. Уч.-изд. л. 6,5. Тираж 120 экз. Заказ . Калининградский государственный университет, 236041, г. Калининград, ул. А. Невского, 14 СОДЕРЖАНИЕ 6
Введение ......................................................................................................... 5 Глава 1. Описание языка C ......................................................................... 5 1.1. Структура C-программы .......................................................................... 5 1.2. Скалярные типы данных и константы, строковые константы ............... 6 1.3. Описание скалярных переменных. Директива #define ........................... 7 1.4. Операции. Выражения ............................................................................. 8 1.5. Стандартные математические функции ................................................ 10 1.6. Ввод-вывод ............................................................................................. 10 1.7. Метки, оператор goto, условные конструкции, оператор break, функция exit ............................................................................................. 14 1.8. Циклические конструкции ..................................................................... 16 1.9. Указатели, адресная арифметика .......................................................... 17 1.10. Массивы ................................................................................................ 18 1.11. Функции ................................................................................................ 19 1.12. Классы памяти. Общие правила описания. Оператор typedef ........... 23 1.13. Строковые переменные, ввод-вывод строк, стандартные функции обработки строк. Функции проверки символов .................................. 25 1.14. Макроопределения ............................................................................... 28 1.15. Внешние файлы .................................................................................... 30 1.16. Структуры, объединения, битовые поля ............................................. 31 1.17. Динамическое распределение памяти ................................................. 33 1.18. Графика ................................................................................................. 34 1.19. Дополнительные возможности языка: тип enum, использование командной строки, функции с переменным числом параметров, средства консольного ввода-вывода, системное время, случайные числа ...................................................................................................... 35 Глава 2. Описание языка FORTRAN ....................................................... 38 2.1. Структура FORTRAN-программы ......................................................... 38 2.2. Типы данных. Константы ...................................................................... 39 2.3. Описание переменных, правила умолчания, операторы IMPLICIT, DATA, PARAMETER ......................................................... 40 2.4. Оператор присваивания. Операции ....................................................... 41
7
2.5. Стандартные математические функции ................................................ 42 2.6. Ввод-вывод ............................................................................................. 46 2.7. Оператор СОNTINUE. Операторы перехода. Условные операторы ... 49 2.8. Операторы цикла .................................................................................... 51 2.9. Функции LOC, LOCFAR, LOCNEAR .................................................... 52 2.10. Массивы ................................................................................................ 52 2.11. Подпрограммы SUBROUTINE, FUNCTION и INTERFACE ............. 54 2.12. Общие области, подпрограмма BLOCK DATA. Оператор EQUIVALENCE .................................................................... 56 2.13. Символьные переменные ..................................................................... 57 2.14. Операторные функции ......................................................................... 59 2.15. Внешние файлы .................................................................................... 59 2.16. Структуры ............................................................................................. 62 2.17. Динамические массивы ........................................................................ 63 2.18. Графика ................................................................................................. 63 2.19. Дополнительные возможности языка: дополнительные точки входа, свободный формат, строки отладки, средства консольного ввода-вывода, системное время, случайные числа ............................. 67 Глава 3. Решение задач на языках C и FORTRAN ................................ 70 Задача 1. Вывод натурального числа ........................................................... 70 Задача 2. Сумма ряда .................................................................................... 71 Задача 3. Медленная сортировка .................................................................. 72 Задача 4. Быстрая сортировка ...................................................................... 74 Задача 5. Слова .............................................................................................. 77 Задача 6. График ........................................................................................... 81 Задача 7. Кубическое уравнение .................................................................. 85 Задача 8. Собственное число ........................................................................ 89 Комментарии к задачам ................................................................................ 91
8
ВВЕДЕНИЕ Эта книга состоит из трех глав. Первые две представляют собой краткие описания языков программирования C и FORTRAN 77, а в третьей главе приведены решения некоторых часто встречающихся задач на этих двух языках и на языке PASCAL. Авторы предполагают, что читатели этой книги уже в достаточной мере знакомы с языком программирования PASCAL, и в ряде мест ссылаются на соответствующие конструкции этого языка. Но владение языком PASCAL не является абсолютно необходимым для пользования этой книгой, читатель должен иметь лишь некоторое представление о языках программирования высокого уровня, поскольку из-за ограниченного объема книги авторы вынуждены излагать материал очень лаконично. Тем, кого интересует только один из представленных языков, можно порекомендовать читать только первую или только вторую главу. Глава 1. ОПИСАНИЕ ЯЗЫКА C Приведенное ниже описание языка C полностью соответствует среде программирования Borland C++ версий 2.0 и 3.0. Многие программисты предпочитают пользоваться языком C++, который является расширением языка C. Оба языка в основном используют один и тот же синтаксис, операторы, выражения, встроенные типы данных, структуры, массивы, объединения, циклы, функции и указатели. Основные расширения языка С++ также описаны и специально оговорены в тексте главы. 1.1. Структура C-программы С-программа размещается в одном или нескольких файлах. Она состоит из оболочки, включающей описания и директивы препроцессора, и одной или нескольких функций. Одна из функций всегда имеет имя main, с нее начинается выполнение программы. Функция состоит из заголовка функции: тип имя ([список параметров])
и тела функции. Тело функции - это блок (последовательность операторов в фигурных скобках). Символы {} в языке С являются логическими скобками. Список параметров может быть пустым, но ( ) должны присутствовать и в этом случае. Для функций, не имеющих параметров, можно указывать список параметров в виде (void) . Если список параметров не пуст, то для каждого параметра указывается его тип. Если функция не должна воз9
вращать никакого значения, то ее тип - void ("пустой" тип). В языке С нет понятия процедуры. Каждый оператор заканчивается символом ; . Идентификаторы могут иметь длину до 31 символа, компилятор различает большие и малые латинские буквы, откуда, в частности, следует, что написание Main или MAIN имени главной функции является ошибкой. Комментарии заключаются в составные символы /* */ . В языке С++ появился еще один вид комментариев: так называемый однострочный комментарий - строка, начинающаяся парой символов // . Директивы препроцессора начинаются с символа # и записываются в отдельной строке, они могут располагаться в любом месте программы, но не внутри функции. Директивы действуют от места появления до конца файла или до их отмены. Препроцессор языка С - это программа, которая, обрабатывая исходный текст до компилятора, выполняет подстановки для макровызовов, осуществляет условную компиляцию, подключает необходимые файлы. Директива #include или #include"файл" присоединяет к программе внешний файл, "" означают поиск файла в текущем каталоге (пользовательский файл), а - поиск в системном каталоге (системный файл). Директиву #include следует использовать в любой программе, вызывающей внешние функции, для подключения т.н. заголовочных файлов - файлов с расширением h (header). В заголовочных файлах содержатся описания (прототипы) функций, необходимые для успешной компиляции программы. 1.2. Скалярные типы данных и константы, строковые константы В языке С определены следующие арифметические типы данных: Тип данных char unsigned char int unsigned long float double
Размер 1 байт 1 байт 2 байта 2 байта 4 байта 4 байта 8 байтов
Диапазон значений от -128 до +127 от 0 до 255 от -32768 до +32767 от 0 до 65535 от -2147483648 до +2147483647 от ± 3.4Е-38 до ±3.4Е+38 (7 верных цифр) от ±1.7Е-308 до ±1.7Е+308 (16 верных цифр)
Все арифметические типы данных имеют аналогии в языке PASCAL: char=ShortInt, unsigned char=Byte, int=Integer, unsigned=Word, long=LongInt, float=Single, double=Double. Целые константы можно запи10
сывать в десятичном, восьмеричном и шестнадцатеричном виде, например, 255 или 0377, или 0XFF. Константа, начинающаяся цифрой 0, считается восьмеричной, а константа, начинающаяся символами 0X или 0x, - шестнадцатеричной. По умолчанию десятичные целые константы имеют тип int, константы типов unsigned и long образуются добавлением справа буквы U (u) или L (l) : -1L, 65535U . Вещественные константы записываются в виде с фиксированной точкой: -2. , 1.3 , .45, или с плавающей точкой: -2e-2, 1.33e0 - и по умолчанию имеют тип double. Константы типа float образуются добавлением справа буквы F (f) : -2.f, 1.22e0f . Символьные константы (они являются в языке C целыми числами и имеют тип int) записываются в одном из четырех видов: - ' символ ' ( например, '!' ) - ' \8-ричная константа ' ( например, '\041' ) - ' \x одна или две 16-ричные цифры ' ( например, '\x21' ) - специальные символы '\a' - звук, '\b' - backspace, '\t' - горизонтальная табуляция, '\n' - новая строка, '\v' - вертикальная табуляция, '\f' - новая страница, '\r' - возврат каретки, '\\' - символ \, '\''- апостроф, '\”' - кавычка, '\%' - символ %. Строковые константы задаются в виде “символы”, в т.ч. могут содержать и специальные символы, например : "abcdef..." или "\n\a\n\t\\\b" . Символы \,'," и в ряде случаев % являются специальными управляющими символами в языке C и не должны входить в строки непосредственно, но лишь в виде составного символа. Компилятор языка C всегда соединяет строковые константы, не разделенные в тексте программы ничем, кроме пробелов. 1.3. Описание скалярных переменных. Директива #define Переменные описываются и инициализируются в виде: тип имя [ = выражение ] , имя [ = выражение] , ... ; Например: int a,b='\020',c=-11; long d=-1L; double e,f=.003,g=1.2E40; Каждая переменная, использованная в программе, должна быть явно описана. Инициализация переменных не является обязательной. Все переменные должны быть описаны раньше, чем будут использоваться. Язык С требует, чтобы все описания локальных переменных внутри блока помещались перед первым исполняемым оператором. В С++ можно описывать переменные в любой точке блока перед их использованием. 11
Простейшая форма директивы препроцессора #define используется для определения символических констант: #define имя строка_замещения Строка замещения, вообще говоря, есть любая последовательность символов. Препроцессор до начала компиляции замещает каждое вхождение имени константы в тексте программы на строку замещения, но только не внутри "". Строка замещения может быть, например, числовой константой: #define PI 3.141592653589793 , тогда идентификатор PI можно рассматривать как именованную константу в языке PASCAL (хотя это и не тождественные вещи). У пользователей языка С существует традиция записывать имена символических констант заглавными буквами, хотя это никак не регламентируется в самом языке. 1.4. Операции. Выражения В языке С определены следующие операции: a) арифметические операции: унарный +, унарный -, сложение +, вычитание - , умножение *, деление /, остаток от деления %, инкремент ++, декремент --. Операция / определена как для вещественных операндов, так и для целых, но для целых операндов результат всегда целый и равен целой части частного. Инкрементная и декрементная операции применимы только к переменным, выражение x++ эквивалентно выражению x=x+1 . Возможны постфиксная и префиксная формы этих операций. При использовании префиксной формы значение переменной изменяется до его подстановки в выражение, а при использовании постфиксной формы - после вычисления выражения. Например, пусть переменная x описана как int x=5; тогда значение выражения ++x*2 будет равно 12, а значение выражения x++*2 равно 10, значение переменной в обоих случаях станет равным 6. б) операции сравнения: равно == , не равно != , больше > , больше либо равно >= , меньше < , меньше либо равно 3 при x=0 не произойдет ошибки, т.к. выражение 1/x не будет вычисляться. г) операция sizeof: sizeof ( тип ) или sizeof выражение . Результат операции - размер объекта в байтах, тип результата всегда unsigned. В языке PASCAL эта операция реализована встроенной функцией SizeOf. д) операция явного преобразования типа: ( тип ) выражение Если операнды некоторого выражения имеют разный тип, то они автоматически приводятся к одному (старшему) типу. Старшинство типов возрастает в такой последовательности : char < unsigned char < int < unsigned < long < float < double . е) битовые операции: побитовое отрицание ~ , побитовое "и" & , побитовое исключающее "или" ^ , побитовое "или" | , сдвиг битов влево > . Битовые операции применимы только к целым операндам, все они имеют аналоги в языке PASCAL : ~ = NOT, & = AND, ^ = XOR, | = OR, > = ShR. ж) операции присваивания: в отличие от языка PASCAL в языке С конструкция, состоящая из двух операндов и операции присваивания, является выражением, его значение равно значению, полученному переменной в левой части выражения. Кроме обычной операции присваивания = существует еще 10 операций: += , =, *= , /= , %= , = , &= , ^= , |= , смысл которых очевиден из простейшего примера : x+=a означает x=x+a . з) операция адрес: & переменная Эта унарная операция применима только к переменным, ее аналог в языке PASCAL - операция @. и) операция "запятая" - довольно необычная операция, имеющаяся только в языке C. Несколько выражений, разделенных запятыми, вычисляются последовательно слева направо. В качестве результата сохраняются тип и значение самого правого выражения. Приоритеты операций определены следующим образом: унарные операции > {*, /, %} > {+, -} > {} > {>, >=, & > ^ > | > && > || > операции присваивания > операция "запятая". Операции одного приоритета выполняются в последовательности слева направо, кроме унарных операций и операций присваивания, которые вы13
полняются справа налево. Для того чтобы изменить порядок выполнения операций, в выражении используются круглые скобки. 1.5. Стандартные математические функции Библиотека математических функций (прототипы функций содержатся в файле math.h) включает : int abs(int x) long labs(long x) double fabs(double x) double ceil(double x) double floor(double x) double fmod(double x,double y) double sqrt(double x) double hypot(double x,double y) double ldexp(double x,int n) double pow(double x,double y) double pow10(int p) double exp(double x) double log(double x) double log10(double x) double sin(double x) double cos(double x) double tan(double x) double asin(double x) double acos(double x) double atan(double x) double atan2(double x,double y) double sinh(double x) double cosh(double x) double tanh(double x)
- |x| для int - |x| для long - |x| для double - наименьшее целое, не меньшее x - наибольшее целое, не большее x - остаток от деления x на y - √x - √(x2 +y2 ) - x⋅2n - xy - 10p - ex - ln(x) - log(x) - sin(x) - cos(x) - tg(x) - arcsin(x) - arccos(x) - arctg(x) - arctg(y/x), возвращает значение от-π до π - sh(x) - ch(x) - th(x)
1.6. Ввод-вывод Форматный вывод данных осуществляется функцией printf : int printf ( строка формата [ , список вывода ] ) которая возвращает количество выведенных символов. Список вывода может содержать любые выражения, разделенные запятыми (полностью аналогичен списку вывода оператора WRITE в языке PASCAL). Строка формата заключается в “ “ и может содержать : 1) обычные символы, которые просто выводятся на экран;
14
2) специальные символы, управляющие размещением данных на экране; 3) элементы формата данных. Для вывода строки на экран элементы формата можно не использовать, в этом случае список вывода пуст : printf("\n\tВыведем что-нибудь...\a"); Элемент формата представляет собой последовательность : % [ - ] [ длина поля ] [ . точность ] [ l ] спецификация типа “ - “ означает сдвиг выводимых данных к левому краю поля ( по умолчанию данные сдвигаются вправо); длина поля - количество позиций для вывода; точность - количество дробных цифр для чисел или количество выводимых символов строки для строк; “ . ” - разделитель; l - означает, что число должно рассматриваться как long или double. Могут использоваться следующие спецификации типов : d,i - для данных типа int; u - для данных типа unsigned; o - для данных типа unsigned (выводятся в восьмеричном виде); x,X - для данных типа unsigned (выводятся в шестнадцатеричном виде), шестнадцатеричные цифры A,B,C,D,E,F изображаются большими буквами при использовании типа X и малыми буквами при использовании x; c - для данных типа char, unsigned char (выводятся в символьном виде); f - для данных типа float,double (выводятся в виде с фиксированной точкой, по умолчанию выводится 6 дробных цифр); e,E - для данных типа float,double (выводятся в виде с плавающей точкой, по умолчанию выводится 7 цифр мантиссы и две цифры порядка, всего 13 позиций), отличаются изображением буквы E; g,G - для данных типа float,double - величины 0.0001 '); PrintComplex(d);WriteLn(' = 0'); END; WriteLn('Нажмите Enter'); ReadLn; END. /*Решение задачи 7 на языке С*/ #include<math.h> #include<stdio.h> #include struct s_complex{double Re,Im;}; typedef struct s_complex complex; complex ComplexRoot2(double x) { complex x_1_2; if(x>=0){x_1_2.Re=sqrt(x); x_1_2.Im=0;} else{x_1_2.Re=0; x_1_2.Im=sqrt(fabs(x));}return x_1_2;} complex ComplexAdd(complex x1,complex x2) {complex y; y.Re=x1.Re+x2.Re; y.Im=x1.Im+x2.Im; return y;} complex ComplexRoot3(complex x){complex x1_3; double z,f; z=sqrt(pow(x.Re,2)+pow(x.Im,2)); f=atan2(x.Im,x.Re); if(z) z=pow(z,1./3); x1_3.Re=z*cos(f/3); x1_3.Im=z*sin(f/3); return x1_3;} complex ComplexMult(complex x1,complex x2){complex y; y.Re=x1.Re*x2.Re-x1.Im*x2.Im; y.Im=x1.Re*x2.Im+x1.Im*x2.Re; return y;} int Min3(double x1,double x2,double x3) {if(x1<x2)if(x1<x3)return 1;else return 3; else if(x2<x3)return 2;else return 3;} void PrintComplex(complex x){ printf("%10.5f",x.Re); if(x.Im>0)printf("+%7.5fi",x.Im);else printf("%8.5fi",x.Im);} void main(void) { double a,b,c,p,q,Q; int i,j; complex A,B,Q1_2,Tmp,Tmp1, Tmp2,y[3],x[3],d,One_1_3_p={-.5,.5},One_1_3_m={-.5,-.5}; One_1_3_p.Im*=sqrt(3); One_1_3_m.Im*=sqrt(3); printf("\nВведите коэффициенты a,b,c "); scanf("%lg%lg%lg",&a,&b,&c); p=-a*a/3+b; q=2*pow(a/3,3)-a*b/3+c; Q=pow(p/3,3)+pow(q/2,2); Q1_2=ComplexRoot2(Q); A.Re=Q1_2.Re-q/2; A.Im=Q1_2.Im; B.Re=-Q1_2.Re-q/2; B.Im=-Q1_2.Im; A=ComplexRoot3(A); B=ComplexRoot3(B); Tmp=ComplexMult(A,B); switch(Min3(fabs(p/3+Tmp.Re), fabs(p/3-Tmp.Re/2-sqrt(3)*Tmp.Im/2), 91
fabs(p/3-Tmp.Re/2+sqrt(3)*Tmp.Im/2))){ case 2:A=ComplexMult(A,One_1_3_p); break; case 3:A=ComplexMult(A,One_1_3_m);} y[0]=ComplexAdd(A,B); Tmp1.Re=(A.Re+B.Re)/2; Tmp1.Im=(A.Im+B.Im)/2; Tmp2.Re=A.Re-B.Re; Tmp2.Im=A.Im-B.Im; Tmp.Re=0; Tmp.Im=sqrt(3)/2; Tmp2=ComplexMult(Tmp,Tmp2); y[1].Re=-Tmp1.Re+Tmp2.Re; y[1].Im=-Tmp1.Im+Tmp2.Im; y[2].Re=-Tmp1.Re-Tmp2.Re; y[2].Im=-Tmp1.Im-Tmp2.Im; printf("\nКорни уравнения и контроль :\n"); for(i=0;i #include #include #include #include<math.h> #include void main(void){ double a,b,c,p,d1,d2,d3; int i,j; complex q,Q,tmp,A,B,y[3],x[3], One_1_3_p=complex(-.5,.5*sqrt(3)),One_1_3_m=complex(-.5,-.5*sqrt(3)); cout>c; p=-a*a/3+b; q=2*pow(a/3,3)-a*b/3+c; Q=pow(p/3,3)+pow(q/2,2); A=pow(-q/2+sqrt(Q),complex(1./3,0)); B=pow(-q/2-sqrt(Q),complex(1./3,0)); tmp=A*B; d1=fabs(p/3+real(tmp)); d2=fabs(p/3-real(tmp)/2-sqrt(3)*imag(tmp)/2); d3=fabs(p/3-real(tmp)/2+sqrt(3)*imag(tmp)/2); if(d2