Языки программирования В настоящее время в мире существует несколько сотен реально используемых языков программирования. Для каждого есть своя область применения. Любой алгоритм, есть последовательность предписаний, выполнив которые можно за конечное число шагов перейти от исходных данных к результату. В зависимости от степени детализации предписаний обычно определяется уровень языка программирования — чем меньше детализация, тем выше уровень языка. По этому критерию можно выделить следующие уровни языков программирования: машинные; машинно-оpиентиpованные (ассемблеpы); машинно-независимые (языки высокого уровня). Машинные языки и машинно-ориентированные языки — это языки низкого уровня, требующие указания мелких деталей процесса обработки данных. Языки же высокого уровня имитируют естественные языки, используя некоторые слова разговорного языка и общепринятые математические символы. Эти языки более удобны для человека. Каждый компьютер имеет свой машинный язык, то есть свою совокупность машинных команд, которая отличается количеством адресов в команде, назначением информации, задаваемой в адресах, набором операций, которые может выполнить машина и др. При программировании на машинном языке программист может держать под своим контролем каждую команду и каждую ячейку памяти, использовать все возможности имеющихся машинных операций. Но процесс написания программы на машинном языке очень трудоемкий и утомительный. Программа получается громоздкой, труднообозримой, ее трудно отлаживать, изменять и развивать. Поэтому в случае, когда нужно иметь эффективную программу, в максимальной степени учитывающую специфику конкретного компьютера, вместо машинных языков используют близкие к ним машинно-ориентированные языки (ассемблеры). Язык ассемблера — это машинно-зависимый язык низкого уровня, в котором короткие мнемонические имена соответствуют отдельным машинным командам. Используется для представления в удобочитаемой форме программ, записанных в машинном коде. Язык ассемблера позволяет программисту пользоваться текстовыми мнемоническими (то есть легко запоминаемыми человеком) кодами, по своему усмотрению присваивать символические имена регистрам компьютера и памяти, а также задавать удобные для себя способы адресации. Кроме того, он позволяет использовать различные системы счисления (например, десятичную или шестнадцатеричную) для представления числовых констант, использовать в программе комментарии и др. Программы, написанные на языке ассемблера, требуют значительно меньшего объема памяти и времени выполнения. Знание программистом языка ассемблера и машинного кода дает ему понимание архитектуры машины Для того, чтобы написать программу на языке ассемблера для конкретного компьютера, важно знать его архитектуру. В качестве примера приведем программу на языке ассемблера для IBM PC. Программа вычисляет значение a = b + c для целых a, b и c: .MODEL SMALL .DATA b DW 5 c DW 3 a DW ? .CODE begin MOV AX,@DATA MOV DS,AX MOV AX,B ADD AX,C MOV A,AX MOV AH,4CH INT 21H END begin Директива .MODEL задает механизм распределения памяти под данные и команды. Директива .DATA определяет начало участка программы с данными. Директивы DW задают типы переменных и их значения. Директива .CODE определяет начало участка программы с командами. Команды MOV AX,@DATA и MOV DS,AX записывают адрес сегмента данных в регистр DS (Data Segment). Для вычисления a используются команды MOV AX, B, ADD AX,C и MOV A,AX. В директиве END задана метка первой выполняемой программы программы begin. Перевод программы с языка ассемблера на машинный язык осуществляется специальной программой, которая называется ассемблером и является, по сути, простейшим транслятором. Языки высокого уровня были разработаны для того, чтобы освободить программиста от учета технических особенностей конкретных компьютеров, их архитектуры Алгоритмические языки в значительной мере являются машиннонезависимыми. Они облегчают работу программиста и повышают надежность создаваемых программ. Языки высокого уровня делятся на: процедурные (алгоритмические) (Basic, Pascal, C и др.), которые предназначены для однозначного описания алгоритмов; для решения задачи процедурные языки требуют в той или иной форме явно записать процедуру ее решения; логические (Prolog, Lisp и др.), которые ориентированы не на разработку алгоритма решения задачи, а на систематическое и формализованное описание задачи с тем, чтобы решение следовало из составленного описания; объектно-ориентированные (Object Pascal, C++, Java и др.), в основе которых лежит понятие объекта, сочетающего в себе данные и действия над нами. Программа на объектноориентированном языке, решая некоторую задачу, по сути описывает часть мира, относящуюся к этой задаче. Описание действительности в форме системы взаимодействующих объектов естественнее, чем в форме взаимодействующих процедур. Никлаус Вирт (Niklaus Wirth) род. 15.02.1934 (Швейцария) Автор языков: (1963) Euler (1966) Algol-W (1968) PL360 (1970) Паскаль (1976) Modula (1979) Modula-2 (1988) Оберон Язык Си Появление Си принято связывать с именем Дениса Ритчи, подготовившего в 1972 году первую версию этого языка в ходе работ над операционной системой UNIX для ЭВМ семейства PDP. Однако исторически его возникновение следует связывать с, во многом машиннозависимым, языком B, созданным Кеном Томпсоном на основе языка BCPL В настоящее время из 13000 строк системного кода UNIXа лишь 800 строк, выполняющих работу наиболее низкого уровня, написаны на языке ассемблера. Остальная же часть этой операционной системы и множество ее программных утилит написаны на Си Язык Си - это алгоритмический язык "не очень высокого уровня". Он проектировался для того, чтобы получить непосредственный доступ к объектам, которыми оперируют процессоры компьютера: разрядам, байтам, словам, адресам По этой причине, а также потому, что Си является блочноструктурированным языком, похожим на Алгол или Паскаль, он прекрасно подходит для системного программирования • В нем удачно сочетаются лучшие свойства ассемблера и языков высокого уровня. От ассемблера были взяты эффективные средства работы с оперативной памятью и регистрами микропроцессора, от языков высокого уровня - широкий набор управляющих конструкций, возможность работы со сложными структурами данных, гибкие средства ввода/вывода информации • Философия языка Си заключается в том, чтобы предоставить программисту максимальную свободу действий при написании программы, но возложить на него всю ответственность за возможные действия приводящие к краху • В языке Си имеется большой набор управляющих конструкций для реализации циклических и разветвленных алгоритмов, средства для блочного и модульного программирования, а также возможность гибкого управления процессом выполнения программы. Он очень удобен для обработки текстов, для технических приложений и моделирования Конечно, другие языки имеют свои специфические особенности, которые делают их во многих случаях более удобными. Но тем не менее язык Си стал очень популярным, им широко пользуются программисты и им он очень нравится Те, кто использует язык Си, приводят обычно следующие причины его популярности: программы на языке Си легче переносятся с одной ЭВМ на другую язык обеспечивает богатый набор операций для вычисления выражений и дает возможность обходиться без языка ассемблера даже при работе с битами программы компактны, н не настолько, чтобы не быть непонятными; язык Си удобен, его синтаксис достаточно прост "Американские ученые, проанализировав статистику боев с японцами во Второй мировой войне, обнаружили, что, несмотря на равенство сил, войска США побеждали чаще. Причину нашли в длине слов английского и японского языков. В английском языке средняя длина слова составляет пять букв, а в японском - тринадцать. То есть пока японцы еще ставили боевую задачу, американцы уже начинали стрелять... После этого в американской армии был введен обычай давать короткие названия (клички) как своей боевой технике, так и технике противника. Когда эта информация дошла до русских, то они вычислили среднюю длину слова в русском языке, которая оказалась равной семи буквам. Однако проведенные полевые исследования показали: в процессе управления боем командир автоматически переходит на мат и информативность речи возрастает в два-три раза". В экспериментах, проведенных под руководством Июаня Тана (Yiyuan Tang) в Даляне, люди, для которых родным языком был английский или китайский, складывали одинаковые числа (написанные арабскими цифрами). Ученые сравнивали с помощью магнитного резонанса процессы в мозге англоговорящих и китайскоговорящих людей при решении ими математических задач. Эти процессы оказались разными. Мысль о том, что структура языка может сузить горизонты мысли, натолкнула, в свою очередь, на противоположную идею, что язык может горизонты мысли и расширить. Психологи недавно провели эксперимент, показавший, что одну и ту же последовательность сцен (мультфильм) люди, говорящие на немецком и на английском языках, описывают по-разному: англичане выделяют в несколько раз больше эпизодов и описывают их как текущие действия (часто употребляя очень удобный для этого английский герундий), носители немецкого языка выделяют эпизоды более длинные и приводящие к какому-то результату [Величковский Б.М., Когнитивная наука. В 2-х. т.. - М.:, Смысл, 2006] (вспомним, что существительные в немецком языке пишутся с заглавной буквы). Выбирая в качестве языка международного общения английский, мы предрешаем кое-что в содержании наших знаний, по-видимому, утрачивая какие-то возможности, доступные при ином выборе. Но нынче разумно учить английский - поскольку он наиболее употребителен. Подготовка к выполнению и выполнение программ Язык Си относится к числу компилируемых языков программирования. Это означает, что подготовка к выполнению Сипрограммы включает в себя следующие этапы: 1. 2. 3. ввод исходного текста программы в файл при помощи какого-либо редактора текстов (имя файла, как правило, имеет стандартное расширение "C " для Си и "CPP" для С++) компиляция программы, т.е. преобразование ее описания на входном языке в семантический эквивалент на машинном языке, называемый объектным модулем (имя файла, в который помещается результат компиляции, обычно имеет расширение "OBJ") построение готового к выполнению загрузочного модуля из объектных модулей, включая модули из внешних библиотек (файл, содержащий готовую программу, имеет имя с расширением "EXE") В процессе компиляции программы создается листинг ее исходного текста, содержащий, возможно, сообщения об обнаруженных ошибках. Наличие листинга существенно упрощает поиск и устранение ошибок, допущенных при подготовке программы, и сокращает время, затрачиваемое на ее отладку. Имя файла, в который записывается листинг исходной программы, снабжается обычно расширением "LST". При наличии ошибок необходимо вернуться на этап редактирования, исправить ошибки и заново откомпилировать программу На этапе построения загрузочного модуля также возможно создание файла-листинга, включающего в себя информацию о размещении собираемых объектных модулей в памяти компьютера. Однако его анализ и использование требует более глубоких знаний основных принципов работы машины, нежели разбор листинга исходной программы Для запуска в работу готовой к выполнению программы в операционной среде MS DOS достаточно набрать имя содержащего ее файла на клавиатуре консольного терминала, закончив ввод нажатием клавиши Enter После этого необходимо проверить правильность работы программы То, что программа правильно откомпилировалась не гарантирует правильность реализации заложенного алгоритма работы Основной путь - проверка на тестовых примерах Однако правильность выполнения тестового примера все равно не гарантирует отсутствие ошибок При нахождении ошибок в программе необходимо вернуться к начальному редактированию текста, компилированию, сборке и т.д. Такой процесс называется отладкой (дебаггинг - ловля блох) 9 сентября 1945 г. ученые Гарвардского университета, тестирующие машину Mark II Aiken Relay Calculator, нашли мотылька, застрявшего между контактами электромеханического реле. Извлеченной насекомое было вклеено в технический дневник, с сопроводительной записью: "First actual case of bug being found". Название "баг" прижилось. В настоящее время реликвия хранится в одном из музеев США Первая программа Единственный способ научиться языку программирования - писать на нем программы Чтобы это сделать надо: создать каким-либо образом текст программы успешно его оттранслировать загрузить, выполнить разобраться что получилось Этапы создания программы На каждом из этапов используется своя программа Текстовый редактор Транслятор Сборщик Отладчик Существует очень много подобных программ. Для удобства все эти программы объединяются в интегрированные среды. Borland, Microsoft Visual и т.п. Мы будем использовать свободно распространяемую систему Bloodshed Dev-C++ Пример системы Всякая программа на языке Си представляет собой совокупность функций, выполняющих основную работу по реализации некоторого алгоритма Каждая из этих функций, в свою очередь, есть независимый набор описаний и операторов, заключенных между заголовком функции и ее концом Та функция, с которой начинается выполнение программы, называется главной функцией. Она должна иметь предопределенное имя main( ) Самая простая программа напечатать какие-либо слова. Эта первая программа, которую пишут на всех языках Эта программа выглядит так void main( ) { printf("HELLO", World \n); } Пример программы Другой вариант void main() { printf("HELLO,"); printf(" World"); printf("\n"); } Пример программы Следующая программа печатает таблицу температур по Фаренгейту и их эквивалент по Цельсию. Для перевода используется формула c=(5/9)(F-32) /* печать таблицы */ /* для f = 0,20,40,...,300*/ void main() { int lower, upper, step; float fahr, celcius; lower = 0; upper = 300; step =20; fahr = lower; while (fahr <= upper) {celcius = (5.0/9.0)*(fahr -32.0); printf(“%4.0f %6.1f \n”, fahr, celcius); fahr = fahr + step; } } Пример программы В Си все переменные должны до их использования описываться В операторе printf( ) спецификация %4.0f указывает, что нужно печатать число с плавающей точкой из 4 позиций без цифр после десятичной точки. %6.1f - число занимает по крайней мере 6 позиций и после точки есть одна цифра. Части спецификаций можно опускать %6f - по крайней мере 6 позиций %.2 - 2 точки после запятой, а общее число цифр не ограничивается %f - печатать число с плавающей запятой В printf() предусмотрены %d - для десятичных целых %o - для восьмеричных %x - для шестнадцатеричных %c - для символов %s - для символьных строк %% - для самого символа % Функция printf( ) не входит в сам язык Си (в Си ввод и вывод не определены). Для ввода используется функция scanf() Изменим программу вычислений градусов по Фаренгейту: void main( ) { int fahr; for (fahr = 0; fahr <= 300; fahr = fahr + 20) printf(“%4d %6.1f \n”, fahr, (5.0/9.0)*(fahr-32)); } Пример программы Эта программа дает тот же результат Плохо если в программе встречаются загадочные цифры вроде 300 или 20 В Си с помощью конструкций #define можно ввести символическую константу. Везде потом транслятор заменит вхождение имени константы на соответствующую строку #define LOWER #define UPPER #define STEP main() { int fahr; for (fahr = printf(“%4d } 0 300 20 LOWER; fahr <= UPPER; fahr=fahr+STEP) %6.1f \n”,fahr,(5.0/9.0)fahr-32)); LOWER, UPPER, STEP - константы, поэтому в описании они не появляются. Символические имена констант обычно записывают заглавными буквами, чтобы отличать их от переменных В конце описания нет точки с запятой. Так как подставляется вместо имени вся строчка, и оказалось бы в операторе for слишком много запятых Модульное программирование, компоновка Полученный в результате трансляции объектный модуль включает в себя готовые к выполнению коды команд, адреса и содержимое памяти данных. Но это касается только собственных внутренних объектов программы (функций и переменных). Обращение к внешним функциям и переменным, отсутствующим в данном фрагменте программы, не может быть полностью переведено во внутреннее представление и остается в объектном модуле в исходном (текстовом) виде. Но если эти функции и переменные отсутствуют, значит они должны быть каким-то образом получены в других объектных модулях. Самый естественный способ - написать их на том же самом Си и оттранслировать. Это и есть принцип модульного программирования - представление текста программы в виде нескольких файлов, каждый из которых транслируется отдельно. С модульным программированием мы сталкиваемся в двух случаях: - когда сами пишем модульную программу; - когда используем стандартные библиотечные функции. БИБЛИОТЕКА ОБЪЕКТНЫХ МОДУЛЕЙ - это файл (библиотечный файл), содержащий набор объектных модулей и собственный внутренний каталог. Объектные модули библиотеки извлекаются из нее целиком при наличии в них требуемых внешних функций и переменных и используются в процессе компоновки программы. КОМПОНОВКА -это процесс сборки программы из объектных модулей, в котором производится их объединение в исполняемую программу и связывание вызовов внешних функций и их внутреннего представления (кодов), расположенных в различных объектных модулях. Источником объектного модуля может быть не только Сипрограмма, но и программа, написанная на любом другом языке программирования, например, на Ассемблере. В этом случае необходимы дополнительные соглашения по поводу "стыковки" вызовов функций и обращений к данным в различных языках.