Западно-Казахстанский государственный университет им. М.Утемисова «Утверждаю» Декан естественно-математического факультета _________ Медешова А.Б. «__»_____________ 20__г. УЧЕБНО-МЕТОДИЧЕСКИЙ КОМПЛЕКС ПО ДИСЦИПЛИНЕ «Решение задач на языке программирования Си» по кредитной технологии обучения для студентов III курса специальности 050111- Информатика Курс Семестр Лекции Лабораторные занятия СРСП СРС Экзамен Всего 3 6 15 ч. 15 ч. 30 ч. 30 ч. 6 семестр 90 ч. Уральск 2010 Программа курса составлена ст. преподавателем Акимовой С.М. на основании типовой программы по информатике для специальности 050602 приказ МОН и РК от 11 мая 2003 г. № 289 Рассмотрена на заседании кафедры Протокол № от « » 20___ г. Зав. кафедрой ______________ Уланов Б.В. Утвержден на заседании учебно-методического совета естественно-математического факультета Протокол № ___ от «___»__________ 20__ г. Председатель УМС ______________ 2 1. Типовая учебная программа дисциплины составлена согласно ГОСО РК 3.08.260-2006 специальности 050111 – Информатика Кафедра физики, математики и информатики, каб.№ 307, корпус №1 2. Программа обучения по дисциплине – SYLLABUS Данные о преподавателе: Акимова Сауле Муратовна –преподаватель Офис: корпус №1 ауд. 307 Данные о дисциплине «Решение задач на языке программирования Си» График занятий: Семестр состоит из 15 учебных недель и 2 недель сессии. В неделю предполагается 2 кредит часа, каждый кредит – час состоит из одного контактного часа (лекция, Практическое занятие) и двух часов самостоятельной работы студентов под руководством преподавателя (СРСП, СРС). Распределение кредита на неделю: Занятия 1. Контактный час (лекция) Время проведения 50 мин Занятия СРСП (прак. зан) Время проведения 50 мин 50 мин СРСП (прак. зан) 50 мин 2. Контактный час (практическое знаятие) Количество кредитов -2; Место проведения: по расписанию Выписка из учебного плана: Курс 3 Семестр 6 Кредиты Лекции Лабораторные 2 15 15 СРСП 30 СРС Всего 30 90 Форма контроля отчет Цели и задачи курса Введение: Студенты, обучающиеся по специальности информатика, шифр 050111, при изучении дисциплины «Языки программирования» знакомятся с языком программирования Turbo Pascal. Далее в курс обучения в график дисциплин, с которыми обязаны познакомиться студенты, обучающиеся по специальности «Информатика», включен и язык программирования СИ. Данный язык относится к языкам структурированного типа. Достоинством данного языка является переносимость, мощность, популярность и развитие. Однако одним из основных недостатков данного языка является сложность в изучении языка, а также жесткая структура построения программ. Данный язык широко применяется для создания системных программ и в коммерческих целях. В курсе обучения предусмотрено следующее: переменные, их описание, выражения, константы, алфавит, специальные символы, используемые при работе в языке Си, а также знакомство с работой меню, с основными управляющими клавишами, использование операторов ввода-вывода, организация программ линейных, условных, циклических , все это студенты изучают в специальном курсе. Данный этап обучения предусматривает знание основных положений языка Си и поэтому обучение направлено на усиленное изучение массивов: одномерные, двумерные, динамические, а также изучение особенностей работы со строковыми данными, организацией работы с подпрограммами, создание простых, графических изображений, а также создание и применение файлов в языке Си. Возможности этого языка очень большие, поэтому для более полного изучения языка Си необходимо дополнительное время, для этого студенты, при желании могут изучать дополнительные возможности на СРС или СРСП. Цель курса: С развитием вычислительной техники усовершенствуются и языки программирования, сегодня большой популярностью пользуются языки объектно-ориентированного программирования. Задача, которую следует ставить при первоначальном изучении программирования – освоение методики программирования. Для указанной цели наиболее подходящим является язык программирования Паскаль, который студенты изучали на первом курсе. Структурная методика остается основой программисткой культуры. Познакомившись с основами структурного программирования, студенты смогут быстро и эффективно изучить и язык программирования Си, опираясь на знания и умения, полученные при изучении Паскаля. Целью данного курса является обучение формальным способам описание языка Си, типов данных, способов и механизмам управления данными, методов и основных этапов трансляции. Задачи курса: 3 Знание языка Си необходимо студентам, обучающимся по специальностям, связанных с информатикой. Данный язык позволяет создавать не просто программы, а и создавать операционные системы, т.к. язык Си является языком системного программирования. Студенты, изучающие данный курс, знакомятся с основами программирования в Си, и они должны научиться реализовывать алгоритмы в программный продукт. Задачей курса «Языки программирования» является овладение знаниями теории языка программирования Си и практическая реализация этих знаний на ЭВМ. Содержание курса: С основами программирования на языке программирования Си студенты данной специальности уже познакомились. Поэтому данный курс направлен на дальнейшее изучение возможностей данного языка, а именно: работа с массивами, функциями и особенностями построения программ. В содержание данного курса включены вопросы обработки символьных строк (необходимо отметить, что работа со строками в языке программирования Си намного сложнее, чем в ранее изучаемых языках программирования), указатели. В рамках данного курса студенты должны познакомиться и научиться работать со структурами и объединениями, определить, что такое потоковый ввод-вывод в стандарте СИ, рассмотреть объектно-ориентированное программирование на базе языка Си++, форматированный ввод-вывод в Си++. Пререквизиты: Для успешного освоения курса «Языки программирования» студенты должны обладать знаниями по основам алгоритмизации, должны знать базовые алгоритмические структуры (линейные, ветвление, циклические), должны изучить дисциплину «Информатика», основы программирования (желательно знание языка программирования Паскаль). Для успешного изучения курса необходимы знания в следующих разделах информатики: системы счисления, кодирование, желательно знания в области программирования, а также желательно знакомство с архитектурой ЭВМ на уровне машинных команд, общее знакомство с Ассемблером. Постреквизиты: По окончании изучения данного курса студент должен свободно составлять программы посредством языка Си/Си++ с применением графических возможностей. Полученные знания по окончании данного курса должны стать базовыми при изучении других языков - ООП, в частности, Delphi, Си++ Builder. Методология обучения При изложении курса особое внимание уделяется разбору примеров программ, а именно целесообразности и экономичности использование того или иного пути реализации поставленной задачи, уделяется внимание особенностям применения операторов. Проведение анализа решения задачи. Обязательное практическое закрепление изучаемого материала на компьютере, а также самостоятельное решение задач по теме по индивидуальным заданиям. . Обучение проводится виде лекций и практических занятий ,а также СРСП, на которых отражаются содержание основного учебного материала, отрабатываются практические навыки по применению полученных знаний на лекциях. Данный курс рассчитан в основном на практическое изучение возможностей языка Си, а именно студенты должны знания, полученные на лекциях, практически закрепить на лабораторных занятиях. Контроль знаний студентов будет осуществляться в виде устного коллоквиума и сдачи отчетов по практическим занятиям, а также отчетов по индивидуальным заданиям. Отчет должен быть представлен в электронном виде, в устном виде студент может комментировать выполненное задание, давать пояснения, каким образом может достичь требуемых эффектов, ответы, работа на занятиях, отчетность учитываются при определении рейтинга. Политика курса Курс составлен на основании государственного. стандарта и типовой программы по дисциплине «Языки программирования», занятия при прохождении данного курса предусматривают лекции и практические занятия на ЭВМ. Задания при изучении курса выдаются на занятиях согласно содержанию курса. По окончании выполнения задания студент обязан отчитаться по выполненной работе, представить преподавателю результат, студенты также должны самостоятельно выполнить задания на занятиях СРС и отчитаться по результатам выполненной работы. Своевременность сдачи отчетов, активность на занятиях, грамотно выполненные задания оцениваются по максимальному баллу, в противном случае будут учитываться штрафные баллы. Студенты обязаны: 1. Не опаздывать на занятия 2. Не разговаривать во время занятий 3. Не пропускать занятия, в случае отсутствия по болезни представлять справку 4. На занятие приходить опрятным, без головных уборов 5. Пропущенные занятия отрабатывать в определенное преподавателям время 6. В случае невыполнение заданий, итоговая оценка снижается 7. Посещать занятия согласно расписанию занятий 8. Активно участвовать в учебном процессе 9. Выполнять задания и отчитываться согласно графика 10. Быть терпимым, открытым, откровенным и доброжелательным к сокурсникам и преподавателям 11. Поддерживать обратную связь на всех занятиях 4 12. 13. 14. 15. Содействовать коллективной работе и вовлечению в дискуссию более застенчивых студентов Быть пунктуальным и обязательным Исключать телефонные переговоры во время занятий, отключать сотовый телефон Не допускать пропуска занятий по неуважительным причинам. Требования к студентам: Посещение: Посещение должно быть обязательным. Пропуски занятий отрабатываются в полном объеме занятий, отраженном в учебно-методическом комплексе. Пропуски занятий без уважительной причины в объеме, превышающем треть курса, ведет к исключению с курса и начислению штрафных баллов. Поведение в аудитории: Студент обязан не опаздывать на занятия, не читать постороннюю литературу, отключить сотовый телефон, активно участвовать в учебном процессе, отвечать на поставленные вопросы. Индивидуальные задания: Индивидуальные семестровые задания являются обязательными, они должны быть выполнены и студент обязан защитить свою работу. Каждое задание оценивается отдельно и влияет на итоговую оценку. Индивидуальные задания должны быть сданы в срок, согласно графика отчетности, в случае не выполнения графика студенту будут начислены штрафные баллы, что существенно влияет на рейтинговую оценку студента. Самостоятельная работа: Данная работа задается студенту и должна быть выполнена и защищена во время проведения СРС. Выполняется самостоятельно и представляется в виде отчета в электронном виде. Контроль знаний студентов может осуществляться с помощью тестов, устного опроса. Коллоквиум: Коллоквиумы должны сдаваться по расписанию для каждой группы отдельно. Контроль знаний студентов может осуществляться посредством решения текстовых заданий и в устной форме. Время отчетности указано в таблице: График и содержание занятий Неделя 1 Кредит час 1 Лекция 1 Тема: «Язык программирования Си и его возможности» 1. Структура программы 2. Алфавит, идентификаторы. 3. Константы и их объявление 4. Спецификаторы и квалификаторы типов Литература: [3] 170-202 [11] 10-15 [9] 15-22 СРСП: Концепция структурного программирования. Концепция модульного программирования. История развития языка Си, достоинства и недостатки языка Си СРС: Работа с меню Кредит час 2 Практическое занятие 1 Тема: Реализация программ на языке Си 1. Ознакомительная работа 2. Этапы работы с программой на языке Си 3. Выражения в Си 4. Реализация практических заданий 5. Использование выражений в языке Си 6. Структура программы на Си: заголовок программы, тело главной функции Литература: [3] 202-207 [11] 10-15 [9] 15-22 СРСП: Логическая схема компьютера. Основные виды вычислительных средств Спецификации и их применение СРС: Работа с экранным меню. Технологии разработки программ и их реализация на алгоритмических языках Работа с экранным меню. Технологии разработки программ и их реализация на алгоритмических языках Неделя 2 Кредит час 1 Лекция 2 5 Тема: Константы и переменные 1. Форма представления констант в языке Си 2. Объявление переменных в программе СРСП: Объявление констант и переменных в программе, способы объявления СРС: Самостоятельная работа над индивидуальным заданием Литература: [11] 20-23 [9] 15-26 Кредит час 2 Практическое занятие 2 Тема: Практическое применение констант Программирование линейных алгоритмов 1. Именованные константы 2. Константы перечисляемого типа 3. Целые и вещественные константы 4. Использование препроцессорной директивы для указания именованных констант 5. Функция клавиатурного ввода данных 6. Функция вывода тестовых сообщений 7. Функция вывода данных 8. Потоковый ввод-вывод в Си++ Литература: [11] 20-23,25-30 [9] 15-26 СРСП: Основные базовые типы данных, представление в памяти, размер, диапазон значений СРС: Самостоятельная работа над индивидуальным заданием Неделя 3 Лекция 3 Кредит час 1 Тема: Операции в языке Си 1.Операции присваивания 2. Логические операции 3. Условная операция, операция запятая 4. Операция явного преобразования типа Литература: [11] 31-37 [9] 33-43 СРСП: Арифметические операции и их применение, скобки в качестве операций СРС: Работа с литературой Кредит час 2 Практическое занятие 3 Тема: Применение операций на практике в программах на языке Си 1. 2. 3. 4. 5. Операции присваивания Префиксные и постфиксные операции декремента и инкремента Условная операция. Операция запятая Работа с заданием Литература: [11] 31-37 [9] 33-43 СРСП: Операция sizeof, ее назначение и практическое применение Отчет по выполнению заданий СРС: Работа с индивидуальным заданием по теме операции в Си Неделя 4 Лекция 4 Кредит час 1 Тема: Программирование разветвляющихся алгоритмов 1. Условный оператор 2. Вложенные условные операторы 3. Переключатель Литература: [11] 78-89 [9] 40-43 СРСП: Директивы условной компиляции СРС: Работа над индивидуальным заданием Кредит час 2 Практическое занятие 4 6 Тема: Условный оператор и его применение в языке программирования Си Переключатель и применение в языке программирования Си 1. Полная форма условного оператора 2. Сокращенная форма условного оператора 3. Вложенные операторы 4. Блоки операторов 5. Переключатель, его блок-схема и его назначение 6. Альтернативный переключатель, его применение, блок-схема СРСП: Отчетность, работа над ошибками Работа с индивидуальным заданием по теме условный оператор СРС: Работа с литературой Графическое представление алгоритмов Литература: [11] 78-89 [9] 40-43 Неделя 5 Лекция 5 Кредит час 1 Тема: Программирование циклических алгоритмов на языке Си 1. Цикл с предусловием 2. Цикл с постусловием 3. Цикл с параметром Литература: [11] 90-101 [9] 44-46 СРСП: Практическая реализация применения операторов цикла. Консультация по индивидуальным заданиям СРС: Работа с литературой Кредит час 2 Практическое занятие 5 Тема: Программирование циклических алгоритмов на языке Си Программирование циклических алгоритмов на языке Си 1. 2. 3. Цикл с предусловием Цикл с постусловием Цикл с параметром и различные варианты его применения Литература: [11] 90-101 [9] 44-46 СРСП: Отчетность по индивидуальным заданиям СРС: Решение дополнительных задач по курсу «Циклы в Си» Неделя 6 Лекция 6 Кредит час 1 Тема: Массивы 1. Описание двумерных и одномерных массивов 2. Инициализация массивов и их особенности 3. Ввод-вывод массивов 4. Разбор примеров 5. Многомерные массивы Литература: [4] 217-222 СРСП: Работа над индивидуальным заданием СРС: Составление программ с использованием математических функций. Описание переменных в программах. Кредит час 2 Практическое занятие 6 Тема: Массивы одномерные Массивы двумерные 1. Описание одномерных массивов 2. Инициализация массивов и их особенности 3. Ввод-вывод одномерных массивов 4. Разбор примеров 5. Особенности описаний массивов в программах 6. Инициализация двумерных массивов 7. Ввод-вывод двумерных массивов . Литература: [4] 217-222 СРСП: Работа над индивидуальным заданием Коллоквиум СРС: Составление программ с массивов из дополнительных заданий 7 Неделя 7 Лекция 7 Кредит час 1 Тема: Функции в языке Си 1. Определение функции, обращение к функции 2. Прототип функции 3. Использование библиотечных функций Литература: [3] 207-217 СРСП: Отчетность по индивидуальным заданиям СРС: Рекурсивное определение функции Кредит час 2 Практическое занятие 7 Тема: Массивы 1. Практическое применение массивов для решения задач с двумерными и одномерными массивами 2. Практическое применение массивов для решения задач с двумерными и одномерными массивами Литература: [3] 217-222 СРСП: Работа с индивидуальным заданием СРС: Решение и разбор примеров программ с использованием операторов условия и выбора. Неделя 8 Лекция 8 Кредит час 1 Тема: Классы памяти 1. Автоматическая 2. Внешняя. 3. Статическая 4. Регистровая Литература: [3] 215-217 СРСП: Практическое применение классов памяти СРС: Глобальные, локальные переменные и расположение их в памяти, согласно классификации. Кредит час 2 Практическое занятие 8 Тема: Функции 1. Создание программ с использованием прототипа 2. Создание программ без использования прототипа 3. Практическое решение задач с использованием функций Литература: [3] 217-222 СРСП: Отчет по заданиям СРС: Работа над индивидуальными заданиями Неделя 9 Лекция 9 Кредит час 1 Тема: Обработка символьных строк 1. Стандартные функции для обработки строк. 2. Описание для символьных переменных 3. Строка как параметр функции Литература: [3] 230-234 СРСП: Разбор примеров решения задач с применением функций СРС: Инициализация строк в программах Кредит час 2 Практическое занятие 9 Тема: Обработка символьных строк 1. Стандартные функции для обработки строк. 2. Описание для символьных переменных 3. Решение задач с применением библиотечных функций для обработки строк и символьных переменных Литература: [3] 230-234 СРСП: Разбор примеров решения задач со строками СРС: Изучение теоретического материала Неделя 10 8 Кредит час 1 Лекция 10 Тема: Структуры и объединения 1. Понятие структуры в языке Си 2. Область применения структур 3. Формат описания структур в программах 4. Примеры применения структур Литература: [3] 234-240 СРСП: Особенности использования структур в программах СРС: Разбор примеров с применением структур Кредит час 2 Практическое занятие 10 Тема: Структуры в языке Си. Объединения и применение 1. Понятие структуры в языке Си 2. Область применения структур 3. Формат описания структур в программах 4. Понятие объединения 2. Область применения объединения Литература: [3] 234-240 СРСП: Особенности использования структур и объединений в программах СРС: Разбор примеров с применением структур и объединений Неделя 11 Кредит час 1 Лекция 11 Тема: Указатели 1. Описание указателей 2. Операции над указателями 3. Использование указателей для передачи параметров функции Литература: [3] 223-229 СРСП: Отчетность по заданиям СРС: Указатели и массивы Кредит час 2 Практическое занятие 11 Тема: Указатели 1. Составление программ с использованием указателей 2. Работа над индивидуальным заданием Литература: [3] 223-229 СРСП: Консультация по индивидуальным заданиям СРС: Работа над индивидуальными заданиями. Неделя 12 Лекция 12 Кредит час 1 Тема: Потоковый ввод-вывод в стандарте СИ 1. Понятие потока в языке СИ 2. Стандартные потоки и объявляемые потоки Литература: [3] 240-249 СРСП: Отчетность по индивидуальным заданиям СРС: Использование новых типов данных в программах, объявление, описание и применение Кредит час 2 Практическое занятие 12 Тема: Потоковый ввод-вывод в стандарте Си 1. Объявление потока в программе 2. Практическое применение Литература: [3] 240-249 СРСП: Работа над индивидуальным заданиям СРС: Форматный обмен с файлами Неделя 13 Кредит час 1 9 Лекция 13 Тема: Область действия переменных 1. Понятие области действия переменных 2. Объявление блоков данных в программах Литература: [3] 129-135 СРСП: Отчетность по заданиям СРС: Работа с литературой Кредит час 2 Практическое занятие 13 Тема: Функции и область действия переменных 1. Описание в программе 2. Решение практических задач Литература: [3] 362-365 СРСП: Отчетность по теоретической части изучаемого материала СРС: Работа с литературой, разбор программ Неделя 14 Лекция 14 Кредит час 1 Тема: Объектно-ориентированное программирование в Си++ 1. Понятие класс, синтаксис объявления классов Режимы доступа к элементам класса СРСП: Понятие наследование, полиморфизм, перегрузка операций СРС: Работа над индивидуальными заданиями Кредит час 1 Практическое занятие 14 Тема: Объектно-ориентированное программирование в Си++ 1. Практическая реализация программ с использованием объектов 2. Практическая реализация программ с использованием объектов Литература: [3] 250-261 СРСП: Отчетность по заданиями СРС: Работа с литературой Неделя 15 Кредит час 1 Лекция 15 Тема: Графика в Си 1. Инициация графического режима 2. Основное назначение графических процедур и их использование Литература: [3] 420-427 СРСП: Отчетность по теоретическому материалу СРС: Работа с литературой Кредит час 2 Практическое занятие 15 Тема: Графика 1. Построение графических объектов Литература: [3] 420-427 СРСП: Отчетность по индивидуальным заданиям Рейтинг СРС: Работа над заданиями Список литературы Основная литература: 1. 2. 3. 4. 5. 6. 7. Курс лекций. Подбельский В.В. Фомин С.С. Программирование на языке Си. – М: Финансы и статистика 1999 Семакин И.Г. Шестаков А.П. Основы программирования Москва 2001 г. Паппас К., Мюррей У. Программирование на С и С++ Киев: «Ирина»;2000г. Подбельский В.В. Язык программирования Си++ М: «Финансы и статистика» Березин Б.И. Березин С.Б. Начальный курс С и С++ М6 Диалог-Мифи 1996 Дейтел Х.М. Как программировать на С++.-3-е изд .-М. :Бином, 10 2003.-1152с. 8. Джосьютис Н. С++ Стандартная библиотека. для профессионалов.СПб.:Питер,2004.-730с. 9. Павловская Т.А. Программирование на языке высокого уровня С/С++-СПб.: Питер, 2004.-461с.: ил 10. Карпов Б. С++:Специальный справочник.-СПб. :Питер, 2001-480с. 11. Могилев А.В., Пак Н.И., Хеннер Е.К. Информатика./ Учебное пособие для студентов вузов / 3-е изд.перераб. и доп.-М.: Издательский центр «Академия»,2004 12. Культин Н. С/С++ в задачах и примерах.-Спб.:БХВ Петербург,2004.-288 с. 13. Страуструп Б. Язык программирования С++: Спец.изд .-М. БИНОМ, 2004.1104с.:ил. 14. Практикум на ЭВМ: Язык программирования СИ А.:жазак университет, 2001 15. Бочков С.О., Субботин Д.М. Язык программирования С для персонального компьютера.-М.:Радио и связь 16. Джехани Н. программирование на языке С++: Пер.с анг.-М. 17. Голуб Ален И. С и С++. Правила программирования. М.,1996 Дополнительная литература: 1. Лавров.С.С «Введение в программирование». 2. Бухтияров А,М «Сборник задач по программированию». Наука. 3. Зуев Е.А. Практическое программирование на языке Turbo Pascal М:Радио и связь 1994 г. 4. Грогоно П. Программирование на языке Паскаль М: Мир 1982г. 5. Под. ред Савельева А.Я. «Задачи и упражнения по программированию». М: Высшая школа. 3. График выполнения и сдачи заданий по дисциплине Вид работ Цель и содержание задания Рекомендуемая литература Продолжительность выполнения и дата (неделя) представления работы Баллы Форма контроля Активность на лекционных занятиях Проверка теоретической подготовки Согласно теме занятия Неделя 100% Устный опрос 2 Написание рефератов Развитие аналитических и познавательных способностей Согласно теме занятия Согласно графику времени отведенному на СРС по теме 100% Проверка письменной работы согласно темам рефератов 2 Разработка компьютерных программ Согласно теме занятия Согласно графику времени отведенному на СРС по теме 100% Проверка работы программы 3 Коллоквиум 6 Экзамен № п/п 1 Развитие аналитических и познавательных способностей Проверка способности логически мыслить Комплексная проверка знаний 100% 100% 4. Карта учебно-методической обеспеченности дисциплины № п/п 1 1 Наименование литературы 2 Дейтел Х.М. Как программировать на С++.-3-е изд .-М. :Бином, 2003.-1152с. Джосьютис Н. С++ Стандартная библиотека. для профессионалов.СПб.:Питер,2004.730с. В библиотеке на кафедре 3 4 3 Наличие обеспеченности студентов (%) 5 20 11 Электронная версия 6 Примечание 7 . 2 3 4 5 Карпов Б. С++:Специальный справочник.-СПб. :Питер, 2001-480с. Культин Н. С/С++ в задачах и примерах.Спб.:БХВ Петербург,2004.-288 с. Страуструп Б. Язык программирования С++: Спец.изд .-М. БИНОМ, 2004.1104с.:ил. Заварыкин В.М. Основы информатики и вычислительной техники Практикум на ЭВМ: Язык программирования СИ .А.:жазак университет, 2001.-80с. Абдрахманов А.Т 2 15 3 20 10 50 3 20 5. Лекционный комплекс: Введение Язык СИ был создан в 1972 году сотрудником фирмы Bell Laboratories в США Денисом Ритчи. Это была третья попытка создания языка: перед тем были созданы языки под названием А и В, но они не получили широкого распространения. Язык Си - это язык высокого уровня, поддерживающий методику структурного программирования (подобно Паскалю), но тем не менее он несет в себе некоторые черты, свойственные языку ассемблера. Этот же язык должен обеспечить возможность создавать такие системные программы, как компиляторы и операционные системы. До появления СИ подобные программы писались исключительно на языках низкого уровня - Ассемблер, Автокод. Первым системным программным продуктом, разработанным с помощью СИ, стала операционная система UNIX. Стандарт СИ был утвержден в 1983 г. Американским национальным институтом стандартов (ANSI) и получил название ANSI С. В начале 1980-х гг. в той же фирме Bell Laboratories ее сотрудником Бьерном Страуструпом было разработано расширение языка СИ, предназначенное для объектно-ориентированного программирования (Си++). Однако этот язык, как подмножество, включает в себя Си и по прежнему сохраняет свойства языка для системного программирования. Все существующие версии трансляторов для Си++ поддерживают стандарт ANSI С. Следует отметить некоторые недостатки и достоинства. Достоинства: 1. Мощность. Программы на Си могут концентрировать массу вычислений в небольшом числе отдельных шагов. Например, в большинстве языков программирования, увеличение значения на единицу выполняется следующим образом: с=с+1. На языке Си такая запись может быть заменена эквивалентной : ++с; Эта запись требует от компьютера меньшей работы на уровне машинного кода, а результат работы тот же – увеличение значения на 1. 2. Переносимость. Это свойство означает, что для программиста использование Си не ограничивается машинами какого-то одного типа. Сейчас доступны версии языка Си почти для каждой из существующих систем компьютеров. Сюда входят системы PC, Apple Macintosh и Unix. Microsoft Windows и Windows NT разрабатывались, главным образом, на Си. Unix была переписана на Си. 3. Популярность. Мощность и переносимость Си сделали его очень популярным. На Си написано большое количество коммерческих программ. 4. Развитие. Язык Си все время изменяется главным образом за счет дополнений и расширений. Первоначальная часть языка не меняется, т.к. это нанесло бы ущерб его переносимости. Дополнения к Си – это обычно специальные 12 библиотеки готовых к использованию процедур. В настоящее время Си проник в область объектно-ориентированного программирования (ООП). Недостатки: 1.Жесткая структура построения программ. 2.Трудность в обращении с некоторыми данными. 3.Сложность в изучении языка. Для того чтобы получить первоначальное представление о программирова-нии на Си/Си++, рассмотрим пример. Пример1. /* Программа на Си*/ # include <stdio.h> void main() { printf (“\n Здравствуйте ! \n”); } В данной программе первая строка представляет собой комментарий. Начало и конец комментария ограничиваются парами символов /* и */. Все, что расположено между этими символами, компилятор игнорирует. Вторая строка программы содержит директиву препроцессора: #include<stdio.h>.Она сообщает компилятору информацию о необходимости подключить к тексту программы содержимое файла stdio.h, в котором находится описание (прототип) библиотечной функции printf () – функции вывода на экран. Запись, которая начинается с #include, иногда еще называют заголовком. Вся последующая часть программы называется блоком описания главной функции. Она начинается с заголовка главной функции: void main(). Любая программа на Си обязательно содержит главную функцию, имя которой- main().Строка, начинающаяся с main(), организует основное тело программы. Слово void обозначает то, что главная функция не возвращает никаких значений в результате своего выполнения, а пустые скобки обозначают отсутствие аргументов. Тело главной функции заключается между парой фигурных скобок, следующих после заголовка. В примере 1 текст программы содержит всего лишь один исполняемый оператор - это оператор вывода на экран. Вывод осуществляется путем обращения к стандартной библиотечной функции printf (). В результате его выполнения на экран выведется текст: Здравствуй! Впереди данной строки после нее будет пропущено по одной пустой строке, что обеспечивается наличием управляющих символов \n. Следующий пример содержит программу, выполняющую те же самые действия, но написанную на Си++. Пример 2. //Программа на Си++ # include <iostream.h> void main() { cout“\n Здравствуйте !\n”; } Комментарий начинается с символов // и заканчивается концом строки. Для организации вывода на экран к программе подключается специальная библиотека объектов, заголовочный файл которой имеет имя iostream.h. Вывод осуществляется посредством объекта cout из этой библиотеки. В примере 1 используется механизм форматного вводавывода, характерный для Си. В примере 2 работает механизм потокового ввода-вывода, реализо-ванный в Си++. Этапы работы с программой на Си++ в системе программирования 13 Текстовый редактор Исходный текст программы на Си++ (файл example.cpp) Препроцесор Включаемые файлы .h Полный текст программы на Си++ (файл example.cpp) Компилятор Объектный код программы (файл example.cpp) Компоновщик Библиотечные файлы Исполняемая программа (файл example.cpp) Замечание. Прямоугольниками отображены системные программы, а блоки с овальной формой обозначают файлы на входе и на выходе этих программ. Последовательность работы: 1.С помощью текстового редактора формируется текст программы и сохраняется в файле с расширением .cpp. Пусть, например, это будет файл с именем example.cpp. 2.Осуществляется этап препроцессорной обработки, содержание которого определяется директивами препроцессора, расположенными перед заголовком программы (функции). В частности, по директиве #include препроцессор подключает к тексту программы заголовочные файлы (.h) стандартных библиотек. 3.Происходит компиляция текста программы на Си++. В ходе компиляции могут быть обнаружены синтаксические ошибки, которые должен исправить программист. В результате успешной компиляции получается объектный код программы в файле с расширением .obj. Например, example.obj. 4.Выполняется этап компоновки с помощью системной программы Компоновщик (Linker). Этот этап еще называют редактированием связей. На данном этапе к программе подключается библиотечные функции. В результате компоновки создается исполняемая программа в файле с расширением .exe. Например, example.exe. Элементы языка Си++ 1.Алфавит. В алфавит языка Си++ входят: латинские буквы: от а до z (строчные) и от А до Z (прописные); десятичные цифры: 0,1,2,3,4,5,6,7,8,9; специальные символы:“,{,},|, [,], (, ),+,-,/, %, \, ;, ‘, :, ?, <, >, _, !, &, #, ^,., *. Кспециальным символам относится также и пробел. В комментариях, строках и символьных константах могут использоваться и другие знаки (например, русские буквы).Комбинации некоторых символов, не разделенных пробелами, интерпретируются как один значимый символ. К ним относятся : ++, -- , = = , && , || , << , >> , >= , <= , += , -= , *= , /= , ?= , /* , */ , // 14 В Си++ в качестве ограничителей комментариев могут использоваться как пары символов /* и */, принятых в языке Си, так и символы //, используемые в Си++. Признаком конца такого комментария является невидимый символ перехода на новую строку. Например: // - это комментарий, используемый в Си++ . Из символов алфавита могут формироваться лексемы – это единицы текста программы, которые при компиляции воспринимаются, как единое и не могут быть разделены на более мелкие элементы. К лексемам относятся идентификаторы, служебные слова, константы, знаки операций, разделители. Последовательность латинских букв, цифр, символов подчеркивания называется идентификатором. Например: В12,rus,I_hmu,_disk, MAX, ris_32. В отличии от Паскаля в Си/Си++ различаются прописные и строчные буквы. Это значит, что, например, flag, FLAG, Flag, FLAg- это разные идентифика-торы. Компиляторы фирмы Borland позволяют использовать до 32 первых символов имени. Служебные (ключевые) слова в Си – это идентификаторы, назначение которых однозначно определено в языке. Они не могут быть использованы как свободно выбираемые имена. Полный список служебных слов зависит от реализации языка, т.е. различается для разных компиляторов. Однако существует неизменное ядро, которое определено стандартом Си++. Вот его список: asm else operator template auto enum private this break extern protected thow case float public try catch аor register typedef char friend return typeid class goto short union const if signed unsigned continue inline sizeof virtual default int static void delete long struct volatile do view switch while double Дполнительные к этому списку служебные слова приведены в описании конкретных реализаций Си++. Некоторые из них начинаются с символа под-черкивания, например: _export, _ds, _AH и др. Существуют служебные слова, начинающиеся и с двойного подчеркивания. Типы данных Концепция типов данных является важнейшей стороной любого языка программирования. В Си/Си++ имеется четыре базовых арифметических (числовых) типов данных. Из них два целочисленных- char, int- и два плава-ющих (вещественных)-float, double. Кроме того, в программах можно исполь-зовать некоторые модификации этих типов, описываемых с помощью слу-жебных слов- модификаторов. Существует два модификатора размера- short (короткий) и long (длинный) – и два модификатора знаков- signed (знаковый) и unsigned (беззнаковый). Знаковые модификаторы применяются только к целым типам.Тип величины связан с его формой внутреннего представления, множеством принимаемых значений и множеством операций, применимых к этой величине. В представленной таблице перечислены арифметические типы данных Си++, указан объем занимаемой памяти и диапазон допустимых значений. Размер типа int и unsigned int зависит от размера слова операционной системы, в которой работает компилятор Си++. В 16-разрядных ОС (MS DOS) этим типам соответствует 2 байта, в 32-разрядных (Windows)-4 байта. Если не указан базовый тип, то по умолчанию подразумевается int. Если не указан модификатор знаков, то по умолчанию подразумевается signed. С базовым типом float модификаторы не употребляются. Модификатор short применим только к базовому типу int. 15 Скалярны е Арифческие Типы Указатели Массивы Составные Целые Плавающие Структуры Смесь Тип данных Размер (байт) char 1 int 2/4 unsigned char 1 unsigned int 2/4 short int 2 unsigned short 2 long int 4 unsigned long int 4 Диапазон значений -128…+127 зависит от системы 0…255 зависит от системы -32768…32767 0…65535 -2147483648…2147483647 0…4294967295 Эквивалентные названия полей signed char signed , signed int Нет unsigned short, short signed int unsigned short int long, signed long int unsigned long float 4 - +(3.4Е 38…3.4Е+38) Нет double 8 - +(1.7Е-308…1.7+308) Нет long double 10 - +(3.4Е-4932…1.1Е+4932) Нет - В Си/Си++ величины типа char причислены к арифметическим типам и могут рассматриваться в программах и как символы, и как целые числа. Все зависит от способа использования этой величины. В случае интерпретации величины типа char как символа ее числовое значение является ASII-кодом. Следующий пример иллюстрирует сказанное: char a=65; printf(“%c”,a); //На экране появится символ А; printf(“%d”,a); //На экране появится число 65. Символы “%c” являются спецификацией формата ввода/вывода символьных данных, а “% d” –спецификацией для целых чисел. В языке Си отсутствует среди базовых типов логический тип данных. В последние версии Си++ добавлен отдельный логический тип с именем bool. Его относят к разновидности целых типов данных. Все данные в компьютере хранятся в специально отведенном месте памяти с произвольным доступом (random-access memory) – RAM. Давая переменным имена необходимо помнить правила: 1.Первым символом имени должна быть либо буква, либо символ подчеркивания. 2.После первого символа можно использовать любую комбинацию букв и цифр. Нельзя использовать не буквенно-цифровые символы вроде # и $. 3.В Си имеет значение регистр букв. 4. Нельзя применять в качестве имен переменных служебные слова, 16 команды. 5.Нельзя использовать в именах пробелы, т.к. пробел служит признаком окончания одного слова и переходом к следующему. Например: выражение work1_work2 рассматривается как одно слово, в то время как work1 work2 считается двумя отдельными словами. Формат описания переменных в программах Си/Си++ имеет вид: имя_типа список _переменных ; Примеры описаний: char symbol, cc; unsigned char code ; int number,row ; unsigned long long_number ; float x, y, z ; double e,b4 ; long double max_num ; Одновременно с описанием можно задать начальные значения переменных. Такое действие называется инициализация переменных. Описание с инициализацией производится по следующей схеме: тип имя_переменной = начальное_значение; Например: float pi=3.14159,c=1.23 ; unsigned int year=2000 ; Константы 1. Целые константы a) Целые десятичные числа не должны начинаться с нуля, например: 4; 346; -128. b) Целые восьмеричные числа записываются всегда с нуля, например:016; 05; c) Целые шестнадцатеричные числа начинаются с символов 0х, например: 0х1А; 0х126; 0хFFFF; Тип константы компилятор определяет по следующим правилам: если значение константы лежит в диапазоне типа int, то она получает тип int, в противном случае проверяется, лежит ли константа в диапазоне типа unsigned int, в случае положительного ответа она получит этот тип. Если не подходит и он, то пробуется тип long и, наконец, unsigned long. Если значение числа не укладывается в диапазон типа unsigned long, то возникает ошибка компиляции. Если в записи числовой константы присутствует десятичная точка (2.5) или экспоненциальное расширение (1Е-8), то компилятор рассматривает ее как вещественное число и ставит ей в соответствие тип double. Например: 44.5; 3.14159; 44Е0; 1.5Е-4; Программист может явно задать тип константы, используя для этого суффиксы. Существует три вида суффиксов: F(f)float; U(u)-unsigned; L(l)-long (для целых и вещественных констант). Кроме того, допускается совместное использование суффиксов U и L в вариантах UL или LU. Примеры: 3.4159F- константа типа float, под которую выделяется 4 байта памяти; 3.14L- константа типа long double, занимает 10 байт; 5000U- константа типа unsigned int, занимает 2 байта; 0LU-константа типа unsigned long, занимает 4 байта; 2424242UL-константа типа unsigned long, занимает 4 байта. 2.Символьные константы заключаются в апострофы. Например: ’А’,’+’,’5’. Строковые константы, представляющие собой символьные последовательности , заключаются в двойные кавычки. Например: “rezult”,“введите число”. Особую разновидность символьных констант представляют так называемые управляющие символы. Их назначение- управление выводом на экран. Такие символы расположены в начальной части кодовой таблицы ASII (коды от 0 до 31) и не имеют графического представления. В программе на Си они изображаются парой символов, первый из которых ‘\’. Вот некоторые из управляющих символов: ‘\n’-переход на новую строку; ‘\t’- горизонтальная табуляция; ‘\a’- подача звукового сигнала. Управляющие символьные последовательности являются частным случаем эскейп-последовательностей ( ESCпоследовательность), с помощью которых можно задать символьную константу указанием ее кода. Код символа можно указать в восьмеричном или шестнадцатеричном представлении. Формат восьмеричного представления:‘\ddd’.Здесь d –восьмеричная цифра(от 0 до 7). Формат шестнадцатеричного представления: ‘\xhh’ ( или‘\Хhh’), где h-шестнадцатеричная цифра от 0 до F). Например, константа, соответствующая заглавной латинской букве А, может быть представлена тремя способами : 17 ‘A’, ’\101’, ‘\x41’. 3.Именованные константы( константные переменные). Как и в Паскале, в программе на Си/Си++ могут использоваться именованные константы. Употребляемое для их определения служебное слово const принято называть квалификатором доступа. Квалификатор const указывает на то, что данная величина не может измениться в течение всего времени работы программы. Примеры описания константных переменных: const float pi=3.14159; const int iMIN=1, iMAX=1000; Еще одной возможностью ввести именованную константу является использование препроцессорной директивы #define в следующем формате: #define <имя константы> <значение константы> Например: #define iMIN=1 #define iMAX=1000 Тип констант явно не указывается и определяется по форме записи. В конце директивы не ставится точка с запятой. На стадии препроцессорной обработки указанные имена заменяются на соответствующие значения. Например, если в программе присутствует оператор Х= iMAX- iMIN; ,то в результате препроцессорной обработки он примет вид: х=1000-1; При этом идентификаторы iMAX и iMIN не требуют описания внутри программы. 4.Константы перечисляемого типа позволяют определять последователь-ность целочисленных именованных констант. Описание перечисляемого типа начинается со служебного слова enum, а последующий список констант заключается в фигурные скобки. Например: enum {A,B,C,D}; В результате имени А будет сопоставлена константа 0, имени В-1,С-3,D-3. По умолчанию значение первой константы равно нулю. Для любой константы можно явно указать значение. Например: : enum {A=10,B,C,D}; В результате будут установлены следующие соответствия : А=10, В=11, С=12, D=13. Возможен и такой вариант перечисления: enum {A=10,B=20,C=35,D=100}; Если перечисляемому типу дать имя то его можно использовать в описании переменных. Этот вариант аналогичен использованию перечисляемого типа данных в Паскале. Например: enum metal { Fe,Co,Na,Cu,Zn}; metal met1,m; Здесь идентификатор metal становится именем типа. После такого описания в программе возможны следующие операторы: met1= Na; m= Zn; Операции и выражения Во всех языках программирования под выражением подразумевается конструкция, составленная из констант, переменных, знаков операций, функций, скобок. Выражение определяет порядок вычисления некоторого значения. Если это числовое значение, то такое выражение называют арифметическим. Например: a+b 2*(x+y) Три первых выражения имеют традиционную форму 12.5-z для языков программирования высокого уровня, поэтому x++ их смысл очевиден. Следующие четыре выражения x++ + b специфичны для языка Си. --n*2 n*= 1 Рассмотрим операции, а также правила записи и вычисления выражений. Операция, применяемая к одному операнду, называется унарной, а операция с двумя операндами – бинарной. Арифметические операции. К ним относятся: вычитание или унарный минус; + сложение или унарный плюс; * умножение; / деление; % деление по модулю; ++ унарная операция увеличения на единицу (инкремент); -унарная операция уменьшения на единицу (декремент); Все операции, кроме деления по модулю, применимы к любым числовым типам данных. Операция % применима только к целым числам. Операции инкремента и декремента могут применяться только к переменным и не могут - к константам и выражениям. Операции ++ и -- увеличивают или уменьшают значение переменной на единицу соответственно. Оба знака операции могут записываться как перед операндом( префиксная форма), так и после операнда(постфиксная форма), например ++Х или Х++,--Х или Х--. Три следующих оператора дают один и тот же результат: х=х+1; ++х; х++; Различие проявляется при использовании префиксной и постфиксной форм в выражениях. Первый пример: а=3; с=2; х=а++*с++; В результате выполнения переменные получат следующие значения: а=4, с=3, х=6. 18 Второй пример:а=3;с=2;х=++а*++с;Результаты будут иными: : а=4, с=3, х=12 Это объясняется следующим образом: при использовании постфиксной формы операции ++ и -- выполняются после того, как значение переменной было использовано в выражении, а префиксные операции – до использова-ния. Поэтому в первом примере значение переменной х вычислялось как произведение 3 на 2, а во втором случае – как произведение 4 на 3. По убыванию старшинства арифметические операции расположены в следующем порядке: 1. ++, -3. +, /, % 2. - (унарный минус) 4. +, Одинаковые по старшинству операции выполняются в порядке слева направо. Для изменения порядка выполнения операций в выражениях могут применяться круглые скобки. Операции отношения. В Си используется тот же набор операций отношения, что и в Паскале. Разница заключается в записи операций «равно» и «не равно». < меньше <= меньше или равно > больше >= больше или равно == равно != не равно В стандарте Си нет логического типа данных. Поэтому результатом операции отношения является целое число: если отношение истинно – то 1, если ложно – то 0. Логические операции. Три основные логические операции в языке Си записываются иначе, чем в Паскале. ! операция (НЕ) && конъюнкция, логическое умножение (И) || дизъюнкция, логическое сложение (ИЛИ) Например, логическое выражение, соответствующее системе неравенств 0<x<1 в программе на Си запишется в виде следующего логического выражения: x>0 && x<1. Здесь не понадобятся круглые скобки для выделения операций отношения. По убыванию приоритета логические операции и операции отношения расположены в следующем порядке: ! > , <, >=, <= = = != && || Помимо рассмотренных операций, в Си имеются поразрядные логические операции. Эти операции выполняются над каждой парой соответствующих двоичных разрядов внутреннего представления операндов. Их называют битовыми логическими операциями. Знаки битовых операций: & поразрядная конъюнкция (И) || поразрядная дизъюнкция (ИЛИ) ^ поразрядное исключающее (ИЛИ) ~ поразрядное отрицание (НЕ) Битовые логические операции вместе с операциями поразрядного сдвига влево (<<) и вправо (>>) позволяют добраться до каждого бита внутреннего кода. Операция присваивания в языке Си не является операндом, следствием является то, что присваивание, как любой другой знак операции, может несколько раз входить в выражение Например: а=b=c=x+y. Присваивание имеет самый низкий приоритет( ниже только у операции “запятая”). Кроме того, операция присваивания- правоассоциативная . Это значит, что несколько подряд расположенных присваиваний выполняются справа налево. В языке Си имеются дополнительные операции присваивания, совмещающие присваивание с выполнением других операций. Среди них : +=, -=, /=, *=, %=. Приоритет у них такой же, как и у простого присваивания. Примеры таких операций: a+=2 эквивалентно a=a+2 x-=a+b эквивалентно x=x-(a+b) h/=10 эквивалентно h=h/10 m*=n эквивалентно m=m*n r%=5 эквивалентно r=r%5. Вместо выражения a=a+2 предпочтительнее a+=2, поскольку второе выражение будет вычисляться быстрее. Операция явного преобразования типа ( операция “тип” ). Применение этой операции имеет следующий формат: (имя_типа ) операнд. Операндом могут быть константа, переменная, выражение. В результате значение операнда преобразуется к указанному типу. Примеры использования преобразования типа: (float)8, (int)x%2. Приоритет операции “тип” выше деления ( и других бинарных арифметических операций). Поэтому в выражении (int)x%2 сначала значение переменной х приведется к целому типу ( отбросится дробная часть)а затем выполнится деление по модулю. В следующем фрагменте, если не использовать преобразование типов, то значение переменной будет равно нулю, при использовании операции явного преобразования типа получится значение 0,5: float c; int f=1,b=2; c=(float)a/b; 19 Операция sizeof имеет две формы записи: операция sizeof (тип) и sizeof (выражение). Результатом операции является целое число, равное количеству байтов, которое занимает в памяти величина явно указанного типа или величина, полученная в результате вычисления выражения. Приоритет операции sizeof выше, чем у бинарных арифметических операций, логических операций и отношений. Примеры использования операции: sizeof (int) результат - 2 sizeof (1) результат - 2 sizeof (0.1) результат - 8 sizeof (1L) результат - 4 sizeof (char) результат - 1 sizeof (‘a’) результат – 2 Операция «запятая». Эта необычная операция используется для связывания нескольких выражений в одно. Несколько выражений, разделенных запятыми, вычисляются последовательно слева направо. В качестве результата такого совмещенного выражения принимается значение самого правого выражения. Например, если переменная х имеет тип int, то значение выражения (х=3, 5*х) будет равно 15, а переменная х примет значение 3. Операция «условие». Это единственная операция, которая имеет три операнда. Формат операции: выражение1 ? выражение2 : выражение3 Данная операция реализует алгоритмическую структуру ветвления. Алгоритм ее выполнения следующий: первым вычисляется значение выражения1, которое обычно представляет собой некоторое условие, если оно истинно, т.е. не равно 0, то вычисляется выражение2 и полученный результат становится результатом операции. В противном случае в качестве результата берется значение выражения3. Например, вычисление абсолютной величины переменной х можно организовать с помощью одной операции: x<0 ? –x: x; Правила языка в данном случае позволяет ставить условную операцию слева от знака присваивания. Операции ()и []. В языке Си круглые и квадратные скобки рассматриваются как операции, причем эти операции имеют наивысший приоритет. Сведем все операции, используемые в языке Си в единую таблицу, расположив по рангам. Ранг операции – это порядковый номер в ряду приоритетов, Чем больше ранг, тем ниже приоритет. В таблице отражено еще одно свойство операций – ассоциативность. Если одна и та же операция, повторяющаяся в выражении несколько раз, выполняется в порядке расположения слева направо, то она называется левоассоциативной; если выполняется справа налево, то – правоассоциативной. В таблице эти свойства отражены стрелками влево и вправо. Приоритеты (ранги) операций Ранг Операции Ассоциативность 1 () [] -> . ------> 2 ! ~ + - ++ -- & * (тип) sizeof (унарные) <------ 3 * / % (мультипликативные бинарные) ------> 4 + - (аддитивные бинарные) ------> 5 << >> 6 < <= >= > (отношения) ------> 7 = = != (отношения) ------> 8 & (поразрядная конъюнкция «И») ------> 9 ^ (поразрядное исключающее«ИЛИ») ------> 10 | (поразрядная дизъюнкция «ИЛИ») ------> 11 && (конъюнкция «И») ------> 12 || 13 ?: (условная) 14 = *= /= %= += -= 15 , (запятая) (поразрядного сдвига) -----> (дизъюнкция «ИЛИ») ------> <------ &= ^= |= <<= >>= <-----------> Приведение типов при вычислении выражений Во всех языках программирования высокого уровня работает ряд общих правил записи выражений: 20 все символы, составляющие выражение, записываются в строку (нет надстрочных и подстрочных символов); в выражении проставляются все знаки операций; при записи выражения учитываются приоритеты операций; для влияния на последовательность операций используются круглые скобки. В языке Си в процессе вычисления выражений с разнотипными операндами производится автоматическое преобразование типов величин. Суть правил преобразования при выполнении бинарных операций сводится к следующему: а) преобразование не выполняется, если оба операнда имеют одинаковый тип; б) при разных типах операндов происходит приведение величины с младшим типом к старшему типу (кроме операции присваивания) ; в) при выполнении операции присваивания величина, полученная в правой части, преобразуется к типу переменной, стоящей слева от знака =. Старшинство типов друг по отношению к другу определяется по следующему принципу: старший тип включает в себя все значения младшего типа как подмножество. Вещественные (плавающие) типы являются старшими по отношению к целым. В свою очередь, внутри каждой из групп иерархия типов устанавливается в соответствии с указанным принципом. Целые типы по возрастанию старшинства расположены в таком порядке: char -->short – >int-->long. Порядок старшинства вещественных типов следующий:float-->double-->long double. Упражнения 1.Определить тип константы: а) 315; б)-32.4; в) 102408; г) 3.7Е57; д) 0315; е) 0х2444 ж) 2.6l; з) 70700U; и) ‘5’; к) ‘\121’; 2.В программе объявлена переменная: int n=10;. Определить результаты вычислений следующих выражений: а) n++ б) ++n в) n%2; г) n/3; д) n/3.; е) ++n+5; ж)5+n++; з)(float)n/4; и) sizeof(n); к) sizeof(1.*n); 3. Координаты точки на плоскости заданы переменными X и Y.Записать следующие условия в форме логических выражений: а) точка лежит в первой четверти координатной плоскости; б) точка лежит на оси X; в) точка лежит на одной из осей; г) точка лежит в первой или во второй четверти внутри единичной окружности; д) точка лежит на единичной окружности в третьей или четвертой четверти; е) точка лежит внутри кольца с внутренним радиусом 1 и внешним радиусом во второй или четвертой четверти; 4.В программе объявлена переменная: float x=2. Какое значение получит переменная x в результате вычисления следующих выражений? а) х+=2; б) х/=10; в) х*=(х+1); г) х+=х+=1; 5. Определить значения выражений для трех вариантов объявления переменной х: 1) float х=1; 2) float х=10; 3) int x=1; а) х>1 ? 2*x : x; б) х/5= =2 ? 5: х/10; в) х >0 &&х<=1 ? 1: 0; Структура программы на Си/Си++ Структура программы имеет следующий вид: директивы препроцессора или директивы препроцессора определения объектов; void main() void main() {определения объектов; { исполняемые операторы; исполняемые операторы; } } Для S= примера рассмотрим программу для вычисления p( p - a)( p - b)( p - c ) #include<stdio.h> #include<math.h> void main() {float a,b,c,p,s; printf (“\n a=”);scanf(“%f”, &a); 21 площади треугольника по формуле Герона: printf(“\n b=”);scanf(“%f”, &b); printf(“\n c=”);scanf(“%f”, &c); p = (a+b+c)/2; s=sqrt(p*(p-a)*(p-b)*(p-c)); printf(“\n Площадь треугольника =%f”,s); } Программа состоит из одной главной функции со стандартным именем main(). Слово void обозначает отсутствие какого-либо возвращаемого этой функцией результата, а пустые скобки – отсутствие у нее аргументов. Все, что следует после заголовка функции и заключено в фигурные скобки, называется телом функции. Первая строка – объявление переменных. Объявление переменных заканчивается точкой с запятой. Далее следуют исполняемые операторы. Понятие «оператор» в Си трактуется следующим образом: любое выражение, после которого стоит точка с запятой, воспри-нимается компилятором как отдельный оператор. Оператор определяет законченное, определенное действие на очередном шаге выполнения прог-раммы. С точки зрения данного выше определения конструкция i++; в программе называется оператором. Его называют также оператором-выражением. Если вычисление заканчивается присваиванием, то его можно назвать оператором присваивания. Таким образом, в программе присутствуют два оператора присваивания: вычисление р и вычисление s. В выражении для вычисления площади используется библиотечная функция sqrt() – квадратный корень. Данная функция относится к библиотеке математических функций. Для подключения этой библиотеки к программе используется директива препроцессора #include<math.h>. math.h - имя заголовочного файла этой библиотеки. В программе операторы printf(…); и scanf(…); реализуют соответственно вывод на экран и ввод исходных данных с клавиатуры. Они осуществляют обращение к соответствующим функциям стандартной библиотеки ввода-вывода Си, заголовочный файл которых имеет имя stdio.h. Математические функции (заголовочный файл math.h ) Обращение abs(x) acos(x) Тип аргумента int double Тип результата int Функции абсолютное значение целого числа double арккосинус (радиан) asin(x) double double арксинус (радиан) atan(x) double double арктангенс(радиан) ceil(x) double double ближайшее целое, не меньше х cos(x) double double косинус (х в радианах) exp(x) double double экспонента от х -ех fabs(x) double double абсолютное значение вещественного х floor(x) double double наибольшее целое, не превышающее х fmod(x) double double остаток от деления нацело х на у log(x) double double логарифм натуральный - lnx log10(x) double double логарифм десятичный lgx pow(x,y) double double х в степени у - ху sin(x) double double синус (х в радианах) sinh(x) double double гиперболический синус sqrt(x) double double корень квадратный - tan(x) double double тангенс (х в радианах) tanh(x) double double гиперболический тангенс double вычисляет гипотенузу прямоугольного треугольника по значению катетов z2=x2+y2 double вычисляет значение полинома hypot(x,y) poly(x,n,c[]) double x, c[]);int n x Форматированный вывод на экран Оператор вызова функции printf() имеет следующую структуру: printf (форматная_строка, список_аргументов); Форматная строка ограничена двойными кавычками (т.е. является текстовой константой) и может включать в себя произвольный текст, управляющие символы и спецификаторы формата. Список аргументов может отсутствовать или состоять из выражений, значения которых выводятся на экран (в частном случае из констант и переменных).Текст 22 заданный в кавычках выводится на экран в том виде, в котором он записан. Управляющие символы влияют на расположение на экране выводимых знаков. Признаком управляющего символа является значок \ . Список управляющих символов \n - перевод строки; \ t - горизонтальная табуляция; \r - возврат курсора к началу новой строки; \a - сигнал-звонок; \b - возврат на один символ (одну позицию); \f - перевод (прогон) страницы; \v - вертикальная табуляция; Оператор printf (“\n Площадь треугольника =%f”,s);содержит все виды пара-метров функции printf.Список аргументов состоит из одной переменной s. Ее значение выводится на экран. Пара символов % и f является спецификацией формата (%f). Значок % - признак формата , а буква f указывает на то, что выводимое число имеет вещественный(плавающий) тип и выводится на экран в форме с фиксированной точкой. Например, если в результате вычислений переменная s получит значение 32,435621, то на экран выведется: Площадь треугольника =32.435621. Спецификатор формата определит форму внешнего представления выводимой величины. Некоторые спецификаторы формата: %c - символ %s - строка %d - целое десятичное число (тип int) %u - целое десятичное без знака (тип unsigned) %f - вещественные числа в форме с фиксированной точкой %e - вещественные числа в форме с плавающей точкой Например, после выполнения следующих операторов float m,p; int k; m=84.3;k=-12;p=32.15; printf (“\n m=%f\t k=%d\t p=%e”,m,k,p); на экран выведется строка: m=84.299999 k=-12 p=3.21500е+01 Здесь дважды используемый управляющий символ табуляции \t отделил друг от друга выводимые значения. Из примера видно, что соответствие между спецификаторами формата и элементами списка аргументов устанавливается в порядке их записи слева направо. К спецификатору формата могут быть добавлены числовые параметры: ширина поля и точность. Ширина – это число позиций, отводимых на экране под величину, а точность – это число позиций под дробную часть (после точки). Параметры записываются между значком % и символом формата и отделяются друг от друга точкой. Если внести изменения в оператор вывода, то получим: printf (“\n m=%5.2f\t k=%5d\ \t p=%8.2e \t p=%11.4e”, m,k,p,p); В результате на экране будет: m=84.30 k= -12 p= 32.15 p= 3.2150е+01 Если в пределы указанной ширины поля выводимое значение не помещается, то этот параметр игнорируется, и величина будет выводиться полностью. К спецификаторам формата могут быть добавлены модификаторы в следующих вариантах: %ld – вывод long int %hu – вывод short unsigned %Lf – вывод long double . В качестве оператора вывода можно также использовать еще один оператор, формат записи которого: puts(строка вывода); Строка вывода обязательно заключается в кавычки, т.е. в данной строке должна быть текстовая информация, в ней также допустимы для использования управляющие символы, но не допустим вывод значений переменных. Таким образом, применение данного оператора возможно для вывода пояснительных строк в программах. Например: puts(“Введите переменную”); Форматированный ввод с клавиатуры Оператор вызова функции scanf() имеет следующую структуру: scanf( форматная_строка, список_аргументов); Данная функция осуществляет чтение символов, вводимых с клавиатуры, и преобразование их во внутреннее представление в соответствии с типом величин. В функции scanf() форматная строка и список аргументов присутствует обязательно. 23 Например: scanf(”%f”,&a ); Здесь”%f” – форматная строка; &a – список аргументов, состоящий из одного элемента. Этот оператор производит ввод числового значения в переменную а. Символьную последовательность, вводимую с клавиатуры и воспринимаемую функцией scanf(), принято называть входным потоком. Функцию scanf() разделяет этот поток на отдельные величины, интерпрети-рует их в соответствии с указанным типом и форматом и присваиваетпереме-ным, содержащимся в списке аргументов. Список аргументов – это перечень вводимых переменных, причем перед именем каждой переменной ставится значок &. Это знак операции «взятие адреса переменной».Форматная строка заключается в кавычки (как и для printf()) и состоит из списка спецификаций. Каждая спецификация начинается со знака %, после которого могут следовать *ширина_поля модификатор спецификатор Из них обязательным элементом является лишь спецификатор. Для ввода числовых данных используются следующие спецификаторы: d - для целых десятичных чисел (тип int); u - для целых десятичных чисел без знака (тип unsigned int); f - для вещественных чисел (тип float) в форме с фиксированной точкой; e - для вещественных чисел (тип float) в форме с плавающей точкой; Звездочка (*)в спецификации позволяет пропустить во входном потоке определенное количество символов. Ширина поля – целое положительное число, позволяющее определить число символов из входного потока, принадлежащих значению соответствующей вводимой переменной. Как и в спецификациях вывода для функции printf(), в спецификациях ввода функции scanf() допустимо использование модификаторов h, l, L.Они применяются при вводе значений модификационных типов: hd - для ввода значений типа short int; ld - для ввода значений типа long int; lf, le - для ввода значений типа double в форме с фиксированной и плавающей точкой; Lf, Le - для ввода значений типа long double в форме с фиксированной и плавающей точкой; Если в программе необходимо ввести несколько переменных одновременно, то можно использовать один оператор: scanf (“%f%f%f”,&a,&b,&c);,для каждой переменной должен указываться свой спецификатор. Если последовательность ввода будет такой : 5 3.2 2.4 <enter> то переменные получат следующие значения : a=5,0 , b=3,2 , c=2,4. Вводить можно одновременно различные по типу переменные. Например: scanf (“%d%f%c”,&a,&,&c); в этом случае переменная а будет целого типа, b - вещественного, с – символьного. Разделителем в потоке ввода между различными значениями может быть любое количество пробелов, а также другие пробельные символы: знак табуляции, конец строки. Только после нажатия клавиши <enter> вводимые значения присвоятся соответствующим переменным. До этого входной поток помещается в буфер клавиатуры и может редактироваться. Потоковый ввод – вывод в Си++ Программируя на языке Си++, можно пользоваться средствами ввода-вывода стандартной библиотеки Си, подключаемой с помощью заголовочного файла stdio.h, как это делалось раньше. Однако в Си++ имеются свои специфические средства ввода-вывода. Это библиотека классов, подключаемая к программе с помощью файла iostream.h. В этой библиотеке определены в качестве объектов стандартные символьные потоки со следующими именами: cin - стандартный поток ввода с клавиатуры; cout - стандартный поток вывода на экран; Ввод данных интерпретируется как извлечение из потока cin и присваивание значений соответствующим переменным. В Си++ определена операция извлечения из стандартного потока, знак которой >>. Например, ввод значений в переменную х реализуется оператором cin>>x; Вывод данных определяется как помещение в стандартный поток cout выводимых значений. Выводиться могут тексты, заключенные в двойные кавычки, и значения выражений. Знак операции помещения в поток << . Примеры использования потокового вывода: cout<<a+b; cout<<”\n Результат = ”<<y; cout<<”x=”<<x<<”y=<<y<<”z”=<<z<<endl; Из примеров видно, что в выходном потоке можно использовать управля-ющие символы, как и при использовании функции printf(); перед каждым элементом вывода нужно ставить знак операции <<. Элемент вывода endl является так называемым манипулятором, определяющим перевод курсора на новую строку (действует аналогично управляющему символу \n). В процессе потокового ввода-вывода происходит преобразование из формы внешнего символьного представления во внутренний формат и обратно. Тип данных и необходимый формат определяется автоматически. Стандартные форматы задаются специальными флагами форматирования, которые устанавливаются с помощью функции setf(). Кроме того, на формат отдельных выводимых данных можно влиять путем применения специальных манипуляторов. Программа вычисления площади треугольника по формуле Герона на Си++ будет иметь следующий вид: 24 #include<iostream.h> #include<math.h> void main() {float a,b,c,p,s; cout<<”\na=”;cin>>a; cout<<”\nb=”;cin>>b; cout<<”\nc=”;cin>>c; p=(a+b+c)/2; s=sqrt(p*(p-a)*(p-b)*(p-c)}; cout<<”\n Площадь треугольника = ”<<s; } Упражнения 1.При выполнении программы # include<stdio.h> void main() {float a,b,c; int m,n; scanf(“%f%d%f%d%f”,&a,&m,&b,&n,&c); printf(“\na=%8.3f d=%7.2f c=%12.3e”, a,b,c); printf(“\nm=%10dn=%5d”,m,n); } с клавиатуры была введена следующая символьная последовательность: 32.4 87 0.05 4567 2314.45 <enter> Как будет выглядеть на экране результат работы программы? 2. Приведенная ниже программа решает следующую задачу: идет к-ая секунда суток. Определить сколько целых часов (h ) и целых минут (m) прошло с начала суток. Например, если к=13257=3 х 36000 +40 х 60 + 57, то h=3, m=40. Вывести на экран фразу: «Это … часов …минут». Вместо многоточий поставить вычисленные значения h и m. #include<stdio.h> void main() {long k; int h,m; printf(“Введите текущее время в секундах”); scanf(“%ld”,&k); h=k/3600; m=(k%3600)/60; printf(“Это %d часов %d %минут \n”, h,m); } Разобрать как работает данная программа. Переписать ее с использованием потокового ввода-вывода Си++. 3.Составить программу решения обратной задачи по отношению к предыдущей: дано количество часов и минут, прошедших от начала суток. Определить количество секунд. 4.Составить программу вычисления объема и площади поверхности куба по данной длине ребра. 5.Составить программу для вычисления корней квадратного уравнения. Программирование ветвлений Для программирования ветвящихся алгоритмов в языке Си имеется несколько различных средств. К ним относятся : 1) операция условия ?:, 2)условный оператор if 3) оператор выбора (переключатель) switch. Условный оператор Формат условного оператора на языке Си имеет следующий вид: if (выражение) оператор1;else оператор2; Это полная форма оператора, программирующая структуру полного ветвления. Обычно выражение – это некоторое условие, содержащее операции отношения и логические операции. Значение выражения приводится к целому и определяются в соответствии с правилом: равно нулю – ложь, не равно – истина. Если выражение истинно, то выполняется оператор1, если ложно – оператор2. Необходимо обратить внимание на следующие особенности синтаксиса условного оператора: выражение записывается в круглых скобках; точка с запятой после оператора1 ставится обязательно. Например, нахождение большего значения из двух переменных a и b: if (a>b) max=a; else max=b; 25 Блок – схема условного оператора оператора (полная форма) + Блок – схема условного оператора (неполная форма) - + - услов да нет оператор1 оператор1 усло вие да оператор2 да оператор Формат условного оператора для неполной формы имеет следующий вид: if (выражение) оператор; Задача нахождения большего из двух чисел может быть решена с использованием неполного ветвления следующим образом : max=a; if (b>a) max=b; Эту же задачу можно решить с помощью операции «условие». В роли операторов в ветвлениях могут выступать другие операторы ветвления, т. е возможно программирование вложенных ветвящихся структур. Рассмотрим примеры программирования таких структур. Вычислить функцию sign(x) – знак числа х, которая определена следующим образом: -1, если х<0 0, если х=0 1, если х>0. Пример1. Алгоритм с полным вложенным ветвлением: y= нет if (x<=0) if (x= =0) y=0; else y=-1; else y=1; да x<=0 x=1 y=1 y=-1 y=0 Пример2. Алгоритм с неполным ветвлением: y= 1 y=1; if (x<=0) if (x= =0) y=0; else y= -1; x<=0 x=0 y=0 y=-1 Пример 3. a>b c=a a=b b=c Упорядочить возрастанию по значения двух переменных a,b. нет да if (a>b) 26 { c=a; a=b; b=c;} cout<<”a=”<<a<<”b=”<<b; В данном примере использован составной оператор – последовательность операторов, заключенная в фигурные скобки. В Си фигурные скобки выполняют роль операторных скобок по аналогии с begin, end в Паскале. Точка с запятой обязательно ставится перед фигурной скобкой, а после фигурной скобки – нет. Рассмотрим пример вычисления площади треугольника по длинам трех сторон. Добавим в программу проверку условия правильности исходных данных: a,b,c должны быть положительными, а сумма длин каждой пары сторон треугольника должна быть больше длины третьей стороны. Пример 4. // Площадь треугольника #include<iostream.h> #include<math.h> void main() { float a,b,c,p,s; cout<<”\na=”;cin>>a; cout<<”\nb=”;cin>>b; cout<<”\nc=”;cin>>c; if ((a>0)&&(b>0)&&(c>0)&&(a+b>c)&&(a+c>b)&&(b+c>a)) { p=(a+b+c)/2; s=sqrt(p*(p-a)*(p-b)*(p-c)); cout<<”\nПлощадь треугольника =”<<s; } else cout(“\n Неверные исходные данные”); } Переключатель (оператор выбора) Переключатель можно рассматривать в двух вариантах: простой переключатель и альтернативный переключатель. Простому переключателю соответствует следующая блок-схема: Формат оператора выбора, соответствующий простому переключателю: выражен switch (выражение) ие М 1 М 2 оператоcase константа 1: список операторов; case константа 2: список операторов; р1 case константа 3: список операторов; оператоcase константа 4: список операторов; … … … р2 case константа n: список операторов; М 3 операто р3 М 4 происходит в следующем операто порядке: р4 1.Вычисляется выражение. default: список операторов; } Выполнение оператора 2.Полученное значение последовательно сравниваются с М операто константами, помещенным после служебного слова n рn case; при первом совпадении значений выполняются операторы, стоящие после двоеточия. 3. Если ни с одной из констант совпадения не произошло, то выполняются операто операторы после слова defaul default. Из блок-схемы видно, что после выбора константы и выполнения t соответствующих р этой константе операторов, будут выполняться все последующие операторы, включая и операторы относящиеся к default . Для того, чтобы «обойти» выполнение операторов на последующих ветвях, нужно принять специальные меры, используя операторы выхода или перехода. В этом случае необходимо применять альтернативный переключатель. Альтернативному переключателю соответствует следующая блок – схема: Рассмотрим фрагмент программы, который переводит числовую оценку знаний ученика в ее словесный эквивалент,согласно вузовской системе оценки знаний: 5 – «отлично» 4 - «хорошо» 3 - «удовлетворительно» 27 2 - «неудовлетворительно». выражен ие М1 М2 М3 М4 Мn Пример 5. операто #include<iostream.h> р1 void main() { int ball; оператоcout<<”\n Ввести оценку”;cin>>ball; switch (ball) р2 { case 2: cout<<”\t неудовлетворительно\n”; операто break; case 3: cout<<”\tудовлетворительно\n”; р3 break; case 4: cout<<”\tхорошо\n”; break; операто case 5: cout<<”\tотлично\n”; break; default:cout<<”\tнет такой оценки”; р4 break; } } операто р n переключателя используется оператор break – оператор прерывания. Его исполнение При реализации альтернативного завершает работу оператора выбора, т.е. происходит «обход» других ветвей. Например, если выполнитьоперато пример 5 со следующими данными, то в результате получим: defaul Ввести оценку 3 удовлетворительно t р такой оценки Ввести оценку 9 нет Если на всех ветвях убрать оператор break, то результат может выглядеть следующим образом: Ввести оценку 3 удовлетворительно хорошо отлично нет такой оценки В этом случае выполняются операторы на всех ветвях, начиная с константы 3. Возможны задачи, в которых такой порядок выполнения ветвей оператора выбора может оказаться полезным. Например, возвести вещественное число х в целую степень n, где n изменяется от1 до 5 y=1; switch(n) {case 5 : y=y*x; case 4 : y=y*x; case 3 : y=y*x; case 2 : y=y*x; case 1 : y=y*x;cout<<”y=”<<y; break; default : cout<<”Степень больше 5”; } Упражнения 1.Составить программу упорядочения по возрастанию значений в трех переменных. 2.Составить программу, которая выводит на экран меню: 1. Первое 2. Второе 3.Третье и в зависимости от выбранного пункта выдает одну из надписей: «Получите суп», «Получите пюре», «Получите компот», «Будете голодным». Написать два варианта программы: с использованием условного оператора и с использованием переключателя. 3.Составить программу решения квадратного уравнения ах2+bx+c=0 , учитывающую все возможные варианты исходных данных: 1) 2) a=0, b=0, с=0; a=0, b=0, с≠0; 28 3) 4) 5) a=0, b≠0; a≠0, d.>=0 (d-дискриминант); a≠0, d.<0. В каждом случае должно выводиться соответствующее решение или сообщение. Программирование циклов В Си, как и в Паскале, существуют все три типа операторов цикла: цикл с предусловием, цикл с постусловием и цикл с параметром. Цикл с предусловием Формат оператора цикла с предусловием: while (выражение) оператор; Блок –схема, соответствующая оператору цикла с предусловием имеет следующий вид: Цикл будет повторять свое выполнение, пока значение начальные присваивания выражения отлично от нуля, т.е. заключенное в нем условие цикла истинно. В качестве примера рассмотрим программу вычисления условие факториала целого положительного числа N!. Можно сопоставить программу решения этой задачи для языка программирования Паскаль и Си++. тело цикла Пример1. Программа на Паскале var f : longint; i,n:integer; begin write (‘n=’); readln(n); f:=1;i:=1; while I<=n do begin f:=f*i; i:=i+1; end; writeln (n,’!=’,f) end. program factor; long int f; int i,n; void main() {count<<”n=”; cin>>n; f=i=1; while (i<=n) f=f*i++; Программа на Си++ #include <iostream.h> cout<<”\n”<<n<<”!=”<<f; } Если сравнить программы между собой, то видно, что в Си-программе используется более лаконичный способ записи операторов присваивания. Например, оператор присваивания f=f*i++; можно записать еще короче: f*=i++; В языке программирования Си можно использовать оператор while(1) Использование в качестве выражения константы 1 приводит к тому, что условие повторения цикла все время остается истинным. Рассмотрим еще один пример использования оператора цикла while. Составим программу итерационного вычисления суммы гармонического ряда: 1+1/2+1/3+… с заданной точностью ε. // Сумма гармонического ряда # include <iostream.h> # include <limits.h> void main() { int n=1; double s=0,eps; cout<<”Точность”; cin>>eps; while (1.0/n>eps&&n<INT_MAX) s+=1./n++; cout<<”\n Сумма=”<<s; } Файл limits.h, подключаемый препроцессором, содержит определения предельных констант для целых типов данных. Константа с именем INT_MAX равна максимальному значению типа int в данной реализации компилятора. Цикл с постусловием. Формат записи оператора цикла с постусловием имеет следующий вид : do оператор while (выражение); Цикл будет выполняться до тех пор, пока выражение отлично от нуля, т.е. заключенное в нем условие цикла истинно. Выход из цикла происходит после того, как значение выражения станет ложным, иными словами равным нулю. В 29 отличие от оператора repeat… until, используемого в Паскале, где в конце пишется условие выхода из цикла , в операторе do…while в Си в конце пишется условие повторения цикла. В качестве примера рассмотрим программу вычисления N!, в которой используется цикл с постусловием. Сопоставим программу с аналогичной на Паскале. Пример. Программа на Паскале Программа на Си program factorial; //Вычисление факториала var f:longint; #include<iostream.h> I,n:integer; long int f; int I,n; begin void main() write(‘n=’); readln(n); { cout<<”n=”; cin>>n; f:=1;i:=1; f=i=1; repeat do f:=f*i; i:=i+1; f*=i++; until i>n; while(i<=n); writeln(n,’!=’’f) cout<<”\n”<<n<<”!=”<<f; end. } Блок-схема, соответствующая циклу с постусловием представлена на рисунке. оператор2 Особенность данного типа цикла заключается в том, что тело цикла обязательно выполнится хотя бы раз, не зависимо выполняется условие цикла или нет. оператор1 Цикл с параметром. Формат оператора цикла с параметром: условыражение_2; выражение_3) for (выражение_1; оператор; в Выражение_1 выполняется только один раз в начале цикла. Обычно оно определяет начальное значение параметра цикла (инициализирует параметр цикла). Выражение_2 – это условие выполнения цикла. Выражение_3 обычно определяет изменение параметра цикла, оператор – тело цикла, которое может быть простым или составным. В последнем случае используются фигурные скобки. Алгоритм выполнения цикла for можно представить в виде следующей блок-схемы, расположенной ниже. Необходимо обратить внимание на то, что после вычисления выражения 3 происходит возврат к вычислению выражения 2, т.е. происходит проверка условия повторения цикла. Рассматривая все компоненты блок-схемы можно сделать заключение: выражение 1 – это начальные присваивания, выражение 2 – это логическое выражение для проверки условия выхода из цикла, оператор – это оператор или группа операторов, образующих тело цикла, выражение 3- это изменение параметров цикла.. С помощью цикла for нахождение n! Выражение 1 можно организовать следующим образом: нет f=1; for (i=1;i<=n;i++) f=f*i; Используя операцию «запятая», Выражение2 можно в выражение 1 внести инициализацию значений сразу нескольких переменных: for (f=1,i=1;i<=n;i++) f=f*i; ОПЕРАТОР Некоторых элементов в операторе for может не быть, однако разделяющие их точки с запятой обязательно должны присутствовать. В следующем примере инициализирующая часть вынесена из Выражение 3 оператора for: Ниже показан еще один вариант вычисления n!. В нем на месте тела цикла находится пустой оператор, т.е. оператор, не содержащий никаких действий, а вычислительная часть внесена в выражение3. for (f=1;i=1; i<=n; f=f*i,i++); Этот же оператор можно записать в следующей форме: for (f=1;i=1; i<=n; f*=i++); 30 В языке Си оператор for является достаточно универсальным средством для организации циклов. С его помощью можно программировать даже итерационные циклы, что невозможно в Паскале. Представляем пример вычисления суммы элементов гармонического ряда, превышающих заданную величину ε: for (n=1,s=0; 1.0/n> eps && n<INT_MAX; n++) s+=1.0/n; И наконец, эта же самоя задача с пустым телом цикла: for (n=1,s=0; 1.0/n> eps && n<INT_MAX; s+=1.0/n, n ++); Рассмотрим другой фрагмент программы на Си++, который содержит два вложенных цикла for. В этом фрагменте запрограммировано получение на экране таблицы умножения. for (x=2;x<=9;x++) for (y=2;y<=9;y++) cout<<”\n”<<x<<”*”<<y<<”=”<<x*y; На экране будет получен результат: 2*2=4 2*3=6 ... 9*9=81 Оператор continue. Если выполнение очередного шага цикла требуется завершить до того, как будет достигнут конец цикла, используется оператор continue. Например, ниже приведенный фрагмент программы обеспечивает вывод на экран всех четных чисел в диапазоне от 1 до 100. for (i=1; i<=100; i++) { if (i%2) continue; cout <<”\t”<<i;} Для нечетных значений переменной i остаток от деления на 2 будет равен единице, этот результат воспринимается как значение «истина» в условии ветвления, и выполняется оператор continue. Он завершит очередной шаг цикла, выполнение цикла перейдет к следующему шагу. Оператор goto. Оператор безусловного перехода goto существует в языке Си, как и во всех языках программирования. Однако с точки зрения структурного программирования его применение необходимо ограничить. Формат оператора имеет следующий вид: goto метка; Метка представляет собой идентификатор с последующим двоеточием, т. е. становится помеченным оператором. Одна из ситуаций, в которых использование goto является оправданным – это необходимость «досрочного» выхода из вложенного цикла. Например: for (…) { while (…) { for (…) …goto 5 …} } } 5: cout<<”выход из цикла”; При использовании оператора безусловного перехода необходимо учитывать следующие ограничения: - нельзя входить внутрь блока извне; - нельзя входить внутрь условного оператора (if …else…); - нельзя входить внутрь переключателя; - нельзя входить внутрь цикла. Упражнения Используя циклы while, do while, for, написать три варианта программы получения на экране таблицы синусов для значений аргумента в диапазоне от 0 до π/2 с заданным числом шагов. 2. Вычислить и вывести на экран все члены числового ряда 1, 1/2!, 1/3!, …, 1/n!, значение которых превышает 10-5. 3. Напечатать в возрастающем порядке все трехзначные числа, в десятичной записи которых нет одинаковых цифр. 4. Дано целое n>2. Напечатать все простые числа из диапазона [2,n]. 5. Составить программу перевода целого десятичного числа в двоичную систему счисления. 1. Массивы Массив- это структура однотипных элементов, занимающих непрерывную область памяти. С массивом связаны следующие его свойства: имя, тип, размерность, размер. Формат описания массива следующий: тип_элементов имя [константное_выражение]; Константное выражение определяет размер массива, т.е. число элементов массива. Например, согласно описанию int a[5]; объявлен массив с именем а, содержащий 5 элементов целого типа. Элементы массива обозначаются индексированными именами. Нумерация индексов начинается с нуля, т. е., нижнее значение индекса равно 0: a[0], a[1], a[2], a[3], a[4]. В отличие от Паскаля в Си нельзя определять произвольные диапазоны для индексов. Размер массива, указанный в описании, всегда на единицу больше максимального значения индекса. Размер массива может 31 явно не указываться , если при его объявлении производиться инициализация значений элементов. Например: int p[] ={2,5,9,0,6}; В этом случае создается массив из пяти элементов со следующими значениями: р[0]=2, р[1]=5, p[2]=9, p[3]=0, p[4]=6. Общей формой оператора, создающего и инициализирующего массив является: тип имя_массива [индекс]= {значение1,значение[,… значение n],}; Необходимо указать значения для каждого из элементов массива. Если значений будет недостаточно, то оставшиеся элементы будут заполнены произвольно. Например, в результате следующего объявления массива int Р[6]={5,3,2} ; будет создан массив из шести элементов. Первые три элемента получат значения при инициализации. Значения остальных будут либо неопределенными, либо равны, если массив внешний или статистический. Можно инициализировать и многомерные массивы. Для этого необходимо представлять, как производится в Си подобная инициализация. Она начинается с последнего измерения. Например, Рассмотрим заполнение трехмерного массива, состоящего из восьми элементов. int A[2] [2] [2]={1,2,3,4,5,6,7,8}; Массив начинает заполняться с конца, так что значения 1 и 2 попадут соответственно в элементы и индексом [0][0][0] и [0][0][1]. Далее процедура продолжается, пока числа 7и 8 не окажутся соответственно в элементах массива А с индексами [1][1][0] и [1][1][1]. Можно задать код более понятным, если применить дополнительные фигурные скобки в инициализирующей части оператора – по одному уровню скобок для каждого измерения массива. Например: int A[2] [2] [2]={{{1,2},{3,4}},{{5,6},{7,8}}}; Вначале в массив введутся четыре первые значения, причем из – сначала первые по два. Рассмотрим еще пример: int a[3][2]={{10,20},{30,40},{50,60}}; . Эта запись эквивалентна последовательности операторов присваивания а[0][0]=10; a[0][1]=20; a[1][0]=30; a[1][1]=40; a[2][0]=5-; a[2][1]=60;. Этот же результат будет получен и по одному списку инициализации , а именно, int a[3][2]={ 10,20,30,40,50,60};. С помощью инициализации можно присваивать значения не всем элементам многомерного массива. Например, чтобы инициализировать только элементы первого столбца матрицы, её можно описать следующим образом: float a[4][6]={{1},{2},{3},{4}}; Следующее описание формирует “треугольную” матрицу в целочисленном массиве из пяти строк и четырех столбцов. int x[5][4]={{1},{2,3},{4,5,6},{7,8,9,10}}; Последняя пятая строка останется незаполненной. Представим схематичное размещение элементов массива: строка столбец Значение 1 1 0 2 - 3 - 4 - 1 2 1 2 3 3 - 4 - 1 4 2 2 5 3 6 4 - 1 7 3 2 8 3 9 4 10 1 - 4 2 - 3 - 4 - Чтобы получить доступ к данным массива, надо указать с помощью индексов, какой элемент надо взять. В остальном работа с массивом – это работа с обычной переменной. Функции Разберемся с вопросом, как в Си/Си++ реализуется механизм работы с подпрограммами. Следует заметить, что этот механизм существенно отличается от реализации на Паскале. В Си используется лишь один тип подпрограмм (в отличие от Паскаля) это - функция. Вообще не принято употреблять термин «подпрограмма», потому, что функция является основной программной единицей в Си, минимальным исполняемым модулем. Любая программа обязательно включает в себя основную функцию с именем main(). Если в программе используются и другие функции, то они исполняют роль подпрограмм. К примеру, необходимо составить программу нахождения наибольшего значения из трех величин, т.е. – max(a,b,c). Для решения можно использовать вспомогательный алгоритм, который позволяет находить максимальное значение из двух величин, т.к. справедливо равенство: max(a,b,c) = max (max (a,b),c). Можно утверждать, что каждая программа на языке программирования Си – это совокупность функций. Функция является отдельным именованным фрагментом, выполняющим конкретную задачу. Сама по себе функция напоминает отдельную программу. В приведенном выше примере, чтобы найти максимальное значение из трех чисел, можно использовать функцию нахождения максимального из двух и применить данную функцию дважды. Функции можно вызывать из основной программы, они могут получать данные также из основной программы и возвращать ей результат работы. По завершению работы функции , управление программой передается оператору, следующему сразу за тем оператором, который вызвал функцию. Все функции разделяются на две категории: 1) это те функции, которые создаются индивидуально; 2) функции, находящиеся в пакете компилятора Си;. Первая категория функций называется функциями, определенными пользователем, вторая – библиотечными. Функции, определенные пользователем состоят из трех частей: прототипа функции, определения, тела функции. а) прототип функции – это сообщение компилятору, что определение функции будет приведено программе ниже. Все прототипы функций должны располагаться до начала функции main(). б) определение функции следует за функцией main(). Определение состоит из единственного оператора, который задает функции имя и сообщает тип данных, который функция ожидает получить при вызове, а также о типе значения, возвращаемого функцией в вызывающую программу. 32 в) тело функции – набор операторов, которые выполняют определенную работу. Тело функции должно быть заключенным в фигурные скобки и располагаться сразу за определением функции. Существуют определенные правила при использовании и наименовании функций: имя функции не должно совпадать со служебными словами, именами библиотечных функций и другими именами в программе. Структура стандартного определения функции имеет вид: тип имя_функции (спецификация формальных параметров) { тело функции } Тип функции – это тип возвращаемого функцией результата. Если функция не возвращает никакого результата, то для нее указывается тип void. Имя функции – идентификатор, задаваемый программистом или main для основной функции. Спецификация параметров – это либо «пусто», либо список имен формальных параметров функции с указанием типа для каждого из них. Тело функции – это либо составной оператор, либо блок. Признаком блока является наличие описаний программных объектов (переменных, массивов и т.д.), которые действуют в пределах этого блока. Блок, как и составной оператор, ограничивается фигурными скобками. В Си действует правило: тело функции не может содержать в себе определения других функций. Иначе говоря, недопустимы внутренние функции, как это принято в Паскале. Из всякой функции возможно обращение к другим функциям, однако они всегда являются внешними по отношению к вызывающей. Важным оператором тела функции является оператор возврата из функции в точку её вызова: return ; или return выражение; Выражение в операторе возврата задает возвращаемое функцией значение. Для функции типа void, не возвращающей никакого значения, выражение в операторе return ; отсутствует, другими словами функция return ; не возвращает никакого значения в качестве своего результата.. Применение оператора return допустимо и в функции main(). Выполнение оператора return ; или return выражение; в функции main() приводит к завершению программы. Результатом функции return выражение; является значение указанного выражения. Тип этого выражения должен совпадать с типом функции, либо относиться к числу типов, допускающих автоматическое преобразование к типу функции. Оператор return ; может в явном виде отсутствовать в теле функции. В таком случае его присутствие подразумевается перед закрывающей тело функции фигурной скобкой. Такая подстановка производится компилятором. Рассмотрим пример, в котором определим функцию для вычисления объема цилиндра. Допустим, что у функции есть два параметра, значение большего из которых считается радиусом цилиндра, а меньший определяет значение высоты цилиндра. Будем считать, что g и h- параметры, позволяющие вычислить объем цилиндра: g*g*h*PI, если g>h или g*h*h*PI, если g<h. Оформим определение функции, оно будет иметь следующий вид: float w ( float g, float h) { if (g>h) return 3.14*g*g*h; else return 3.14*g*h*h; } Строка номер один - float w ( float g, float h) – это и есть определение функции. Все остальные строки образуют тело функции. По стандарту языка Си предусмотрено обязательное описание функции со стандартным заголовком, с помощью прототипа. Если определение функции вынесено за пределы основной программы, то указание прототипа в программе обязательно. Прототип - это тоже определение функции, но в отличие от нее прототип всегда заканчивается обязательно точкой с запятой, и имена формальных параметров в прототипе могут не указываться. Формат прототипа имеет следующий вид: тип_результата имя_функции (спецификация формальных параметров); Определение функции выглядит почти одинаково с прототипом и отличается от него только отсутствием точки с запятой в конце строки. Необходимо помнить, что возвращаемый тип и тип аргументов, а также их число должны в прототипе и определении функции быть одинаковы. Например, float at (int c, int n,float t) - это определение функции с именем at; float at (int c, int n, float t); - прототип функции; float at (int, int, float ); - прототип функции; Из примера видно, что, действительно определение и прототип имеют одинаковую структуру представления: имя функции – at, в результате выполнения функции будет возвращаться значение типа float, при вызове функции она должна получить три переменные (две – целого типа, одну - вещественного). Имена переменных, появляющихся в прототипе и определении функции, являются средством передачи в функцию данных. Эти переменные называются аргументами. Для того чтобы вызвать функцию необходимо поместить в соответствующем месте имя функции с необходимыми аргументами. Аргументы в операторе, вызывающем функцию, называются параметрами. Параметры должны всегда размещаться в скобках вслед за именем функции, как и аргументы. рассмотрим применение функции на конкретном примере. Задача. Вычислить Cnm = факториала. # include <stdio.h> int fact (int k ) { int i, j; n! , гдеn>m>0, m, n –целые числа. Используем функцию для вычисления m!(n - m)! ( это определение функции для вычисления факториала k!) (вспомогательные переменные) 33 for (i=1, j=1; i<=k; i++) (цикл вычисления) j*=i; return j; } (конец функции ) // Вычисление биноминального коэффициента void main() { int n, m, nmc, nm; (nm – значение (n-m)) (nmc – значение биноминального коэффициента) while (1) { printf (“\n Ввести n=”); scanf (“%d”, &n); printf (“\n Ввести m=”); scanf (“%d”, &m); if (m>=0 && n>=m && n<10) break; printf (“Ошибка ! Необходимо задать 0<=m<=n<=10”); } nm = n-m; nmc = fact (n)/fact (m)/fact (nm); printf (“\n Коэффициент = %d”, nmc); } (конец основной программы) Из примера видно, что функция fact () в основной программе не описана. Другими словами прототип здесь не указывается , т.к. определение функции находится в одном и том же файле main(), причем определение функции размещается выше, чем вызов данной функции. Рассмотрим следующий пример, в котором наличие прототипа обязательно. Задача. Вычислим объем цилиндра, используя в качестве функции приведенный выше фрагмент нахождения объема, в зависимости от величины радиуса. // Вычисление объема цилиндра # include <stdio.h> main() { float w (float, float); (прототип функции) float a,b; (исходные данные) int j; (счетчик попыток ввода) for (j=0; j<5; j++) (цикл ввода данных) { printf (“\n Ввести а=”); scanf (“%f”, &a); printf (“\n Ввести b=”); scanf (“%f”, &b); if (a>0.0 && b>0.0) break; printf (“\n Ошибка ввода!”);} if (j==5) { puts (“\n Очень плохо вводите данные”); return;} (аварийное отключение программы) printf (“\n Объем цилиндра =%f”, w(a,b)); } (конец основной программы) float w (float g, float h) (определение функции) { if (g>h) return (3.14*g*g*h); else return (3.14*h*h*g); } В основной программе использован оператор return, прерывающий исполнение программы. Если количество неудачных попыток ввода равно 5, то сработает оператор return, В программе использован прототип функции, это необходимо, т.к. функция возвращает значение и определена позже, чем обращение к ней. В данном примере w() использовано в качестве фактического параметра функции printf(). В первой части данного курса лекций был рассмотрен пример, в котором вычислялись сложные проценты по вкладам. Усложним эту задачу. Задача. Вычислить сложные проценты и выплаты по ссуде, применив функции. Для решения задачи необходимо ввести основную сумму, процентную ставку и время. Ввод данных и распечатка результатов производится в функции main(). Действия для вычисления сложных процентов и выплат по ссуде будут реализованы в функциях rr и ss. #include <stdio.h> #include <math.h> int r; float balance, rate, future, months; /* Прототипы функций */ 34 float rr (float, float, float); float ss (float, float, float); main() { r=1; puts (“Программа калькуляции сложных процентов”); while (r!=3) { puts(“\n Ввести начальный баланс =”); scanf (“%f”, &balance); puts(“\n Ввести процентную ставку =”); scanf (“%f”, &rate); puts(“\n Ввести число месяцев =”); scanf (“%f”, &months); // Проверка введенных значений if (( balance<=0) || (rate<=0) ||(month<=0)) puts (“Введены неверные данные”); else { puts(“Ввести 1 для сложных процентов, 2- для ссуд, 3- для выхода”); scanf (“%d”, &r); if (r==1) { puts (“Вычисление сложных процентов”); future = rr (balance, rate, months); printf (“\n Новое значение баланса = %f \n”, future); } if (r==2) printf (“ Вычисление выплат по ссуде”); future = ss (balance, rate, months); printf (“\n Новое значение баланса = %f \n”, future); } }} // Определения функций float rr (float balance, float rate, float month) { return (balance* pow(2.7183, (rate/1200)* months)); } float ss (float balance, float rate, float month) {return((( rate/1200)* month)*balance *(pow(2.7183, (rate/1200)* months))); } Сопоставим программу вычисления наибольшего общего делителя для суммы, разности и произведения двух чисел на Паскале и на Си++. Программа на Паскале Программа на Си++ program NOD3; # include <iostream.h> var a, b, rez : integer; #include <math.h> function NOD2 (m, n:integer):integer; int NOD2 (int, int); begin void main() while m<>n do { int a, b, rez; if m>n then m:=m-n; cout<<”a=”; cin>>a; else n:=n-m; cout<<”b=”; cin>>b; NOD2:=m; rez=NOD2(NOD2(a+b,abs(a-b)),a*b); end; } begin int NOD2 (int m, int n) write (“a=”); { while (m!=n) readln ()a; { if (m>n) m=m-n; write (“b=”); else n=n-m; readln (b); } rez:=NOD2(NOD2(a+b,abs(a-b)), a*b); return m; writeln (“NOD =”, rez); } end. Может возникнуть вопрос: если основная часть программы является функцией, то кто (или что) её вызывает? Ответ состоит в следующем: программу вызывает операционная система при запуске программы на исполнение. При составлении программ широко используются библиотечные функции. Библиотечными называются вспомогательные функции, хранящиеся в отдельных файлах. Стандартные библиотеки входят в стандартный комплект системы программирования на Си\Си++. Чтобы использовать стандартные функции необходимо подключить к программе заголовочные файлы соответствующих библиотек. Это выполняется с помощью директивы #include с указанием имени заголовочного файла. Например, #include<stdio.h> . Все заголовочные файлы имеют расширение h (от header англ.). Эти файлы содержат прототипы функций библиотеки. На стадии претрансляции происходит подстановка прототипов перед основной функцией, после чего компилятор в состоянии контролировать 35 правильность обращения к функциям. Сами программы, реализующие функции, хранятся в форме объектного кода и подключаются к основной программе на стадии редактирования связей (при работе компоновщика). Задача. Зная декартовы координаты вершин выпуклого четырехугольника, вычислить его площадь. 2 1 Математическое решение этой задачи следующее. Обозначим координаты вершин четырехугольника так : (x1,y1), (x2,y2,), (x3,y3), (x4,y4). Площадь 3 четырехугольника можно вычислить как сумму 3 площадей двух треугольников. В свою очередь, площадь каждого треугольника вычисляется по формуле Герона. 4 Для применения формулы Герона нужно найти длины сторон. Длина стороны между первой и второй вершинами вычисляется по формуле: 2 L12 = (x1 - x 2 ) 2 + (x 1 - x 2 ) . Аналогично вычисляются длины других отрезков. Таким образом, для решения основной задачи _ вычисления площади четырехугольника – требуется вспомогательный алгоритм вычисления площади треугольника, для которого, в свою очередь, необходим вспомогательный алгоритм вычисления длины отрезка по координатам концов. Ниже приведена программа решения поставленной задачи. // Площадь выпуклого четырехугольника #include <iostream.h> #include <math.h> #include <conio.h> typedef double D; // Переименование типа double D line (D,D,D,D); // Прототип функции D geron (D,D,D,D,D,D); //Прототип функции // Основная функция { D x1, y1, x2, y2, x3, y3, x4, y4, s; clrscr(); cout<<”x1=”; cin>>x1; cout<<”y1=” ; cin>>y1 ; cout<<”x2=”; cin>>x2; cout<<”y2=” ; cin>>y2 ; cout<<”x3=”; cin>>x3; cout<<”y3=” ; cin>>y3 ; cout<<”x4=”; cin>>x4; cout<<”y4=” ; cin>>y4 ; s=geron(x1,y1,x2,y2,x3,y3)+geron(x1,y1,x3,y3,x4,y4) ; cout<< ”Площадь четырехугольника =”<< s;} // Определение функции line D line (D a, D b, D c, D d) { return sqrt (a-c)*(a-c)+(b-d)*(b-d));} // Определение функции geron D geron (D a1, D a2, D b1, D b2, D c1, D c2) { D p, ab, bc, ca; ab = line(a1,a2,b1,b2); bc = line(b1, b2, c1, c2); ca= line(c1, c2, a1, a2); p = (ab+bc+ca)/2; return sqrt (p*(p-ab)*(p-bc)*(p-ca)); } В этой программе используются функции из трех стандартных библиотек с заголовочными файлами iostream.h, math.h, conio.h. Файл conio.h содержит функции, предназначенные для управления выводом на экран в символьном режиме. Она является аналогом модуля CRT в Паскале. В программе из этой библиотеки используется функция clrscr() – очистка экрана. Еще одним новым элементом в приведенной программе является строка typedef double D; Служебное слово typedef представляет собой спецификатор типа, позволяющий определять синонимы для обозначения типов. В результате в рассматриваемой программе вместо длинного слова double для обозначения того же самого типа можно употреблять одну букву D. Данное описание действует глобально и распространяется как на основную, так и на вспомогательные функции. Необходимо обратить внимание на одно обстоятельство. В функции geron имеются обращения к функции line, а в основной функции – обращение только к функции geron. Для компилятора важно, чтобы перед вызывающей функцией присутствовал или прототип, или определение вызываемой функции. Поэтому если из данной программы убрать прототип line,т о ошибки не будет. Но если одновременно с этим поменять местами определения функций line и geron, то компилятор выдаст сообщения об ошибке. Рекурсивное определение функций. Как и в Паскале, в языках Си/Си++ допускается рекурсивное определение функций. Рассмотрим определение рекурсивной функции на классическом примере вычисления факториала целого положительного числа. long factor (int n) 36 { if (n<0) return 0; if (n==0) return 1; return n*factor(*n-1); } В случае если при вызове функции будет задан отрицательный аргумент, она вернет нулевое значение – признак неверного обращения. Глобальные и локальные переменные Областью действия описания программного объекта называется часть программы, в пределах которой действует (учитывается) это описание. Если переменная описана внутри некоторого блока, то она оказывается локализованной в этом блоке и из других блоков, внешних по отношению к данному, «не будет видна». Если описание переменной находится вне блока и предшествует ему в тексте программы, то это описание действует внутри блока и называется глобальным. Глобальная переменная «видна» из блока. Например: double x; int fun() { int y;…} void main() {float y ;...} Переменная x является глобальной по отношению к функциям fun(), main() и, следовательно, может в них использоваться. В функциях fun() и main() имеются локальные переменные с одинаковым именем y. Однако это разные величины , никак не связанные друг с другом. Поскольку переменная x является общей для обеих функций, то они могут взаимодействовать через x друг с другом. При обращении к функции передача значений возможна как через параметры, так и через глобальные переменные. Используя этот механизм, в программах на Си можно реализовывать функции, работающие подобно процедурам в Паскале. Пример . int z; //Описание глобальной переменной void MAX (int x, int y) { if (x>y) z=x ; else z=y ; } # include <iostream.h> void main() { int a,b,c; cout<<”a=”; cin>>a; cout<<”b=”; cin>>b; cout<<”c=”; cin>>c; MAX(a,b); MAX(z,c); cout<<”max=”<<z ; } Результат выполнения функции MAX заносится в глобальную переменную z, которая «видна» также и из основной функции. Поэтому при втором обращении эта переменная играет одновременно роль аргумента и результата. Здесь оператор обращения к функции выглядит подобно обращению к процедуре на Паскале, а глобальная переменная z играет роль var-параметра. Другими словами можно заключить следующее: в Си предусмотрена возможность ограничения «поля деятельности» переменной. Можно ограничить использование переменной пределами только одной функции. Даже, если в другой функции есть переменные с точно таким же именем, эти переменные не будут иметь друг с другом никакого отношения. Они ведут себя как две отдельные переменные с различными именами. Самым большим преимуществом управления областью действия является изоляция данных в функции, предотвращающая вмешательство других процедур. Переменная, объявленная внутри функции, доступна только в её пределах. Такая переменная является локальной и её содержимое становится недоступным другим процедурам. Принцип этот имеет и обратную силу. Если переменные функции main() объявляются как локальные, то функции, вызванные из main(), не смогут изменить их. Например: # include<stdio.h> Запуск программы выдаст на экран int x; результат 100 и 99. void myfunction (void); main() Это результат запуска программы { x=100; с одной переменной, чья область printf(“%d\n”, x); действия делает её доступной из всех x=99; функций программы. myfunction(); } void myfunction (void) {printf(“%d\n”,x); } 37 Сравним первую программу со второй: # include<stdio.h> Строка, в которой объявляется x, была void myfunction (void); передвинута внутрь функции main. Кроме main() того, этаже строчка была скопирована и {int x; вставлена в функции myfunction. Других x=100; изменений нет. А результат получим printf(“%d\n”, x); следующий: x=99; 100 myfunction(); любое void myfunction (void) т.к. область действия ограничена { int x; функцией, где она была объявлена. printf(“%d\n”,x); } В первом примере переменная х сохранила значение 99, которое ей было присвоено в main(). Это значение и было распечатано функции myfunction(), хотя переменная не передавалась ей в списке параметров. Во втором варианте, значение переменной дает случайный результат. Во втором примере х по сути –это две совершенно разные переменные, не имеющие отношения друг к другу. Второй х создается, когда начинает выполняться функция myfunction(). Так как ей не было присвоено никакого значения, то printf распечатывает старые данные, оставшиеся в памяти. Проведем еще изменения в этом примере: # include<stdio.h> void myfunction (void); myfunction (void) пытается изменить main() значение х перед тем, как возвратить {int x; управление в main(). На экране будет: x=100; 100, 87-случайное число, 99. printf(“%d\n”, x); Значение х в main() остается x=99; равным 99,хотя myfunction, как myfunction(); будто меняет его на 125. printf(“%d\n”, x); void myfunction (void) { int x; printf(“%d\n”,x); x=125; } Классы памяти. Под всякую переменную, используемую в программе. должно быть выделено место в памяти ЭВМ. Выделение памяти может происходить либо на стадии компиляции (компоновки ) программы, либо во время ее выполнения. Существует четыре класса памяти Выделяемой под переменные: - автоматическая (ключевое слово auto); - внешняя (extern); - статическая (static); - регистровая (register). Под глобальные (внешние) переменные выделяется место во внешней памяти( это оперативная память класса extern). Внешняя переменная- это переменная, которая создана вне любой из функции программы. Объявление такой переменной предшествует функции main(). Например: int x; float y; main() Внешняя переменная доступна для всех функций программы. Понятие внешняя переменная и глобальная переменная – одно и тоже. Внешнюю (глобальную) переменную достаточно объявить только один раз. Один из наиболее важных принципов структурного программирования заключается в том, что используемые в программах функции, необходимо проектировать как можно более изолированными друг от друга. Функция должна только принимать параметры, которые передаются ей через список её аргументов, и просто возвращать ожидаемый от неё результат посредством оператора return. Чтобы применение внешних переменных согласовывалось с принципами структурного программирования, необходимо сделать явным использование таких переменных в каждой функции. Т.е., если необходимо объявить переменную, находящуюся внутри блока, как внешнюю (глобальную), то необходимо выполнить следующее – добавить в разделе описания переменных ключевое слово extern, что явным образом сообщает, что функция использует внешнюю переменную. Внешние переменные доступны всем в любое время, локальные же переменные активны только во время исполнения объявления её функцией. Локальные переменные лучше включать в тело функции сразу вслед за её определением, непосредственно после открывающей блок операторов функции фигурной скобки. Например: int z; В данном примере переменная z будет main() являться внешней, а переменные x,y будут { int x,y; являться локальными. Объявим переменную внутри функции в качестве внешней, используя ключевое слово extern: 38 myfunction() { extern int x; …… } Переменная x является внешней переменной. Рассмотрим следующий фрагмент float myfunction (int x,int y) { int z; Аргументы x и y и переменная z являются локальными переменными по отношению к функции myfunction. Можно сделать переменную настолько локальной, что они не будут «видны» процедуре, в которой объявляется. Если объявить переменную в блоке операторов, то она будет локальной именно для этого блока. Другие блоки данной процедуры будут ей недоступны. Переменные надо объявлять сразу после открывающей фигурной скобкой, что помечает начало блока операторов. Подходящим случаем для подобных объявлений переменных являются циклы for. В качестве счетчика такого цикла можно использовать локальную в цикле переменную, не заботясь о том, что где-то в программе есть переменная с тем же именем. Рассмотрим пример, в котором переменная i встречается дважды, но каждая из них локальна в своем блоке. # include<stdio.h> main() Переменная i во внутреннем { int i; цикле никак не влияет на for (i=1; i<=10; i++) переменную i внешнего цикла, { хотя имена у этих переменных { int i; одинаковы. for (i=5; i<=7; i++) printf (“%d”, i); } } } Содержимое локальной переменной уничтожается, когда управление покидает блок, в котором она объявлена, если не оговорить это специально. Локальные переменные, объявленные внутри блоков, распределяются в автоматической памяти, работающей по принципу стека. Выделение памяти происходит при входе выполнения программы в блок, а при выходе из блока память освобождается. Ключевое слово auto писать не обязательно (по умолчанию) т. е всякая локальная переменная будет автоматической. Статическая память выделяется под переменные, локализованные внутри блока, но в отличие от автоматической памяти не освобождаются при выходе из блока. Таким образом, при повторном вхождении в блок статическая переменная сохраняет свое прежнее значение. Чтобы создать статическую переменную, нужно явно объявить её как static. Общий вид объявления статической переменной имеет вид: static тип имя; Например: static int tt; Инициализация статической переменной происходит только при первом вхождении в блок. Если инициализация явно не указана, то переменной автоматически присваивается нулевое начальное значение. Статические переменные можно использовать, например, для организации счетчика числа вхождений в блок. Регистровая память выделяется под локальные переменные. Регистры процессора - самый быстрый и самый маленький вид памяти. Они задействованы при выполнении практически всех операций в программе. Поэтому возможность распоряжаться регистровой памятью лучше оставить за компилятором. Упражнения 1.Найти ошибку в программе: #include<iostream.h> void main() { int a=1, b=2, c; c=sum(a, b); cout<<c; } int sum (int x, int y) { return x+y ;} 2. Определить результат выполнения программы: #include<iostream.h> void mul (int, int); int s; void main() { int a=2, b=3; mul(a,b); a=2*s; mul(a,b); cout<<s; } void mul (int x, int y) { s=x*y; } 3. Составить программу для вычисления площади кольца по значениям внутреннего и внешнего радиусов, используя функцию вычисления площади круга. 4. Даны три целых числа. определить сумма цифр которого из них больше. Подсчет суммы цифр организовать через функцию. 39 5. Составить функцию, определяющую, является ли её целый аргумент простым числом. Использовать эту функцию для подсчета количества простых чисел в последовательности из десяти целых чисел, вводимых с клавиатуры. 6. Даны натуральные числа n и m : найти НОД (n, m). Составить рекурсивную функцию вычисления НОД, основанную на соотношении НОД(n, m)= НОД(n, r), где r – остаток от деления n на m (n>m). Указатели Статическими называются такие величины, память под которые выделяется во время компиляции и сохраняется в течение всей работы программы. Существует и другой способ выделения памяти под данные, который называется динамическим. В этом случае память под величины отводится во время выполнения программы. Такие величины называются динамическими. Использование динамических величин предоставляет программисту ряд дополнительных возможностей. Во-первых, подключение динамической памяти позволяет увеличить объем обрабатываемых данных. Во-вторых, если потребность в каких-либо данных отпала до окончания программы, то занятую ими память можно освободить для другой информации. В-третьих, использование динамической памяти позволяет создавать структуры данных переменного размера. Работа с динамическими величинами связана с использованием еще одного типа данных – ссылочного. Величины, имеющие ссылочный тип, называют указателями. Указатель содержит адрес поля в динамической памяти, хранящего величину определенного типа. Сам указатель располагается в статической памяти. Статическая память Динамическая память Величина Указател ь Адрес Значение Адрес величины – это номер первого байта поля памяти, в котором располагается величина. Размер поля однозначно определяется типом. Если обратиться к понятию указателя для Си\Си++, то можно с уверенностью утверждать, что смысл этого понятия остается тем же, т.е. указатель – это адрес поля памяти, занимаемого программным объектом. Будем считать, что в программе определены три переменные разных типов: int a=5; char c=’g’; float r=1.2E8; Можно схематично представить , как эти величины разместятся в памяти компьютера? Память Переменные Значения FFC0 FFC1 a 5 FFC2 c g FFC3 FFC4 r 1.2*108 FFC5 FFC6 Опер ация & - адрес. Применение этой операции к имени переменной дает в результате ее адрес в памяти. Для переменных из данного выше примера: &a равно FFC0, &c – FFC2, &r – FFC3. Описание указателей. Для хранения адресов используются переменные типа «указатель». Формат описания таких переменных имеет следующий вид: тип*имя_переменной; Приведем примеры описания указателей: int*pti; char*ptc; float*ptf; После такого описания переменная pti может принимать значение указателя на величину целого типа; переменная ptc предназначена для хранения указателя на величину типа char; переменная ptf – на величину типа float. Указателям могут присваиваться значения адресов объектов только того типа, с которым они описаны. В нашем примере допустимы операторы: pti=&a; ptc=&c; ptf=&r; В результате указатели примут следующие значения: pti – FFC0, ptc – FFC2, ptf – FFC3. Как и для других типов данных, значения указателей могут инициализироваться при описании. Например: int a=5; int*pti=&a; char c=’g’; char*ptc=&c; float r=1.2E8; float*ptf=&r; В заголовочном файле stdio.h определена константа – нулевой указатель с именем NULL. Её значение можно присваивать указателю. Например: ptf=NULL; Нулевой указатель обозначает отсутствие конкретного адреса ссылки. Использованный в описаниях указателей символ * (звездочка) в данном контексте является знаком операции разадресации. С ее помощью можно сослаться через указатель на соответствующую переменную. После приведенных выше описаний в записи выражений этой 40 программы, взаимозаменяемыми становятся a и *pti, c и *ptc, r и *ptf. Например, два оператора x=a+2; и x=*pti+2; тождественны друг другу. В результате выполнения оператора cout<<*pti<<a; на экран выведется 55. Операции над указателями. Записывая выражения и операторы, изменяющие значения указателей, необходимо помнить главное правило: единицей изменения значения указателя является размер соответствующего ему типа. Рассмотрим это правило на определенных выше указателях. Выполнение операторов pti=pti+1; или pti++; изменит значение указателя на 2, в результате чего он примет значение FFC2. В результате выполнения оператора pti--; значение указателя уменьшится на 2 и станет равным FFBE. Аналогично для указателей других типов: ptc++; увеличит значение указателя на 1; ptf++; увеличит значение указателя на 4. Использование указателей для передачи параметров функции. Рассматривая ранее правила использования функций, мы обращали внимание на то, что в языке Си возможна только односторонняя передача значений фактических параметров из вызывающей программы к формальным параметрам вызываемой функции. Возвращаемое значение несет сама функция, используемая в качестве операнда в выражении. Может показаться, что в процессе выполнения функции не могут изменяться значения переменных в вызывающей программе. Однако это правило можно обойти, если в качестве параметров функции использовать указатели. Рассмотрим пример, в котором с помощью функции swap() производится обмен значениями двух переменных величин, заданных своими указателями в аргументах. void swap (int*a, int*b) { int c; c=*a; *a=*b; *b=c; } Если в основной программе содержится следующий фрагмент: int x=1, y=2; swap (&x, &y) ; printf (“x=%d y=%d “ ,x,y ) ; То на экран будет выведено: x=2 y=1, т.е. переменные x и y поменялись значениями. После обращения к функции указатель a получил адрес переменной x, указатель b – адрес переменной y. После этого переменная x в основной программе и разадресованный указатель *a в функции оказываются связанными с одной ячейкой памяти, так же - y и *b. Таким образом, можно сделать вывод о том, что использование указателей в параметрах функции позволяет моделировать работу процедур. Указатели и массивы Имя массива можно трактовать как указатель-константа на массив. Например, в программе объявлен массив: int x[10]; В таком случае х является указателем на нулевой элемент массива в памяти компьютера. В связи с этим истинным является отношение x==&x[0]. Отсюда следует, что для доступа к элементам массива кроме индексированных имен можно использовать разадресованные указатели по принципу: имя [индекс] тождественно *(имя + индекс) Например, для описанного выше массива х взаимозаменяемы следующие обозначения элементов: x[5], или *(x+5), или *(5+x). Необходимо помнить, что для указателей работают свои правила сложения. Поскольку х – указатель на величину целого тип, то х+5 увеличивает значение адреса на 10. В языке Си символ [ играет роль знака операции сложения адреса массива с индексом элемента массива. Из сказанного должно быть понятно, почему индекс первого элемента массива всегда нуль. Его адрес должен совпадать с адресом массива: x[0] ==*(x+0) Поскольку имя массива является указателем-константой, то его нельзя изменять в программе, т.е. ему нельзя ничего присваивать. Например, если описаны два одинаковых по структуре массива: int x[10], y[10]; ,то оператор присваивания x=y будет ошибочным. Такое возможно в Паскале, но недопустимо в Си. Пересылать значения одного массива в другой можно поэлементно. Рассмотрим двумерные массивы. Допустим, что в программе присутствует описание: int p[5][10];. Это матрица из пяти строк и десяти столбцов. Двумерный массив расположен в памяти в последовательности по строкам. По-прежнему pявляется указателем-константой на массив, т.е. на элемент p[0][0]. Индексированное имя p[i] обозначает i-ю строку. Ему тождественно следующее обозначение в форме разадресованного указателя: *(p+i*10) Обращение к элементу массива p[2][4] можно заменить на *(p+2*10+4). В общем случае эквивалентны обозначения : p[i][j] и *(p+i*10+j) Здесь дважды работает операция «квадратная скобка». Последнее выражение можно записать иначе, без явного указания на длину строки матрицы p: *(*(p+i)+j). Очевидно, что по индукции для ссылки на элемент трехмерного массива a[i][j][q] справедливо выражение *(*(*(a+i)+j)+q) и т.д. Упражнения 1. В оперативной памяти вектор intx[10] расположен, начиная с адреса B7F0. Какие значения примут выражения: а) х+1; б) х+5; в) х-4 ? 2. В программе объявлен массив: int p[]={0,2,4,5,6,7,9,12}; Какие значения примут выражения: а) p[3]; б) *p; в)*(p+4); г) *(p+p[2])? 3. Составить функцию сортировки значений трех переменных a,b,c в порядке возрастания. 41 4. Составить функцию заполнения целочисленного одномерного массива случайными значениями в диапазоне от 0 до N. Символьные строки В языках Си/Си++ нет специально определенного строкового типа данных, как в Турбо Паскале. Символьные строки организуются как массивы символов, последним из которых является символ \0, внутренний код которого равен нулю. Отсюда следует одно важное преимущество перед строками в Турбо Паскале, где размер строки не может превышать 255(длина указывается в первом байте), - на длину символьного массива в Си нет ограничения. Строка описывается как символьный массив. Например: char str[20]; Одновременно с описанием строка может инициализироваться. Возможны два способа инициализации строки – с помощью строковой константы и в виде списка символов: char s[10] = “строка”; char s[] = “строка”; char s[10] = {‘с’,’т’,’р’,’о’,’к’,’а’,’\0’}; В результате первого описания под строку s будет выделено 10 байт памяти, из них первые 7 получат значения при инициализации (седьмой – нулевой символ). Второе описание сформирует строку из семи символов. Третье описание по результату равнозначно первому. Можно определить символьный массив и так: char s[10] = {‘с’,’т’,’р’,’о’,’к’,’а’}; , т .е. без нулевого символа в конце. Но это приведет к проблемам с обработкой такой строки, так как будет отсутствовать ориентир на его окончание. Отдельные символы строки идентифицируются индексированными именами. Например, в описанной выше строке s[0]=’c’, s[5]=’a’. Обработка строк обычно связана с перебором всех символов от начала до конца. Признаком конца такого перебора является обнаружение нулевого символа. Составим программу, в которой производится последовательная замена всех символов строки на звездочки и подсчет длины строки. // Замена символов на звездочки # include<stdio.h> # include<conio.h> void main() { char s[]= “fh5j”; int i=0; clrscr(); puts (s); while(s[i]) { s[i++]=’*’; puts(s); } printf (“\n длина строки=”,i); } В результате выполнения программы на экране получим: fh5j *h5j **5j ***j **** Длина строки =4 В этой программе цикл повторяет свое выполнение, пока s[i] не получит значение нулевого символа. Для вывода строки на экран в стандартной библиотеке stdio.h имеется функция puts(). Аргументом этой функции указывается имя строки. В этой же библиотеке есть функция вода строки с клавиатуры с именем gets(). В качестве аргумента указывается имя строки, в которую производится ввод. Среди стандартных библиотек Си\Си++ существует библиотека функций для обработки строк. Её заголовочный файл – string.h. Воспользуемся функцией определения длины строки из этой библиотеки. Имя функции – strlen(). В качестве аргумента будем указывать имя строки. Поставим задачу: ввести символьную строку, перевернуть (обратить) эту строку. Например, если ввести строку «abcdef», то в результате в ней должны получить «fedcba». Идея алгоритма состоит в перестановке символов, расположенных на одинаковом расстоянии от начала и конца строки. Перебор элементов строки доходит до ее середины. Составляя подобные программы, не надо забывать, что индекс первого символа строки – 0, а индекс последнего на единицу меньше длины строки. // обращение строки #include<stdio.h> #include<string.h> #include<conio.h> void main() { char c, s[10]; int i; clrscr(); printf(“Ввести строку”); get(s); for (i=0; i=(strlen(s)-1)/2; i++) 42 {c=s[i]; s[i]=s[strlen(s)-i-1]; s[strlen(s)-i-1]=c;} printf(“\n Перевернутая строка”); puts(s); } Строка как параметр функции. Использование строк в качестве параметра функции аналогично рассмотренному выше использованию массивов других типов. Необходимо помнить, что имя массива есть указатель на его начало. Однако для строк имеется одно существенное отличие от массивов других типов: имя строки является указателемпеременной, и, следовательно, его значение может подвергаться изменению. Стандарт Си рекомендует в заголовках функций, работающих со строками, явно использовать обозначение символьного указателя. Приведем пример определения функции вычисления длины строки, т.е. это аналог стандартной функции strlen(). int lehgth (char*s) { int k; for (k=0; *s++!=’\0’;k++); return k; } Здесь функция использует явный механизм работы с указателем. Изменение значения указателя s допустимо благодаря тому, что он является переменной. Необходимо помнить, что для числовых массивов этого делать нельзя. Если соблюдать данное ограничение и для строк , то условное выражение в операторе for следовало бы писать так: *(s+k)!=’\0’ или s[k]!=’\0’. Составим программу обращения строки в виде функции и составим основную программу, использующую эту функцию. Алгоритм обращения выполним иначе, чем в рассмотренной выше программе. Для определения длины строки не будем пользоваться стандартной функцией. Для вывода строки на экран применим функцию printf() со спецификатором %s (работает аналогично функции puts()). // Обращение строки #include<stdio.h> #include<conio.h> //Прототипы функций int length(char*str); void invers(char*str); //Основная программа void main() { char s[]= “123456789”; clrscr(); invers(s); // Вызов функции обращения строки printf(“\n %s”, s);} //Функция вычисления длины строки int length(char*s) { int k; for (k=0; *s++!=’\0’; k++); return k;} //Функция обращения строки void invers (char *e) { char c; int i, j, m; m=length(e); //Вызов функции for (i=0, j=m-1; i<j; i++, j--) { c=e[i]; e[i]=t[j]; e[j]=c;} } В результате выполнения этой программы на экране получим строку: 9876543210 В этой программе функция invers() работает аналогично паскалевской процедуре. Обмен параметрами через указатели имитирует обмен по имени. Рассмотрим еще пример: опишем функцию вставки символа в строку. Параметрами функции будут выступать : строка, позиция вставки, вставляемый символ. Используем эту функцию в основной программе, где исходная строка, номер позиции и вставляемый символ задаются вводом. // Вставка символа в строку #include<stdio.h> #include<string.h> #include<conio.h> void invert (char *str, int p, char c) { int i; for (i=strlen(str); i>=p; i--) str[i+1]=str[i]; str[p]=c; } void main() { char c, s[100]; int n; clrscr(); 43 puts (“Введите строку”); gets(s); puts (“Введите позицию вставки”); scanf(“%d”,&n); puts (“Введите символ”); getche(); invert(s,n,c); puts (“\n Результат”); puts(s); } Вот примерный вариант диалога на экране компьютера при выполнении этой программы: Введите строку: 0123456789 Введите позицию вставки: 4 Введите символ: * Результат: 0123*456789 В этой программе наряду с рассмотренными ранее функциями ввода и вывода gets() и puts() используется функция чтения символа с клавиатуры getche() из библиотеки stdio.h. Её прототип имеет вид: int getche(void). Она возвращает значение символа, введенного с клавиатуры, которое может быть присвоено символьной переменной. Ниже приведена таблица , в которой указаны функции для работы со строками - Это файлы string.h, stdlid.h. Функция atof atoi atol itoa ltoa strcat strchr strcmp strcpy strlen strlwr strncat strncmp strncpy strnset strrchr strset strupr ultoa free Прототип и краткое описание действий double atof(char*str); Преобразует строку str в вещественное число типа double int atoi(char*str); Преобразует строку str в десятичное целое число long atoll(char*str); Преобразует строку str в длинное десятичное целое число char*itoa(int v,char*str,int baz); Преобразует целое v в строку str. При изображении числа используется основание baz(2<=baz<=36). Для отрицательного числа и baz=10 первый символ – минус (-) char*ltoa(long v,char*str,int baz); Преобразует длинное целое v в строку str. При изображении числа используется основание baz(2<=baz<=36) char*strcat(char*sp,char*si); Приписывает строку si к строке sp (конкатенация) char*strchr(char*str,intc); Ищет в строке первое вхождение символа c. int strcmp(char*str1,char*str2); Сравнивает строки str1 и str2. Результат отрицателен, если str1<str2; равен нулю, если str1=str2 и положителен, если str1>str2 (сравнение беззнаковое) char*strcpy(char*sp,char*si); Копирует байты строки si в строку sp. unsigned strlen(char*str); Вычисляет длину строки str. char*strlwr(char*str); Преобразует буквы верхнего регистра в строке в соответствующие буквы нижнего регистра. char*strncat(char*sp,char*si,int kol) ; Приписывает kol символов строки si к строке sp (конкатенация) int strncmp(char*str1,char*str2,int kol); Сравнивает части строк str1 и str2, причем рассматриваются первые kol символов. Результат отрицателен, если если str1<str2; равен нулю, если str1=str2 и положителен, если str1>str2 (сравнение беззнаковое) char*strncpy(char*sp,char*si,int kol); Копирует kol символов строки si в строку sp («хвост» отбрасывается или дополняется пробелами) char*strnset(char*str,int c,int kol); Заменяет первые kol символов строки str символом c char*strrchr(char*str,int c); Ищет в строке str последнее вхождение символа c int strset(char*str,int c); Заполняет строку str символом с char*strupr(char*str); Преобразует буквы нижнего регистра в строке в соответствующие буквы верхнего регистра char*ultoa(unsigned long v, char*str,intbaz);Преобразует беззнаковое длинное целое v в строку str void*free(void*bl); Освобождает ранее выделенный блок динамически расположенной памяти с адресом первого байта bl Упражнения 1.Составить программу подсчета количества цифр в данной строке. 2.Составить программу, которая по данной символьной строке формирует числовой массив, содержащий коды символов, составляющих строку. 3.Составить функцию, определяющую тождественность двух данных строк. 4.Составить программу, удаляющую в данной строке каждый символ с четным номером. 5.Составить функцию конкатенации (слияния)двух строк. В основной программе использовать эту функцию для слияния четырех строк. 44 6.Составить функцию, переводящую десятичное целое число, представленное в символьном виде, в соответствующую величину целого типа. Структуры и объединения В языках Си/Си++ понятие структуры аналогично понятию записи (record) в Паскале. Это структурированный тип данных, представляющий собой поименованную совокупность разнотипных элементов. Тип структура обычно используется при разработке информационных систем, баз данных. Комбинированный тип данных – это структурированный тип, состоящий из фиксированного числа компонент (полей) разного типа. В Паскале комбинированный тип имеет название запись, в языке Си/Си++ - это структура. Таким образом, структура – это совокупность разнотипных атрибутов, относящихся к одному объекту. Например, анкетные сведения о студенте вуза могут быть представлены в виде следующей структуры: Анкета студента Пол Ф.И.О. Адрес Дата рождения Курс Группа Стипендия Такая структура называется двухуровневым деревом. Например, те же сведения о студентах можно отобразить трехуровневным деревом: Анкета студента Ф.И.О. Пол Год Месяц Дата рождения День Адрес Курс Город Группа Стипендия Улица, дом, квартира Выше приведенная организация данных позволит делать выборки студентов по году рождения или по месту жительства и т.д. Рассмотрим пример: сведения выплате студентам стипендии требуется организовать в следующем виде: Студент Фамилия Курс Группа Стипендия Элементы такой структуры (фамилия, курс, группа, стипендия) называются полями. Каждому полю должно быть поставлено в соответствие имя и тип. Формат описания структурного типа имеет вид: struct имя_типа {Определения элементов}; В конце обязательно ставится точка с запятой (это оператор). Для рассмотренного примера определение соответствующего структурного типа может быть следующим: struct student { char fam[30]; int kurs; char grup[3]; float stip; }; После такого описания student становится именем структурного типа, который может быть назначен некоторым переменным. В соответствии со стандартом Си это нужно выполнить следующим образом: struct student stud1, stud2; 45 Правила языка Си++ разрешают в этом случае служебное слово struct опускать, в этом случае запись будет иметь упрощенный вид: struct stud1, stud2; Здесь stud1 и stud2 – переменные структурного типа. Допускаются и другие варианты описания структурных переменных. Можно вообще не задавать имя типа, а описывать сразу переменные: struct { char fam[30]; int kurs; char grup[3]; float stip; };stud1,stud2, *pst; В этом примере кроме двух переменных структурного типа объявлен указатель pst на такую структуру. В данном описании можно было сохранить имя структурного типа student. Обращение к элементам (полям) структурной величины производится с помощью уточненного имени следующего формата: имя_структуры . имя_элемента Например, уточненные имена для описанных выше переменных: stud1.fam; stud1.stip; Таким образом, уточненное имя – это выражение с двумя операндами и операцией «точка» между ними. Операция «точка» называется операцией доступа к элементу структуры (или объединения). У этой операции самый высокий ранг наряду со скобками и операцией «стрелка» для доступа к элементам структуры через адресующий указатель. Значения элементов структуры могут определяться вводом, присваиванием, инициализацией. Приведем пример инициализации при описании: student stud1={ “Сидоров”,3, “Э32”, 3000}; Рассмотрим пример программы с инициализацией структуры и выводом значений ее элементов: на складе находится товар, введем название товара, его оптовую цену, наценку, количество, дату поставки. #include<stdio.h> void main() { struct goods { char*name; long price; float percent; int vol; char date[9]; }; struct goods coat={ “пиджак”, 4000, 7.5,220,”12.01.2004”}; printf (“\n Товар на складе:”); printf (“\n Наименование: %s.”, coat.name); printf (“\n Оптовая цена: %d тенге”, coat.price); printf (“\n Наценка : %f%%.”, coat.percent); printf (“\n Объем партии: %d штук.”, coat.vol); printf (“\n Дата поставки: %s”, coat.vol); } Допустим, что в программе определен указатель на структуру student *pst, stud1; . Тогда после выполнения оператора присваивания pst=&stud1; к каждому элементу структурной переменной stud1 можно обратиться тремя способами. Например, для поля fam stud1.fam или (*pst).fam или pst-> stip. В последнем варианте используется знак операции доступа к элементу структуры: ->. Аналогично можно обращаться и к другим элементам этой переменной: pst->fio, pst ->grup, pst->stip. Поля структуры могут сами иметь структурный тип. Такие величины представляют многоуровневые деревья. Допускается использхование массивов структур. Например, сведения о 100 студентах могут храниться в массиве, описанном следующим образом: student stud[100]; . Тогда сведения об отдельных студентах будут обозначаться , например; stud[1].fam, syud[5].rurs и т.д. Если необходимо обратиться к первой букве фамилии 20-го студента, то следует набрать: stud[20].fam[0]. Пример1. Ввести сведения об n студентах. Определить фамилии студентов, получающих самую высокую стипендию. #include<stdio.h> #include<conio.h> void main() { const n=30; int i; float maxs; struct student {char fam[15]; int kurs; char grup[3]; float slip; }; student stud[n]; 46 clrscr(); for(i=0; i<n; i++) { printf(“%d –й студент”, i); printf(“\n Фамилия:”); scanf(“%s”, &stud[i].fam); printf(“Курс:”); scanf(“%d”, &stud[i].kurs); printf(“Группа:”); scanf(“%s”, &stud[i].grup); printf(“Стипендия:”); scanf(“%f”, &stud[i].stip);} maxs=0; for (i=0; i<n; i++) if (stud[i].stip>maxs) maxs=stud[i].stip; printf(“\n Студенты, получающие максимальную стипендию %f тенге.”, maxs); for(i=0; i<n; i++) if (stud[i].stip==maxs) printf (“\n %s”, stud[i].fam); } Элемент структуры типа поля битов Использование структуры в программе на Си позволяет работать с отдельными битами, т.е. с разрядами двоичного кода. Для этого используются элементы структуры типа поля битов. Формат структуры, содержащий поля битов следующий: struct имя_структуры { тип имя_поля_1: длина_в_битах; тип имя_поля_2: длина_в_битах; тип имя_поля_3: длина_в_битах; … … … … … … … тип имя_поля_n: длина_в_битах; }; В качестве типа полей могут использоваться спецификаторы int, unsigned, signed. Минимальной величиной такого типа может быть структура, состоящая всего из одного битового поля. Пример описания такой структуры: struct bit { unsigned b1:1; } cod; Для переменной cod в памяти будет выделено 8 бит (1байт), но использоваться будет только один первый бит. Поля могут размещаться как слева направо, так и справа налево. Для компиляторов, работающих под управлением MSDOS на IBM PC, поля, которые размещены в начале описания структуры, имеют младшие адреса. Таким образом, для примера: struct { int x:5; iny y:3; } hh; hh.x=4 ; hh.y=2 ; В одном байте формируется последовательность битов, приведенная на рисунке : 7 6 5 4 3 2 1 0 Номера битов: 0 Битовые поля hh.y 1 hh.x 0 0 0 1 0 0 Объединение Объединение – это еще один структурированный тип данных. Объединение похоже на структуру и в своем описании отличается от структуры тем, что вместо ключевого слова struct используется слово union. union имя_типа {определения_элементов}; Объединение отличается от структуры способом организации во внутренней памяти. Все элементы объединения в памяти начинаются с одного байта, т.е. все элементы объединения имеют нулевое смещение от её начала. При таком размещении разные элементы занимают в памяти один и тот же участок. Тем самым объединения обеспечивают возможность доступа к одному и тому же участку памяти с помощью переменных (и/или массивов и структур) разного типа. Необходимость в такой возможности возникает, например, при выделении из внутреннего представления целого числа его отдельных байтов. Допустим, что в программе описана структура: struct s {int i; char ch; long int l; }; Расположение ее элементов в памяти будет иметь вид: 47 байт байт байт байт байт байт байт i ch l Элементы структуры занимают последовательные ячейки памяти с размером, соответствующим типу. Общий размер структуры равен сумме длин полей. Рассмотрим объединение со следующим описанием: union s { int i; char ch; long int l; }; Величина с таким типом в памяти будет расположена следующим образом: байт байт байт байт ch i l Поля объединения накладываются друг на друга. Общий объем занимаемой памяти равен размеру самого большого поля. Изменения значения любого поля объединения меняет значения других полей. Пример. Составить программу решения следующей задачи: с клавиатуры вводится символ. Вывести на экран двоичный код этого символа. // Получение двоичного кода символа #include<stdio.h> #include<conio.h> //Структура битовых полей struct byte {int b1:1; int b2:1; int b3:1; int b4:1; int b5:1; int b6:1; int b7:1; int b8:1; }; //Объединение – переменная union bits { char ch; byte cod; } u; //Прототип функции декодирования void decode (bits,x); //Основная программа void main() { do { u.ch=getche(); //Ввод символа с клавиатуры printf(“:”); decode(u); } while(u.ch!=’q’); // Символ q – признак конца ввода } //Функция декодирования void decode(bit u) { if (u.cod.b8) printf(“1”); else printf(“0”); if (u.cod.b8) printf(“1”); else printf(“0”); if (u.cod.b8) printf(“1”); else printf(“0”); if (u.cod.b7) printf(“1”); else printf(“0”); if (u.cod.b6) printf(“1”); else printf(“0”); if (u.cod.b5) printf(“1”); else printf(“0”); if (u.cod.b4) printf(“1”); else printf(“0”); if (u.cod.b3) printf(“1”); else printf(“0”); if (u.cod.b2) printf(“1”); else printf(“0”); if (u.cod.b1) printf(“1”); else printf(“0”); printf (“\n”); } В этой программе переменная – объединение u содержит два элемента: символьное поле ch и битовую структуру cod, которые накладываются друг на друга. Таким образом, оказывается возможным получить доступ к каждому биту кода символа. Работа программы заканчивается после ввода символа q. Ниже приведен вариант результатов работы данной программы. s: 01110011 d: 01100100 48 1. 2. 3. J: 01101010 a: 01100001 b: 01100010 c: 01100011 d: 01100100 q: 01110001 Упражнения Сведения о каждом химическом элементе из периодической таблицы Д.И.Менделеева представить в виде структуры. Написать программу ввода таблицы в память компьютера. Представить координаты точки в трехмерном пространстве в виде структуры, состоящей из трех вещественных полей. Написать программу ввода координат двух точек и вычисления расстояния между ними. Рассматривая комплексное число как структуру, состоящую из двух вещественных полей, составить функции выполнения четырех арифметических операций с комплексными числами. Потоковый ввод – вывод в стандарте Си Под вводом-выводом в программировании понимают процесс обмена информацией между оперативной памятью и внешними устройствами: Клавиатурой, дисплеем, магнитными накопителями и т.п. Ввод – это занесение информации с внешних устройств в оперативную память , вывод – вынос информации из оперативной памяти на внешние устройства. Такие устройства, как дисплей и принтер, предназначены только для вывода; клавиатура – устройство ввода. Магнитные накопители (диски, ленты) используются как для ввода, так и для вывода. Основным понятием, связанным с информацией на внешних устройствах ЭВМ, является понятие файла. Всякая операция ввода-вывода трактуется как операция обмена с файлами: ввод – это чтение из файла в оперативную память; вывод – запись информации из оперативной памяти в файл. Поэтому вопрос об организации ввода-вывода сводится к вопросу об организации работы с файлами. В Паскале использовалось представление о внутреннем и внешнем файле. Внутренний файл – это переменная файлового типа, являющаяся структурированной величиной. Элементы файловой переменной могут иметь разный тип и, соответственно, различную длину и форму внутреннего представления. Внутренний файл связывается с внешним (физическим) файлом с помощью стандартной процедуры assign. Один элемент файловой переменной становится отдельной записью во внешнем файле и может быть прочитан или записан с помощью одной команды. Попытка записать в файл или прочитать из него величину, не совпадающую по типу с типом элементов файла, приводит к ошибке. Аналогом понятия внутреннего файла в языках Си/Си++ является понятие потока. Отличие от файловой переменной Паскаля состоит в том, что потоку в Си не ставится в соответствие тип. Поток – это байтовая последовательность, передаваемая в процессе ввода-вывода. Поток должен быть связан с каким-либо внешним устройством или файлом на диске. В терминологии Си это звучит так: поток должен быть направлен на какое-то устройство или файл. Основные отличия файлов в Си состоят в следующем: здесь отсутствует понятие типа файла и, следовательно, фиксированной структуры записи файла. Любой файл рассматривается как байтовая последовательность: байт0 байт1 байт2 … EOF Стрелочкой обозначен указатель файла, определяющий текущий байт файла. EOF является стандартной константой – признаком конца файла. Существуют стандартные потоки и потоки, объявляемые в программе. Последние обычно связываются с файлами на диске создаваемыми программистами. Стандартные потоки назначаются и открываются системой автоматически. С началом работы любой программы открываются 5 стандартных потоков, из которых основными являются следующие: Название потока Назначение stdin поток стандартного ввода(обычно связан с клавиатурой) stdout поток стандартного вывода (обычно связан с дисплеем) stderr вывод сообщений об ошибках(связан с дисплеем ) Кроме того, открывается поток для стандартной печати и дополнительный поток для последовательного порта. Работая ранее с программами на Си, используя функции ввода с клавиатуры и вывода на экран, мы уже имели (неявно) дело с первыми двумя потоками. А сообщения об ошибках, которые система выводила на экран, относятся к третьему стандартному потоку. Поток для работы с дисковым файлом должен быть открыт в программе. Работа с файлами на диске. Работа с дисковым файлом начинается с объявления указателя на поток. Формат такого объявления: file *имя_указателя; Например: file * ft; Слово file является стандартным именем структурного типа, объявленного в заголовочном файле stdio.h. В структуре file содержится информация, с помощью которой ведется работа с потоком, в частности: указатель на буфер, указатель (индикатор) текущей позиции в потоке и т. д. 49 Следующий шаг – открытие потока, которое производится с помощью стандартной функции fopen(). Эта функция возвращает конкретное значение для указателя на поток и поэтому её значение присваивается объявленному ранее указателю. Соответствующий оператор имеет формат: имя_указателя = fopen (имя_файла, режим_открытия); Параметры функции fopen() являются строками, которые могут быть как константами, так и указателями на символьные массивы. Например: fp = fopen(“test.dat”,”r”); Здесь test.dat – это имя физического файла в текущем каталоге диска, с которым теперь будет связан поток с указателем fp. Параметр режима r означает, что файл открыт для чтения. Понятие «открытие потока» тоже самое, что и «открытие файла». Существуют следующие режимы открытия потока и соответствующие им параметры: Параметр Режим Открыть для чтения r w Создать для записи a Открыть для добавления r+ Открыть для чтения и записи w+ Создать для чтения и записи a+ Открыть для добавления или для чтения и записи Необходимо помнить, что открытие уже существующего файла для записи ведет к потере прежней информации в нем. Если такой файл не существовал, то он создается. Открывать для чтения можно только существующий файл. Поток может быть открыт либо для текстового, либо для двоичного (бинарного) режима обмена. текстовый файл – это последовательность символов, которая делится на строки специальными кодами – возврат каретки (код13) и перевод строки (код10). Если файл открыт в текстовом режиме, то при чтении из такого файла комбинация символов «возврат каретки – перевод строки» преобразуется в один символ \n – переход к новой строке. При записи в файл осуществляется обратное преобразование. При работе с двоичным файлом никаких преобразований символов не происходит, т.е. информация переносится без всяких изменений. Указанные выше параметры режимов открывают текстовые файлы. Если требуется указать на двоичный файл, то к параметру добавляется буква b. Например: rb, или wb, или r+b. В некоторых компиляторах текстовый режим обмена обозначается буквой t, т.е. записывается a+t или rt. Если открытии потока по какой-либо причине возникла ошибка, то функция fopen() возвращает значение константы NULL. Эта константа также определена в файле stdio.h. Ошибка может возникнуть из-за отсутствия открываемого файла на диске, нехватки места в динамической памяти и т.п. Поэтому необходимо контролировать правильность прохождения процедуры открытия файла. Рекомендуется следующий способ открытия: file *fp; if (fp=fopen (“test.dat”,”r”)==NULL { puts(“Не могу открыть файл \n”); return;} В случае ошибки программа завершит выполнение с закрытием всех ранее открытых файлов. Закрытие потока (файла) осуществляет функция fclose(), прототип которой имеет вид: int fclose(file *fptr); Здесь fptr обозначает формальное имя указателя на закрываемый поток. Функция возвращает ноль, если операция закрытия файла прошла успешно. Другая величина означает ошибку. Запись и чтение символов. Запись символов в поток производится функцией putc() с прототипом int putc(int ch?file *fptr); Если операция прошла успешно, то возвращается записанный символ. В случае ошибки возвращается константа EOF. Считывание символа из потока, открытого для чтения, производится функцией gets() с прототипом int gets (file *fptr);. Функция возвращает значение считываемого из файла символа. Если достигнут конец файла, то возвращается значение EOF. Заметим, что это происходит лишь в результате чтения кода EOF. Функция gets() возвращает значение типа int. То же можно сказать и про аргумент ch в описании функции puts(). Используется же в обоих случаях только младший байт. Поэтому обмен при обращении может происходить и с переменными типа char. Пример 1. Составить программу записи в файл символьной последовательности, вводимой с клавиатуры. Символом завершения ввода будет символ *. // Запись символов в файл #include<stdio.h> void main() { file *fp; char c; if ((fp=fopen(“test.dat”, “w”))== NULL ) { puts(“Не могу открыть файл \n”); return;} puts(“Ввести символы. Признак конца - *”); while (( c=getchar())!=’*’) putc(c, fp); fclose(fp); } 50 В результате на диске (в каталоге, определяемом ситемой) будет создан файл с именем test.dat, который заполнится вводимыми символами. Символ * в файл не запишется. Пример 2. Файл, созданный в результате работы предыдущей программы, требуется последовательно прочитать и содержимое вывести на экран. // Чтение символов из файла #include<stdio.h> #include<conio.h> void main() { file *fp; char c; clrscr(); if ((fp=fopen(“test.dat”, “r”))==NULL) { puts(“не удалось открыть файл! \n”); return;} while ((c=getc(fp))!=EOF) putchar(c); fclose(fp); } Связь между результатом работы предыдущей программы и данной программой осуществляется через имя физического файла, которое в обоих случаях должно быть одним и тем же. Запись и чтение целых чисел. Запись целых чисел в поток без преобразования их символьную форму производится функцией putw() c прототипом int putw(int, file *fptr); Если операция завершена успешно, то возвращается записанное число. В случае ошибки возвращается константа EOF. Считывание целого числа из потока, открытого для чтения, производится функцией getw() с прототипом int getw(file *fptr);. Функция возвращает значение считываемого из файла числа. Если прочитан конец файла, то возвращается значение EOF. Пример 3. Составить программу, по которой в файл запишется последовательность целых чисел, вводимых с клавиатуры, а затем эта последовательность будет прочитана и выведена на экран. Считаем, что признаком конца ввода будет число 9999. //Запись и чтение целых чисел #include<stdio.h> #include<conio.h> void main() { file *fp; int x; clrscr(); //Открытие потока для записи if ((fp=fopen(”test.dat”,”w”))==NULL) {puts(“Ошибка открытия файла для записи \n”); return;} puts(“Вводите числа, Признак конца 9999”); scanf(“%d”, &x); while(x!=9999) {putw(x,fp); scanf (“%d”,&x); } fclose(fp); // Закрытие потока в режиме записи // Открытие потока для чтения if ((fp=fopen(“test.dat”,”r”))==NULL) {puts(“Ощибка открытия файла для чтения! \n”); return;}while((x=getw(fp)!=EOF) printf(“\n%d”,x); fclose(fp); } После завершения ввода чисел в файл его необходимо закрыть. При этом происходит сброс накопленных в буфере значений на диск. Только после этого можно открывать файл доя чтения. Указатель устанавливается на начало потока, и дальнейшее чтение будет происходить от начала до конца файла. Запись и чтение блока данных. Специальные функции обмена с файлами имеются только для символьного и целого типа данных. В общем случае используются функции чтения и записи блоков данных. С их помощью можно записывать в файл и читать из файла вещественные числа, массивы, строки, структуры. При этом, как и для ранее рассмотренных функций, сохраняется форма внутреннего представления данных. Функция записи блока данных имеет прототип int fread (void*buf, int bytes, int n, file*fptr); Здесь buf – указатель на адрес данных, записываемых в файл; bytes – длина в байтах одной единицы записи(блока данных); n – число блоков, передаваемых в файл; fptr – указатель на поток. Если запись выполнилась благополучно, то функция возвращает число записанных блоков (значение n). Функция чтения блока данных из файла имеет прототип: int fwrite(void*buf, int byte, int n, file*fptr); 51 По аналогии с предыдущим описанием легко понять смысл параметров. Пример 4. Организовать запись блоком в файл строки (символьного массива), вывод на экран записанной информации. #include<string.h> #include<stdio.h> void main() { file *stream; char msg[]=”this is a test”; char buf[20]; if ((stream=fopen9””DUMMY.FIL”,”w”))==NULL) {puts (“Ошибка открытия файла \n”); return;} // Запись строки в файл fwrite(msg, strlen(msg)+1, 1,stream); //Установка указателя на начало файла fseek(stream,0 ,0 SEEK_SET); // Чтение строки из файла fread(buf, strlen(msg)+1, 1, stream); printf(“%s \n”, buf); fclose(stream); } В этой программе поток открывается в режиме +w (создание для записи с последующим чтением). Поэтому закрывать файл после записи не надо. Новым элементом данной программы по сравнению с предыдущими является использование функции установки указателя потока в заданную позицию. Ее формат: int fseek(указатель на поток, смещение, начало отсчета); Начало отсчета задается одной из констант, определенных в файле stdio.h: SEEK_SET (имеет значение 0) – начало файла; SEEK_CUR (имеет значение 1) – текущая позиция; SEEK_END (имеет значение 2) – конец файла. Смещение определяет число файт, на которое надо сместить указатель относительно заданного начала отсчета. Смещение может быть как положительным, так и отрицательным числом. Оба параметра имеют тип long. Форматный обмен файлами. С помощью функции форматного вывода можно формировать на диске текстовый файл с результатами вычислений. представленными в символьном виде. В дальнейшем этот может быть просмотрен на экране, распечатан на принтере, отредактирован с помощью текстового редактора. Общий вид функции форматного вывода: int fprintf(указатель на поток, форматная строка, список переменных); Использовавшаяся ранее функция pintf() для организации вывода на экран является частным вариантом функции fprintf(). Функция printf() работает лишь со стандартным потоком stdin, который всегда связывается системой с дисплеем. Не будет ошибкой, если в программе вместо printf() написать fprintf(stdin, …). Правила использования спецификаторов форматов при записи в файлы на диске точно такие же, как и при выводе на экран. Пример5. Составить программу, по которой будет рассчитана и записана в файл таблица квадратных корней для целых чисел от 1 до 10. Для контроля эта же таблица выводится на экран. // Таблица квадратных корней #include<stdio.h> #include<iostream.h> #include<math.h> void main() { file *fp; int x; fp=fopen(“test.dat”, “w”); //Вывод на экран и в файл шапки таблицы printf(“\t Таблица квадратных корней \n”); printf(“\t x\t\t sqrt(x)\n”); printf(fp, ”\t x \t\t sqrt(x); //Вычисление и вывод таблицы квадратных корней //на экран и в файл for(x=1; x<=10; x++) { printf (“\t%f\t%f\n” , float(x), sqrt(float(x))) ; fprintf(fp, “\t%f\t%f\n”, float(x), sqrt(float(x)) ) ; } fclose(fp) ; } Если теперь с помощью текстового редактора открыть файл test.dat, то на экране увидим: Таблица квадратных корней x sqrt(x) 1.000000 1.000000 2.000000 1.414214 3.000000 1.732051 52 4.000000 2.000000 5.000000 2.236068 6.000000 2.449490 7.000000 2.645751 8.000000 2.828427 9.000000 3.000000 10.000000 3.162278 Форматный ввод из текстового файла осуществляется с помощью функции fscanf(), общий формат которой выглядит следующим образом: int fscanf(указатель на поток, форматная строка, список адресов переменных); Данной функцией удобно пользоваться в тех случаях, когда исходные данные заранее подготавливаются в текстовом файле. В следующем примере числовые данные из файла test.dat, полученного в результате выполнения предыдущей программы, вводятся в числовые массивы x и y. Для контроля значения элементов массивов выводятся на экран. Предварительно с помощью текстового редактора в файле test.dat удаляются две первые строчки с заголовками. В результате в файле останутся только два числа. Пример 6. //Ввод чисел из файла #include<stdio.h> #include<iostream.h> #include<math.h> void main() { file *fp; int i; float x[10], y[10]; fp=fopen(“test.dat”, “r”); for (i=0; i<10; i++) { fscanf(fp, “%f%f”, &x[i], &y[i]); printf(“%f %f \n”, x[i], y[i]); } close(fp); } 1. 2. 3. 4. 5. 6. 7. Упражнения Составить программу, которая формирует файл целых чмсел, получаемых с помощью датчика случайных чисел. Составить программу, которая в файле, сформированном программой из предыдущей задачи, находит наибольшие и наименьшие значения. Составить программу, которая формируетфайл из строчных латинских букв, выбираемых случайным образом. Составить программу, которая в файле, сформированном программой из предыдущей программы подсчитает количество букв «а». Составить программу, записывающую на диск таблицу Менделеева. Составить программу, которая в файле, сформированном в результате решения предыдущей задачи, будет отыскивать сведения о заданном химическом элементе. Сведения о деталях, хранящихся на складе, содержат следующие атрибуты: название, количество, стоимость одной детали. Составить программы, решающие следующие задачи: а) заполнить файл с информацией о деталях на складе; б) вычислить общую стоимость деталей; в) выяснить, какие детали имеются в наибольшем количестве, какие – в наименьшем; г) вывести информацию о наличии на складе деталей данного типа и их количестве; д) внести изменения в файл после выдачи со склада определенного количества данного вида деталей. Если какойто тип деталей полностью отсутствует, то уничтожить запись о нем в файле. Объектно-ориентированное программирование в Си++ Основополагающей идеей одного из современных подходов к программированию – объектно-ориентированному – является объединение данных и обрабатывающих их процедур в единое целое – объекты. Объектноориентированное программирование – это методология программирования, которая основана на представлении программы в виде совокупности объектов, каждый из которых является реализацией определенного класса (типа особого вида), а классы образуют иерархию, основанную на принципах наследуемости. При этом объект характеризуется как совокупностью всех свойств и их текущих значений, так и совокупностью допустимых для данного объекта действий. Несмотря на то что в различных источниках делается акцент на те или иные 53 особенности внедрения и применения ООП, три основных (базовых) понятия ООП остаются неизменными. К ним относятся: - наследование (Inheritance); - инкапсуляция (Encapsulation); - полиморфизм (Polymorphism). При процедурном подходе решения задачи требуется описать каждый шаг, каждое действие алгоритма для достижения конечного результата. В отличие от него объектно-ориентированный подход оставляет за объектом право решать, как отреагировать и что сделать в ответ на поступивший вызов. Достаточно в стандартной форме поставить перед ним задачу и получить ответ. Объект состоит из следующих трех частей: - имени объекта; - состояния (переменных состояния); - методов (операций). Можно дать обобщающее определение: объект ООП – это совокупность переменных состояния и связанных с ними методов (операций). Методы определяют, как объект взаимодействует с окружающим миром. Под методами объекта понимают процедуры и функции, объявление которых включено в описание объекта и которые выполняют действия. Возможность управлять состояниями объекта посредством вызова методов в итоге и определяет поведение объекта. Совокупность методов часто называют интерфейсом объекта. Инкапсуляция – это механизм, который объединяет данные и методы, манипулирующие этими данными, и защищает и то и другое от внешнего вмешательства или неправильного использования. Когда методы и данные объединяются таким способом, создается объект. Применяя инкапсуляцию, мы защищаем данные, принадлежащие объекту, от возможных ошибок, которые могут возникнуть при прямом доступе к этим данным. Кроме того, применение указанного принципа очень часто помогает локализовать возможные ошибки в коде программы. Инкапсуляция обеспечивает сокрытие данных, что позволяет защитить эти данные. Однако применение инкапсуляции ведет к снижению эффективности доступа к элементам объекта. Наследование – это процесс, посредством которого один объект может наследовать свойства другого объекта и добавлять к ним черты, характерные только для него. В итоге создается иерархия объектных типов, где поля данных и методов «предков» автоматически являются и полями данных и методов «потомков». Смысл и универсальность наследования заключается в том, что не надо каждый раз заново («с нуля») описывать новый объект, а можно указать «родителя» (базовый класс) и описать отличительные особенности нового класса. В результате новый объект будет обладать всеми свойствами родительского класса плюс своими собственными отличительными особенностями. Пример1: Можно создать базовый класс «транспортное средство», который универсален для всех средств передвижения. Этот класс «знает», как двигаются колеса, как они поворачиваются, тормозят и т.д. Затем на основе этого класса создадим класс «легковой автомобиль». Поскольку новый класс унаследован из класса «транспортное средство», унаследованы все особенности этого класса, и нет необходимости снова описывать, как двигаются колеса. Нам необходимо добавить те черты, которые характерны для легковых автомобилей. В то же время можно взять за основу этот же класс «транспортное средство» и построить класс «грузовые автомобили». Описав отличительные особенности грузовых автомобилей, получим новый класс «грузовые автомобили». К примеру, на основании класса «грузовой автомобиль» уже можно описать определенный подкласс грузовиков и т.д. Таким образом, сначала формируем простой шаблон, а затем, усложняя и конкретизируя, поэтапно создаем все более сложные шаблоны. Полиморфизм – это свойство, которое позволяет одно и то же имя использовать для решения некоторых технически разных задач. Полиморфизм подразумевает такое определение методов в иерархии типов, при котором метод с одним именем может применяться к различным родственным объектам. В общем смысле концепцией полиморфизма является идея «один интерфейс – множество методов». Преимуществом полиморфизма является то, что он помогает снижать сложность программ, разрешая использование одного интерфейса для единого класса действий. Выбор конкретного действия в зависимости от ситуации возлагается на компилятор. Пример2. Пусть есть класс «автомобиль», в котором описано, как должен передвигаться автомобиль, как он поворачивает, как подает сигнал и т.д. Там же описан метод «переключение передачи». Допустим, что в этом методе класса «автомобиль» описана коробка передач. А теперь необходимо описать класс «спортивный автомобиль», у которого механическое (ручное) переключение скоростей. Можно описать заново все методы для класса «спортивный автомобиль», но лучше указать, что класс «спортивный автомобиль» унаследован из класса «автомобиль», а следовательно, он обладает всеми свойствами и методами, описанными для класса-родителя. Единственное, что надо сделать – это переписать метод «переключение передач» для механической коробки передач. В результате при вызове метода «переключение передач» будет выполняться метод не родительского класса, а самого класса «спортивный автомобиль». Механизм работы ООП в таких случаях можно описать примерно так: при вызове того или иного метода класса сначала ищется метод в самом классе. Если метод найден, то он выполняется, и поиск этого метода завершается. Если же метод не найден, то обращаемся к родительскому классу и ищем вызванный метод в нем. Если он найден, то поступаем, как при нахождении метода в самом классе. А если нет, то продолжаем дальнейший поиск вверх по иерархическому дереву, вплоть до корня (верхнего класса) иерархии. Этот пример отражает так называемый механизм раннего связывания. Основным отличием языка Си++ от Си является наличие в нем средств объектно-ориентированного программирования (ООП). Для языка Си++ базовые понятия ООП остаются теми же, что и для любого языка программирования (в частности Паскаля): инкапсуляция, наследование и полиморфизм. Реализация ООП на Си++ 54 несколько более гибкая, чем в Турбо Паскале. Существуют определенные терминологические отличия. Первое такое отличие заключается в следующем: вместо понятия «объектный тип данных», применяемого в Турбо Паскале, в Си++ используется понятие «класс». Класс – это структурированный тип, включающий в себя в качестве элементов типизированные данные и функции, применяемые по отношению к этим данным. Таким образом, инкапсуляция(объединение параметров и методов) заложена в составе элементов класса: типизированные данные – это параметры, а методы реализованы через функции. Тип «класс» устанавливается для объектов. Принято говорить: однотипные объекты принадлежат одному классу. Синтаксис объявления класса подобен синтаксису объявления структуры в Паскале. Объявление начинается с ключевого слова class, за которым следует имя класса. В простейшем случае объявления класса имеет следующий формат: class имя { тип1 переменная1 тип2 переменная2 ………………….. public: функция1; функция2; ………… }; Основное отличие класса от структур состоит в том, что все члены класса по умолчанию считаются закрытыми и доступ к ним могут получить только функции – члены этого же класса. Однако режим доступа к элементам класса может быть изменен путем его явного указания. Для этого перед элементами класса записывается соответствующий спецификатор доступа. Существуют три таких спецификатора: private (частный); public (общедоступный); protected (защищенный). Режим доступа private обозначает, что соответствующий элемент может использоваться только функциями данного класса. Этот режим доступа устанавливается по умолчанию. Элементы с режимом доступа public доступны в других частях программы. Чаще всего режим доступа к данным (переменным) бывает private, а к функциям – public. Это отражено в приведенном выше формате объявления класса. В качестве примера рассмотрим объявление класса обыкновенных дробей с именем drob, в котором значение дроби определено через структуру двух целых чисел (числитель и знаменатель), а к методам работы с дробью отнесены ввод дроби – функция vvod; вычисление наибольшего общего делителя числителя и знаменателя – функция nod; сокращение дроби – функция sokr; возведение дроби в целую степень – функция stepen и вывод дроби на экран – функция print. Объявление соответствующего класса выглядит следующим образом: class drob { frac a; public: void vvod(void); int nod(void); void sokr(void); void stepen(int n); void print(void); }; Имеется ввиду, что глобально по отношению к этому классу объявлена структура с именем frac: struct frac {int p; int q;}; Таким образом, пять методов реализованы пятью функциями, которые в объявлении класса представлены своими прототипами. Описания функций - членов класса производится отдельно. При этом необходимо указывать, к какому классу принадлежит данная функция. Для этого используется операция принадлежности, знак которой ::. Например: void drob::vvod(void) { cout<<”Числитель”; cin>> a.p; cout<<”Знаменатель”; cin>>a.q; } В основной части программы (основной функции) класс drob будет поставлен в соответствии определенным переменным в качестве типа. Например: drob y; После этого переменная y воспринимается в программе как объект соответствующего класса. Для основной программы открыты только функции этого объекта. Следовательно, воздействовать на параметры объекта можно только через эти функции. Аналогично элементам структуры обращение к элементам объекта производится с помощью составного имени (через точку). Например: y.vvod(). Пример. Рассмотрим программу, в которой будет объявлен класс простых дробей, описана переменная этого класса, выполнена обработка этой переменной. #include<iostream.h> #include<math.h> 55 struct frac {int p; int q;}; frac f; //Объявление класса class Drob { frac a; public: void vvod(void); void sokr(void); void stepen(int n); void print(void); }; //Описания функций – членов класса void drob::vvod(void) {cout<<”числитель”; cin>>a.p; cout<<”числитель”; cin>>a.q; } int drob:: nod(void) { int m,n; m=abs(a.p); n=a.q; while(m!=n) {if (m>n) if (m%n!=0) m=m%n; else m=n; else if (n%m!=0) n=n%m; else n=m;} return m;} void drob:: sokr(void) { int x; x=nod(); if (a.p!=0){ a.p=a.p/x; a.q=a.q/x;} else a.q=1; } void drob:: stepen (int n) { int i; f.p=f.q=1; for (i=1; i<=n; i++) { f.p*=a.p; f.q*=a.q;}} void drob:: print(void) { cout<<”\n”<<a.p<<”/”<<a/q<<”\n”;} //Основная функция void main(void) { drob y; //Объединение объекта cout<<”Ввести дробь”<<”\n “; y.vvod(); y.sokr(); cout<<”Дробь после сокращения”<<”\n”; y.print(); y.stepen(2); cout<<”Дробь, возведенная в квадрат”<<”\n”; cout<<f.p<<”/”<<f.q<<”\n”; } В результате выполнения этой программы на экране получим: Ввести дробь: Числитель: 6 Знаменатель: 15 Дробь после сокращения: 3/5 Дробь, возведенная в квадрат: 9/25 Как говорилось выше, наследование – второе фундаментальное понятие ООП. Механизм наследования позволяет формировать иерархии классов. Класс-наследник получает свойства класса-предка. Как и в Турбо Паскале, в классе-наследнике могут быть объявлены новые дополнительные элементы. Элементы-данные должны иметь имена, отличные от имен предка. Элементы-функции могут быть новыми относительно предка, но могут и повторять имена функций своих предков. Как и в Турбо Паскале, здесь действует принцип «снизу вверх» при обращении к функции: функция потомка перекрывает одноименную функцию своего предка. Формат объявления класса-потомка имеет следующий вид: class имя потомка: режим доступа имя предка {новые элементы} Для того чтобы элементы-данные класса-предка были доступны функциям класса-потомка, этим элементам должен быть поставлен в соответствие режим доступа protected(защищенный). Рассмотрим программу, в которой есть родительский объектный тип “выпуклый четырехугольник” (поля типа «координаты вершин, заданные в порядке их обхода») и типы, им порожденные: параллелограмм, ромб, квадрат. Описать для указанных фигур методы «вычисление углов »(в градусах), «вычисление диагоналей», «вычисление длин сторон», «вычисление периметра», «вычисление площади». 56 // Объявлен исходный класс четырехугольников // и классы-наследники параллелограммов, ромбов и квадратов #include<iostream.h> #include<math.h> // Объявление базового класса четырехугольников class fourangle { protected: double x1,y1,x2,y2,x3,y3,x4,y4,a,b,c,d,d1,d2,alpha,beta,gamma,p,s ; public : void init (void) ; void storony (void) ; void diagonali(void) ; void angles (void) ; void perimetr (void) ; void ploshad (void) ; void printelements (void) ;}; // Объявление класса параллелограммов – наследника четырехугольников class parall: public fourangle { public: void storony (void) ; void perimetr (void) ; void ploshad (void) ;}; //Объявление класса ромбов – наследника параллелограммов class romb: public parall { public: void storony (void) ; void perimetr (void) ;}; //Объявление класса квадратов – наследника ромбов class kvadrat: public romb { public: void angles (void) ; void ploshad (void) ;}; //Описания функции – членов класса void fourangle:: init(void) { cout <<”\n Ввести координаты вершин:\n”; cin>>x1>>y1>>x2>>y2>>x3>>y3>>x4>>y4; } void fourangle ::stiriny(void) { a=sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)) ; b=sqrt((x3-x2)*(x3-x2)+(y3-y2)*(y3-y2)) ; c=sqrt((x4-x3)*(x4-x3)+(y4-y3)*(y4-y3)) ; d=sqrt((x4-x1)*(x4-x1)+(y4-y1)*(y4-y1)) ; } void fourangle :: diagonali(void) { d1=sqrt((x1-x3)*(x1-x3)+(y1-y3)*(y1-y3)) ; d2=sqrt((x2-x4)*(x2-x4)+(y2-y4)*(y2-y4)) ; } //Функция ugol не является членом какого-либо класса. Она выполняет // вспомогательную роль для функции angles. Эта функция может //независимо программе для определения // углов треугольника, заданного длинами сторон double ugol (double aa, double bb, double cc) { double vspcos, vspsin, pi; pi=4*atan(1.0); vspcos=(aa*aa+bb*bb-cc*cc)/2/aa/bb ; vspsin=sqrt(1-vspcos*vspcos) ; if (abs(vspcos)>1e-7) return(atan(vspsin/vspcos)+pi*(vspcos<0))/pi/180 ; else return 90.0; } void fourangle :: angles(void) { alpha=ugol(d,a,d2); beta=ugol(a,b,d1); gamma=ugol(b,c,d2); delta=ugol(c,d,d1); } void fourangle:: perimeter(void) { p=a=b=c+d;} void fourangle:: ploshad(void) { double per1, per2; per1=(a+d+d2)/2; per2=(b+c+d1)/2; s=sqrt(per1*(per1-a)*(per1-d)*(per1-d2))+ 57 использоваться и в основной sqrt(per2*(per2-b)*(per2- c)*(per2-d1)); } void fourangle:: printelements(void) { cout<<”Стороны:\n”<<a<<” “<<b<<” “<<c<<” “<<d<<”\n”; cout <<”Углы:\n<<alpha”<<” “<<beta<<” “<<gamma<<” “<<delta<<”\n”; cout<< “Периметр:\n”<<p<<”\n”; cout<< “Площадь:\n”<<s<<”\n”; cout<<”Диагонали: \n”<<d1<<” “<<d2<<”\n”; } void parall::storony(void) { a=sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)); b=sqrt((x3-x2)*(x3-x2)+(y3-y2)*(y3-y2)); c=a; d=b;} void parall :: perimetr(void) { p=2*(a+b) ;} void parall :: ploshad(void) {double per; per=(a+d+d2)/2; s=2*sqrt(per*(per-a)*(per-d)*(per-d2));} void romb::storony(void) { a=b=c=d=sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)) ;} void romb ::perimetr(void) {p=4*a ;} void kvadrat::angles(void) { alpha=beta=gamma=delta=90.0;} void kvadrat::ploshad(void) { s=a*a ; } //Основная функция. По координатам вершин квадрата вычисляет и // выводит все его параметры void main(void) { kvadrat obj; //Объявление объекта класса «квадрат» obj.init(); obj.storony(); obj.diagonali(); obj.angles(); obj.perimetr(); obj.ploshad(); obj.printelements(); } В результате выполнения теста на экране будет получено: Ввести координаты вершин: 0 01 1 2 0 1 -1 Стороны: 1.414214 1.414214 1.414214 1.414214 Углы: 90 90 90 90 Периметр: 5.656854 Площадь: 2 Диагонали: 2 2 Конструкторы и деструкторы Основное назначение конструктора – инициализация элементов-данных объекта и выделение динамической памяти под данные. Конструктор срабатывает при выполнении оператора определения типа «класс для объекта». Деструктор освобождает выделенную конструктором память при удалении объекта. Области памяти, занятые данными базовых типов, таких, как int, float, double и т.п., выделяются и освобождаются системой автоматически и не нуждаются в помощи конструктора и деструктора. Конструктор и деструктор объявляются как члены-функции класса. Имя конструктора совпадает с именем класса. Имя деструктора начинается с символа ~(тильда), за которым следует имя класса. Пример. Объявляется класс для строковых объектов. В этом примере конструктор с помощью оператора new резервирует блок памяти для указателя stringl. Освобождение занятой памяти выполняет деструктор с помощью оператора delete. class string_operation { char*stringl; int stringl_len; public: string_operation(char*) //Конструктор 58 {string=new char[string_len];} ~string_operation() //Деструктор { delete string;} void input_data(char*); void output_data(char*); }; В основной программе явного обращения к конструктору и деструктору не требуется. Они выполняются автоматически. Полиморфизм допускает использование функций с одним и тем же именем (а также операций) применительно к разным наборам аргументов и операндов, а также к разным их типам, в зависимости от контекста программы. В Си++ полиморфизм реализован через механизм перегрузки. Внутри класса допускается существование нескольких функций с одинаковым именем, но различающимися типами результатов и наборами формальных параметров. При обслуживании обращения к такой функции компилятор выбирает подходящий вариант в зависимости от количества и типов аргументов. Пример. В ниже приведенной программе определяется перегруженная функция modul() класса absolute, которая возвращает абсолютное значение как целочисленного, так и вещественного аргумента. В первом случае для этого используется библиотечная функция abs(), принимающая аргумент типа int, во втором случае – fabs(), принимающая аргумент типа double. #include<iostream.h> #include<math.h> class absolute { public: int modul(int); double modul (double);}; int absolute:: modul(int x) { return (abs(x)) ;} double absolute :: modul(double x) { return (fabs(x)) ;} void main() { absolute number; cout<<”Абсолютное значение числа – 765 равно:”<<number.modul(-765)<<endl; cout<<”Абсолютное значение числа – 23.987 равно:”<<number.modul(-23.987)<<endl; В результате работы получим: Абсолютное значение числа -765 равно 765 Абсолютное значение числа -23.987 равно 23.987 Перегрузка операций. Полиморфизм в Си++ реализуется не только через механизм перегрузки функций, но и через перегрузку операций. Применительно к объектам определенного класса могут быть определены специфические правила выполнения некоторой операции. При этом сохраняется возможность ее традиционного применения в другом контексте. Для перегрузки операции применительно к классу в число членов класса должна быть включена специальная функция операции, которая определяет действия, выполняемые по этой операции. Формат определения функции-операции: тип_возвращаемого_значения operator знак_операции (спецификации_параметров_операции) (тело_функции-операции) Рассмотрим пример программы, в которой используются перегружаемые операции. Пример. Класс vector определяет трехмерный вектор в евклидовом пространстве. В этом классе будут использоваться перегруженные операции сложения (+) и присваивания (=) как операции с трехмерными векторами. Сумма двух векторов вычисляется как вектор, компоненты которого равны суммам соответствующих компонент слагаемых. Операция = выполняет покомпонентное присваивание векторов. # include<iostream.h> class vector {int x,y,z; // Компоненты вектора public: vector operator + (vector t); vector operator = (vector t); void show(void); void assign (int mx, int my, int mz);} //Перегрузка операции + vector vector:: operator+(vector t) {vector temp; temp.x=x+t.x; temp.y=y+t.y; temp.z=z+t.z;} 59 //Перегрузка операции= vector vector:: operator=(vector t) {vector temp; temp.x=t.x; temp.y=t.y; temp.z=t.z; return *this; // Использован this (см. ниже) } void vector :: show(void) { cout<<x<<”,”; cout<<y<<”,”; cout<<x<<\n; } void vector :: assign (int mx, int my, int mz) { x=mx; y=my; z=mz; } // Основная программа void main (void) { vector a,b,c; a.assign (1,2,3); b.assign (10,10,10); a.show(); b.show(); c=a+b; // Работают перегруженные операции +,= c.show(); c=a+b+c; c.show; c=b=a; c.show; b.show; } В результате выполнения программы на экране получим: 1, 2, 3 10, 10, 10 11, 12, 13 22, 24, 26 1, 2, 3 1, 2, 3 Возникает вопрос: почему бинарные операции-функции и = имеют в описании только по одному аргументу? Дело в том, что другой аргумент всегда передается неявно с использованием this-указателя. Оператор Temp.x=this->x+t.x , т.е. х ссылается на this->x. Здесь this ассоциируется с объектом, предшествующим знаку операции. Объект справа от знака операции передается как параметр функции. Если аналогичным образом определять унарные операции как функции-члены класса, то для них не требуется указания параметра. Объект, к которому относится операция, передается в функцию неявно через указатель this. Например, для класса vector можно добавить объявление унарной постфиксной операции ++; vector operator++ (void); Описание этой функции будет следующим: vector vector :: operator ++(void) { x++; y++; x++; return * this; } Форматированный ввод-вывод в Си++ Для организации ввода-вывода в Си++ можно использовать средства языка Си (conio.h). Однако в Си++ существует стандартная библиотека классов, ориентированная на организацию потокового ввода-вывода. Классы ввода-вывода образуют иерархию по принципу наследования. Базовым в этой иерархии является класс ios (исключение составляют лишь классы буферизированных потоков). В классе ios объединены базовые данные и методы для ввода-вывода. Прямыми потомками класса ios являются классы istream и ostream. Класс istream –это класс входных потоков; ostream –класс выходных потоков. Потомком этих двух классов является iostream – класс двунаправленных потоков ввода-вывода. Объект cout принадлежит к классу ostrem и представляет собой поток вывода, связанный с дисплеем. Объект cin принадлежит классу istream и является потоком ввода, связанным с клавиатурой. Оба эти объекта наследуются классом iostream. Знак << обозначает перегруженнуюоперацию вставки символов в поток вывода cout, а >> - знак операции извлечения из потока ввода cin. Для организации форматированного потокового ввода-вывода в Си++ существуют два средства: - применение функций-членов класса ios для управления флагами форматирования; - применение функций-манипуляторов. Управление флагами форматирования. Флаги форматирования- двоичные коды, управляющие форматом выводимых значений. В заголовочном файле iostream.h определено следующее перечисление , задающее флаги форматирования: enum{ skipws = 0x0001 отбрасывание пробелов left = 0x0002 выравнивание по левому краю поля right = 0x0004 выравнивание по правому краю поля 60 internal = 0x0008 заполнение пустых позиций dec = 0x0010 выдача в десятичном виде oct = 0x0020 выдача в восьмеричном виде hex = 0x0040 выдача в шестнадцатеричном виде showbase =0x0080 выдача основания системы счисления showpoint= 0x0100 выдача позиции точки uppercase= 0x0200 выдача в формате хх.хххх Ехх showpos = 0x0400 выдача знака у положительного числа scientific = 0x0800 выдача в форме с плавающей точкой fixed = 0x1000 выдача в форме с фиксированной точкой unibuf = 0x2000 улучшенная выдача stdio = 0x4000 освобождение потока }; Фактически в этом списке содержатся имена констант, определяющие флаги соответствующих назначений. Коду формата соответствует целый тип long. Изменить состояние флагов формата можно с помощью функции-члена класса ios, имеющей прототип long setf (long flags) Например, чтобы установить флагshowbase в активный режим (включить) применительно к стандартному потоку вывода, используя оператор cout.setf(ios::showbase); Для установки флагов можно использовать побитовые операции. Например: cout.setf(ios::left|ios::hex); В результате включаются одновременно флаги, управляющие выравниванием по левому краю и выводом целых значений в шестнадцатеричной системе. Для выключения используется функция unsetf (long flags); Например, для отмены вывода основанием системы счисления используется оператор: cout.unsetf(ios::showbase); Представим еще некоторые функции-члены класса ios: long flags(void) - возвращает текущее состояние флагов; int width (int len) – возвращает текущую ширину поля вывода и устанавливает значение ширины, равное len; char fill(char ch) - возвращает текущий символ заполнения и устанавливает новый символ заполнения ch; int precision(int num) – возвращает текущее число десятичных знаков после точки и устанавливает значение этого параметра равным num. Пример. Рассмотрим нижеприведенную программу, которая иллюстрирует применение рассмотренного способа управления форматным выводом. #include<iostream.h> void main(void) { long fl; fl=cout.flags(); cout<<”Исходное состояние флагов:”<<fl<<”\n”; //Выведется целое число - код флагов, установленных по // умолчанию cout.set(ios::shoupos); cout.set(ios::scientific); cout<<123<<” “<<1.2345678<<”\n”; //Выведется: //+123+1.23456e+00 cout.set(ios::hex | ios::showbase); cout.unseft(ios::showpos); cout.width(15); cout.precision(10); cout<<123<<” “<<123.456” “1.2345678<<”\n”; //Выведется: //0x7B 1.2345e+02 1.234567e+00 cout<<”Новое состояние флагов:”<<cout.flags()<<”\n”; //Выведется: // Новое состояние флагов: 0х28С1 cout.flags(fl);//Возврат к исходному состоянию cout<<”После восстановления исходных флагов:\n”; cout<<123<<” “<<123.456<<1.2345678<<”\n”; //Выведется: //После восстановления исходных флагов: } Использование манипуляторов. Для управления форматами потокового вывода можно использовать специальные функции, называемые манипуляторами. Доступ к программе к стандартным манипуляторам можно получить, подключив файл iomanip.h. Список стандартных манипуляторов: 61 dec endl ends flush hex resetiosflags(long f) setbase(int base) setfill (char ch) srtiosflags(long f) setprecision(int p) setw(int w) ws Десятичный формат Вывод “\n”и освобождение буфера Вывод NULL Освободить поток Шестнадцатеричный формат числа Отключить флаги, определенные f Установить основание системы счисления Установитьсимвол заполнения Включить флаги, указанные f Установить р цифр в дробной части Установить ширину поля выдачи Режим пропуска символов пробела Пример. В следующей программе вычисляется и выводится на экран таблица значений функций sin x и cos x на n шагах в интервале от 0 до р. Для форматирования таблицы результатов используются манипуляторы. #include<iostream.h> #include<math.h> #include<iomanip.h> void main() { double a,b,x; int n=20; a=0; b=4*atn(1.); cout<<” x sin(x) cos(x)”<<endl; cout<< ”- - - - - - - - - - - - - - - - - - - -- - - - - - - -“<<endl; for(x=a; x<=b;x=x+(b-a)/n) cout<<setprecision(4)<<setw(10)<<x<< “ ” <<setprecision(4)<<setw(10)<<sin(x)<< “ <<setprecision(4)<<setw(10)<<cos(x)<<endl; } Начальная часть таблицы, выводимая по этой программе, имеет вид: ” x sin(x) cos(x) ----------------------------------------------0 0 1 0.1571 0.1564 0.9877 0.3142 0.309 0.9511 0.4712 0.454 0.891 0.6283 0.5878 0.809 0.7854 0.7071 0.7071 Под каждое число выделяется по 10 позиций на экране. По умолчанию число занимает крайнюю правую позицию в отведенном под него поле. Оставшиеся слева позиции занимает символ-заполнитель. По умолчанию символомзаполнителем является пробел. Однако с помощью манипулятора setfill() его можно заменить. Если в крайних правых позициях оказываются нули, то они не выводятся. Действие манипулятора распространяется только на значение, непосредственно следующее за ним в потоке вывода. 6. Планы семинарских (практических) занятий № Тема Содержание семинарского занятия 7. Ознакомительная работа Реализация программ 8. Этапы работы с на языке Си программой на языке Си Работа с экранным меню. 1 Технологии разработки программ и их реализация на алгоритмических языках Выражения в Си Реализация практических заданий 3. Использование выражений в языке Си 4. Структура программы на Си: заголовок программы, тело главной функции Спецификации и их применение Неделя 1 Литература [11] 10-15 [9] 15-22 [3] 202-207 1. 2. 2 Реализация программ на языке Си 62 1 [3] 202-207 [11] 10-15 [9] 15-22 Практическое применение констант 3 9. Именованные константы 10. Константы перечисляемого типа 11. Целые и вещественные константы 12. Использование препроцессорной директивы для указания именованных констант Основные базовые типы данных, представление в памяти, размер, диапазон значений 1. 4 5 6 Программирование линейных алгоритмов Применение операций на практике в программах на языке Си Применение операций на практике в программах на языке Си 2. 3. 4. Функция клавиатурного ввода данных Функция вывода тестовых сообщений Функция вывода данных Потоковый ввод-вывод в Си++ Операции присваивания Префиксные и постфиксные операции декремента и инкремента Операция sizeof, ее назначение и практическое применение 2 [11] 20-23 [9] 15-26 2 [9] 27-30 [11] 25-30 3 [11] 31-37 [9] 33-43 3 [9] 33-43 [11] 31-37 4 [11] 78-89 [9] 40-43 4 [9] 40-43 [11] 78-89 5 [9] 44-46 [11] 90-101 5 [9] 44-46 [11] 90-101 6. 7. 1. 2. 3. Условная операция. Операция запятая Работа с заданием Полная форма условного оператора 8. Сокращенная форма условного оператора 9. Вложенные операторы 10. Блоки операторов 7. 7 8 9 10 Условный оператор и его применение в языке программирования Си Переключатель и применение в языке программирования Си 1. 2. Переключатель, его блоксхема и его назначение Альтернативный переключатель, его применение, блок-схема Программирование циклических алгоритмов на языке Си 4. 5. Программирование циклических алгоритмов на языке Си 1. Цикл с параметром и различные варианты его применения Цикл с предусловием Цикл с постусловием Описание одномерных массивов 9. Инициализация массивов и их особенности 10. Ввод-вывод одномерных массивов 11. Разбор примеров 8. 11 Массивы одномерные 63 6 [4] 217-222 1. 12 2. Массивы двумерные 3. 3. 13 Массивы Практическое применение массивов для решения задач с двумерными и одномерными массивами 1. 14 Массивы 4. 15 Функции 5. 6. Практическое применение массивов для решения задач с двумерными и одномерными массивами Создание программ с использованием прототипа Создание программ без использования прототипа Практическое решение задач с использованием функций 1. 16 Особенности описаний массивов в программах Инициализация двумерных массивов Ввод-вывод двумерных массивов . Функции Практическое решение задач с использованием функций Стандартные функции для обработки строк. 4. Описание для символьных переменных 3. Строка как параметр функции 6 7 7 8 8 [3] 217-222 [3] 217-222 [3] 217-222 [3] 217-222 [3] 217-222 3. 17 Обработка символьных строк 1. 18 Обработка символьных строк 5. 19 6. Структуры в языке Си 7. 20 Объединения и применение Указатели 4. Составление программ с использованием указателей Работа над индивидуальным заданием 1. 22 23 Указатели в языке Си Потоковый ввод- Понятие структуры в языке Си Область применения структур Формат описания структур в программах 1. Понятие объединения 2. Область применения объединения 3. 21 Решение задач с применением библиотечных функций для обработки строк и символьных переменных 2. 3. Особенности использования указателей в Си Практическая реализация задач с использованием указателей Объявление потока в 9 9 10 10 11 11 12 64 [3] 230-234 [3] 230-234 [3] 234-240 [3] 234-240 [3] 223-229 [3] 223-229 [3] 240-249 вывод в стандарте Си 4. программе Практическое применение 24 Потоковый вводвывод в стандарте Си 1. 2. Работа с файлами на диске Запись и чтение символов 25 Потоковый вводвывод в стандарте Си 1. 2. Запись и чтение блоков данных Практическая реализация программ 26 Функции и область действия переменных 3. 4. Описание в программе Решение практических задач 3. Практическая реализация программ с использованием объектов Объектноориентированное программирование в Си++ 27 28 29 Объектноориентированное программирование в Си++ Практическая реализация программ с использованием объектов Графика 2. Практическое использование графических возможностей Си 30 12 Построение графических объектов 1. 13 13 14 14 15 Создание графических объектов 15 [3] 240-249 [3] 240-249 [3] 362-365 [3] 250-261 [3] 250-261 [3] 420-427 [3] 420-427 7. Методические рекомендации по изучению дисциплины В данном разделе представлены типовые задания, выполнив которые студент практически сможет реализовать знания, полученные на лекциях по дисциплине «Языки программирования». Для выполнения их необходимо предварительно изучить теоретический материал по лекциям или, прибегая к учебникам. Задания несложные, позволяющие на практике посмотреть, как работают , рассматриваемые в изучаемом разделе операторы, процедуры, функции и в дальнейшем применять их для решения сложных задач. Первоначальные задания направлены на повторение пройденного материала в рамках изученного ранее курса. Типовые задания для индивидуального выполнения: Задание 1. Вычислить значение выражения по формуле (все переменные принимают действительные значения). b b 2 4ac a 3c b 2 1. 2a 2. y 1 3. 3 e 1 x 2 y tgx 4. sin x cos y tgxy cos x sin y ln y x y x x2 x 4 Задание 2. Вычисления в математических задачах. Вычислить периметр и площадь прямоугольного треугольника по длинам a и b двух катетов. Заданы координаты трех вершин треугольника (x1, y1), (x2, y2), (x3, y3). Найти его периметр и площадь. Вычислить площадь и периметр правильного n-угольника, описанного около окружности радиуса r (рассмотреть n – целого типа, r - вещественного типа). Определить, во сколько раз площадь круга радиуса r больше сегмента, отсеченного хордой длины а. Задание 3. Задачи на составление логических выражений. 65 Составить линейную программу, печатающую значение true, если указанное высказывание является истинным, и false – в противном случае. 1. Целое число n является четным двузначным числом. 2. Среди чисел f,b,c есть хотя бы одна пара взаимно противоположных. 3. Даны три стороны одного и три стороны другого треугольника. Эти треугольники равновеликие, т.е. имеют равные площади. 4. Сумма цифр данного трехзначного числа n является четным числом. Задание 4. Области, описываемые логическими выражениями. 1. Для заданных областей составить линейную программу, которая печатает true, если точка с координатами (x,y) принадлежит этой области, и false – в противном случае. Области задаются индивидуально. Задание 5. Условные вычисления 1. Даны три действительных числа. Возвести в квадрат те из них, значения которых неотрицательны, и в четвертую степень – отрицательные. 2. Даны два угла треугольника (в градусах). Определить, существует ли такой треугольник, и если да, то будет ли он прямоугольным. 3. Услуги телефонной сети оплачиваются по следующему правилу: за разговоры до А минут в месяц – И тенге, а за разговоры сверх установленного тарифа оплачиваются из расчета С тенге за минуту. Написать программу, вычисляющую плату за пользованием телефоном для введенного времени разговора за месяц. 4. Определить правильность даты, введенной с клавиатуры (число – 0т 1 до 31, месяц – от 1 до 12). Если введены некорректные данные, то сообщить об этом. Задание 6. Вычисление значений функций. Вычислить значение функции: x 2 3x 9, еслиx 3 1. f(x)= 1 , еслиx3 3 x 6 x 2 3 x 9, еслиx 3 . 2. f(x)= 1 , еслиx3 3 x 6 Задание 7. Оператор выбора 1. Написать программу, которая по номеру дня недели выдает в качестве результата количество занятий в этот день. 2. Написать программу, которая бы по введенному номеру времени года (1 – зима, 2 – весна, 3 – лето, 4 - осень) выдавала соответствующее этому времени года месяцы, количество дней в каждом из месяцев. 3. Написать программу, которая по номеру месяца выдает название следующего за ним месяца. 4. Написать программу, которая по вводимому числу от 1 до 11 (номер класса) выдает соответствующее приветствие «Привет k-классник». Задание 8. Циклы 1. Начав тренировки, спортсмен в первый день пробежал 10 км. Каждый день он увеличивал дневную норму на 10% нормы предыдущего дня. Какой суммарный путь пробежит спортсмен за 7 дней? 2. Дано натуральное число n . Вычислить: S 1 1 1 1 1 n ... 1 * n 2 4 8 2 3. Дано действительное x. Вычислить: x3 x5 x 7 x9 x3! 5! 7! 9! 4. Даны числовой ряд и некоторое число . Найти сумму тех членов ряда, модуль которых больше или равен . Общий член ряда имеет вид: 3n * n! an 2n! 1. Составить программу для вычисления значений функций f(x) на отрезке [a,b] с шагом h. Результат представить в виде таблицы, первый столбец которой – значения аргумента, второй – соответствующее значение функции. F(x)= 2cos√x + 0,5. 66 Задание 9. Массивы 1. При поступлении в ВУЗ абитуриенты, получившие двойку, ко второму экзамену не допускаются. В массиве A[n] записаны оценки экзаменующихся, полученные на первом экзамене. Подсчитать, сколько человек не допущено ко второму экзамену. 2. Дана последовательность чисел, среди которых имеется один нуль. Вывести на печать все числа до нуля включительно. 3. Упорядочить одномерный массив по возрастанию. 4. Транспонировать квадратную матрицу и вывести результат на экран. Задание 10. Работа со строками 1. Дана строка, заканчивающаяся точкой. Подсчитать, сколько слов в строке. 2. Дана строка, содержащая текст. Найти длину самого короткого слова и самого длинного слова. 3. Дана строка. Преобразовать ее, удалив каждый символ * и повторив каждый символ, отличный от *. 4. Проверить, является ли заданное слово перевертышем. Задание 11. Подпрограммы 1. Найти площадь пятиугольника, если известны все стороны и диагонали. 2. Составить программу для нахождения наибольшего общего делителя и наименьшего общего кратного двух натуральных чисел ( НОК ( А, В )) 3. 4. А* В НОД ( А, В) Есть часть катушки с автобусными билетами. Номер билета шестизначный. Составить программу, определяющую количество счастливых билетов на катушке, если меньший номер билета – n , больший – m (билет считается счастливым, если сумма первых трех цифр равна сумме последних трех цифр). Написать программу, определяющую сумму n- значных чисел, содержащих только нечетные цифры. Определить также, сколько четных цифр в найденной сумме. Задание 12. Структуры и объединения 1. Заданы имена девушек. Определить, какие из этих имен встречаются во всех группах курса. 2. Имеется множество, содержащее натуральные числа из некоторого диапазона. Сформировать два множества, первое из которых содержит все простые числа из данного множества, а второе – все остальные. 3. Известны марки всех машин, выпускаемых в данной стране и импортируемых за рубеж. Даны некоторые n стран. Определить для каждой из марок, какие из них были: Доставлены во все страны; Доставлены в некоторые страны; Не доставлены ни в одну страну. 4. Задан текст. Напечатать в алфавитном порядке все гласные буквы, которые входят в каждое слово. Задание 13. Структуры и объединения 1. Распечатать список студентов, фамилии которых начинаются на букву В, с указанием даты их рождения. 2. Из ассортимента конфет выбрать те, стоимость которых от300 до 500 тенге за 1 кг. Указать срок годности и номера магазинов, в которых они продаются. 3. Распечатать анкетные данные студентов, участвующих в олимпиаде и получивших более 70 баллов. 4. Составить программу начисления стипендии студентам по результатам сессии, используя следующие правила: Если все оценки 5, назначается повышенная стипендия 15%; Если все оценки 4 и 5, назначается обычная стипендия; Если оценка 3, то стипендия не назначается . В результате работы программы должен быть напечатан список группы с оценками и средним баллом каждого студента и два списка фамилий (назначенных на повышенную и обычную стипендию). Задание 14. Файлы 1. Заполнить файл последовательного доступа f целыми числами, полученных с помощью генератора случайных чисел. Получить в файле g те компоненты файла f , которые являются четными. 2. Задан файл, содержащий различные даты. Каждая дата – это число, месяц и год. Найти год с наименьшим номером. 3. Задан текстовый файл. Сколько слов в тексте? Сколько цифр в тексте? 4. Задан текстовый файл. Удалить из него все лишние пробелы, оставив между словами не более одного пробела. Результат поместить в новый файл. 67 Задание 15. Классы 1. Реализовать в виде модуля набор подпрограмм для выполнения следующих операций над числами: Сложение; Вычитание; Деление; Умножения. Задание 16. Указатели 1. Составить программу, которая вставляет в список новый элемент за каждым вхождением определенного элемента списка. 2. Составить программу, которая удаляет из списка все отрицательные элементы. Задание 17. Графика. Построить чертежи к следующим задачам: 1. В прямоугольном параллелепипеде провести диагональное сечение. 2. Построить правильную четырехугольную пирамиду. 3. Построить сектор и закрасить его 8. Методические рекомендации и указания по типовым расчетам, выполнению расчетно-графических, лабораторных работ, курсовых проектов (работ) (не предусмотрено программой курса) 9. Материалы для самостоятельной работы студента Цель работы: изучить работу с массивами одномерными и двумерными 1. Решение задач по индивидуальным вариантам 2. изучение методов сортировки массивов 3. Работа с двумерными массивами Контрольные вопросы. 1.Что такое массив? 2.В чем заключается метод «пузырька»? ЗАДАНИЕ: « Функции» Цель работы: изучение особенностей построения подпрограмм на языке Си 1.Формализовать постановку задачи. 2.Составить список используемых переменных. 3. Составить программу. Контрольные вопросы. 1. Что такое прототип, определение, тело функции? 2. Какие данные необходимы для организации функций ? 3. Как осуществляется возврат данных из функций? 4. Что такое подпрограмма? 2. Для чего используются подпрограммы? Задание «Работа со строковыми переменными» 1. Формализовать постановку задачи. 2. Составить список используемых переменных. 3. Составить программу. Контрольные вопросы 1. Каким образом описываются строковые данные? 2. Указать основные функции для работы со строковыми переменными: опеределение длины строки, копирование, вставка и другие. Для желающих закрепить изучаемый материал, предлагаются дополнительные задачи: Линейные программы 1. Составьте алгоритм и программу нахождения площади ромба по стороне и острому углу.(Угол предварительно переведите в радианы) S=a^2 sin f, где a- сторона, f-угол. 2. Среднее значение четырех чисел равно одной четверти суммы этих четырех чисел. Напишите программу, которая находит среднее значение четырех чисел. 3. Человеку нужно съездить из Лондона в расположенный в 390 милях Эдинбург. Он может ехать на автомобиле марки Роллс-Ройс, либо на автомобиле марки Форд Эскорт. Роллс-Ройс расходует 1 галлон бензина на каждые 15 миль пути. Форд Эскорт расходует 1 галлон бензина на каждые 36 миль пути. Сколько будет стоить поездка в Эдинбург на Роллс-Ройсе, если стоимость 1 галлона бензина составляет X-фунта? Сколько денег он сбережет, если вместо этого он поедет на 68 машине марки Форд Эскорт? 4. Работник зарабатывает X руб. за каждые из 38 часов своей работы. Ему платят в 1,5 раза больше за каждый час сверх 38 часов. Какую сумму он получит если работает A час.(A должно быть заведомо больше 38). 5. В пяти тестовых опросах мальчик получил оценки. Составьте программу, которая определит среднее значение оценок, полученных мальчиком в пяти опросах. 6. Вычислите заработанную плату работника при почасовой системе оплаты, если ставка за 1 час и количество отработанных часов в месяц. 7. По двум сторонам и углу между ними в треугольнике ABC найдите два остальных угла и третью сторону. C^2= A^2 + B^2 - 2AB cos f , где A, B-известные стороны, f-угол между ними. 8. Составьте алгоритм и программу вычисления подоходного налога от заработной платы.(Подоходный налог исчисляется в размере 13% от общей суммы). 9. Автомобиль на каждом из пяти одинаковых по длине участков дороги шел с известной средней скоростью. Составьте алгоритм и программу для определения средней скорости на всем пути. 10. Реактивный аэробус летит с пассажирами на борту из Лондона в Нью-Йорк. Три четверти пассажиров имеют билеты первого класса, стоимостью X фунтов за каждый. Остальные пассажиры имеют билеты первого класса, которые стоят вдвое дороже билетов второго класса. Напишите программу, которая выведет сумму денег, получаемую авиакомпанией от продажи билетов на этот рейс. 11. Команда Ливерпуля выиграла футбольный матч у команды Ковентри со счетом a:b. Выведите результат матча в виде: Ливерпуль 4, Ковентри 1. Осуществите запрос a и b. 12. Как вы полагаете, сколько денег вы расходуете каждую неделю? Напишите программу, которая выведет на экран сумму ваших расходов за год. Предположим, что вы хотите прожить до 80 лет. Добавьте в вашу программу операторы для вывода на экран той суммы, которую вы израсходуете за это время. 13. Составьте алгоритм и программу вычисления скорости тела в момент времени t при равноускоренном движении. Известны начальная скорость V0 и ускорение a, при условии, что тело движется прямолинейно. Vt= V0 + at. 14. Составьте алгоритм и программу вычисления сопротивления в цепи электрического тока R по данным значениям тока 1 и напряжения V. R=V/1. 15. Магазин продает B автомашин по цене 417 525 руб. за каждую. Найдите общую выручку от продажи машин. 16. Хозяин хочет оклеить обоями длинную стену в своем доме. Длина этой стены равна a м., а высота в м. Рулон обоев имеет длину 12 м и ширину 1м. Сколько будут стоить обои для всей стены, если цена одного рулона k руб. 17. Заработок рабочих на фабрике составил 624 750 руб.Его нужно разделить поровну между A рабочими . Выведите заработок каждого рабочего. 18. Найдите площадь круга если известен радиус. S=3,14R^2. 19. Четыре человека пообедали в ресторане. Официант подал им счет на X руб. каждому. Они решают оставить официанту чаевые в размере 15% от счета. Составьте программу, которая выведет на экран сумму израсходованную в ресторане и размер чаевых. РАЗВЕТВЛЯЮЩИЕСЯ ПРОГРАММЫ. 1. Округлите действительное положительное число x, меньше 5, до ближайшего целого числа: 0,если X<0.5; 1,если 0.5<=X<1.5; 2,если 1.5<=X<2.5; N(x)= 3,если 2.5<=X<3.5; 4,если 3.5<=X<4.5; 5,если 4.5<=X. 2. Группу детей, приехавшую в пионерский лагерь, распределяют по отрядам по принципу: с 6 до 7 лет - 5 отряд, с 7 до 9 лет - 4 отряд, с 9 до 11 лет - 3 отряд, с 11 до 13 лет - 2 отряд, с 13 до 15 лет (включительно) - 1 отряд. Составьте программу, которая позволила бы каждому приезжающему самому определять свой отряд. В лагере имеется персональная ЭВМ. 3. Вычислите значение функции: X^2, если X=>1; 69 Z= 1, если -1<X<1; X^3, если X,<=-1. 4. Для натурального К напечатайте фразу "мы нашли "К" грибов в лесу", согласовав окончание слова "гриб" с числом К. 5. Известно, что астрологи делят год на 12 периодов и каждому из них ставят в соответствие один из знаков Зодиака: 20.1 - 18.2 Водолей 23.7 - 22.8 Лев 19.2 - 20.3 Рыба 23.8 - 22.9 Дева 21.3 - 19.4 Овен 23.9 - 22.10 Весы 20.4 - 20.5 Телец 23.10 - 22.11 Скорпион 21.5 - 21.6 Близнецы 23.11 - 21.12 Стрелец 22.6 - 22.7 Рак 22.12 - 19.01 Козерог Напишите программу, которая вводит дату некоторого дня года и печатает название соответствующего знака Зодиака. 6. Составьте программу, определяющую, как заданная сумма денег выражается минимальным числом банкнот ценностью по 100, 50, 25, 10, 5, 3 и 1 руб. На печать выводится сумма денег, количество банкнот каждого вида и общее число банкнот. 7. Составьте алгоритм и программу, выбирающую из трех чисел то, которое лежит между двумя другими. 8. В старо-японском календаре был принят 60 летний цикл, состоявший из пяти 12-ти летних подциклов. Подциклы обозначались названиями цвета: зеленый, красный, желтый, белый, черный. Внутри каждого подцикла годы носили названия животных: крысы, коровы, тигра, зайца, дракона, змеи, лошади, овцы, обезьяны, курицы, собаки, свиньи.(1984 год-год зеленой крысы был началом очередного цикла). Напишите программу, которая вводит номер года нашей эры и печатает его название по старо-японскому календарю с указанием цвета. 9. Самолет летит из пункта A в пункт B со средней скоростью V. Составьте алгоритм нахождения времени в полете t, если возможны три варианта: а) дует встречный ветер (K=1); б) ветра нет (K=2); в) дует попутный ветер (K=3). 10. Если автомобиль движется со скоростью более, чем 50 км/час, он расходует 1 литр бензина на каждые 20 км пути. Если он движется со скоростью меньше 50 км/час, он расходует 1 литр бензина на каждые 30 км. Автомобиль должен проехать всего B км. Напишите программу, для которой входной величиной является скорость автомобиля. Эта программа должна вывести на экран количество литров бензина, расходуемых на все путешествие. 11. Напишите программу, которая будет распечатывать любой из столбиков таблицы умножения (предусмотрите возможность ошибок при вводе). ЦИКЛЫ. 1. Составьте программу вычисления 20-го и 25-го чисел из ряда Фибоначчи. (числа Фибоначчи - это члены последовательности 0,1,1,2,3,5,..., где каждый последующий, начиная с третьего вычисляется как сумма двух предыдущих. Первые два числа 0 и 1 заданы). 2. Выведите на экран орнамент "*-*-*-* +.+.+.+.+" Из 16 строк с повторяющимся узором. 3. Напечатайте 20 раз свою фамилию. 4. Найдите сумму и произведение всех четных чисел от 1 до 20. 5. Найдите сумму, произведение всех нечетных чисел от 1 до 20. 6. Распечатайте значения функции y=tg x для всех целых x-10 до 10. 7. Найдите произведение первых 10 членов натурального ряда. 8. Каждая бактерия делится на две в течение одной минуты. В начальный момент имеется одна бактерия. Сколько их станет через 15 минут? 9. Сберегательная касса начисляет 2% годовых (т.е. через год вклад увеличивается на 2% без участия вкладчика). Какой станет сумма (в рублях),положенная в сберкассу на n лет ? 10. В течение двух недель человек заключает пари на скачках. В первый день он делает ставку в 1 фунт и проигрывает. Во второй день, чтобы возместить свой проигрыш, он делает ставку в 2 фунта, но снова проигрывает. На третий день он ставит три фунта, однако опять проигрывает. Он упрямо продолжает увеличивать на 1 фунт свою ставку, но продолжает проигрывать. Напишите программу, которая при выполнении выведет на экран сумму денег, проигранную этим человеком к концу второй недели. 11. Вы должны своему другу 5 рублей. Вместо того, чтобы попросить вас вернуть ему сразу весь долг, ваш друг предлагает, чтобы вы платили ему определенную сумму еженедельно в течение 10 недель. Он просит вас уплатить ему в первую неделю 1 копейку, во вторую -2, в третью -4,в четвертую -8 и т.д. Вы 70 уже почти согласились с его предложением, но затем решаете сначала написать программу, чтобы проверить, какую сумму вам придется заплатить, если вы примете его предложение. Напишите эту программу и решите, каким же способом лучше выплатить свой долг. 12. Население города увеличивается на 3% каждый год. В 1983 году население города составляло 65000. Напишите программу, которая выведет на экран предсказываемую численность населения города в каждом году вплоть до 1993 г. 13. В текущем месяце бригада в каждый последующий день работы выпускала на три изделия больше, чем в предыдущий. В первый день было выпущено 42 изделия, что составило 67% дневной нормы (в месяце 26 дней). Напечатайте: "Бригада выполнила норму" или "Бригада не выполнила норму", в зависимости от полученного результата. 14. Найдите произведение цифр заданного четырехзначного числа. 15. Определите число, полученное выписыванием в обратном порядке цифр заданного трехзначного числа. ВЛОЖЕННЫЕ ЦИКЛЫ. 1. Выведите на экран всевозможные сочетания из четырех нечетных чисел, сумма которых равна 10. 2. Запрашиваются результаты экзаменов по трем предметам у трех учащихся. Определите лучший результат и выведите его порядковый номер. 3. Найдите все двузначные числа, сумма квадратов цифр которых делится на 13; 17; 19. 4. Припишите к 1022 слева и справа по одной цифре так, чтобы полученное число делилось на 7, 8 и 9. 5. В десятичной записи числа 42*4* две цифры пропущены. Восстановите их, если известно, что число кратно 72. 6. Сколько существует четырехзначных чисел, кратных 45, две средние цифры которых 9 и 7? 7. Три друга были свидетелями дорожного происшествия. Первый заметил, что номер нарушителя делится на 2, 7 и 11, второй запомнил, что в записи номера участвуют две цифры, а третий, что сумма цифр равна 30. Определите номер нарушителя. 8. Найдите все двузначные числа, сумма квадратов цифр которых делится на 13. 9. Найдите все делители числа 1234. 10. Найдите все трехзначные числа, кратные 15, но не кратные 30. 11. Напечатайте все четырехзначные натуральные числа, в десятичной записи которых нет двух одинаковых цифр. 12. Припишите к 523*** три такие цифры справа, чтобы полученное шестизначное число делилось на 7, 8, 9. 13. Составьте программу вывода всех трехзначных десятичных чисел, сумма цифр которых равна данному целому числу. 14. Сколько существует натуральных чисел, меньших 1000 не делящихся на 5 и 7. 15. Долгожитель (т.е. человек, проживший более ста лет) заметил, что если к сумме квадратов цифр его возраста прибавить число его дня рождения (т.е. число от 1 до 31), то получится как раз его возраст. Сколько лет долгожителю. 16. Найдите все трехзначные числа, которые можно представить разностью между квадратом числа, образованного первыми двумя цифрами и квадратом третьей цифры. 17. Сколько существует положительных целых чисел X, меньших 100, для которых 2-X делится на 7. 18. Найдите все двузначные числа, сумма цифр которых не меняется при умножении числа на 2, 3, 4, 5, 6, 7. Одномерные массивы 1. В произвольном массиве поменяйте местами соседние четные и нечетные по номеру элементы. Дополнительные массивы не использовать. 2. Для заданного массива А из М чисел сформируйте массив В из М/2 чисел по формуле : В (I)=(А(I)+ А (M+1-I))/2 Предусмотрите каким-либо образом случай, когда М нечетно. 3.Дан натуральный массив S(N). Постройте на экране дисплея N столбиков так, чтобы была высота 1-го столбика была равна S(I). 71 4.Измените знак всех нечетных (четных) элементов массива, состоящего из L чисел (предусмотреть случай наличия нецелых элементов) 5. Сожмите массив, выбросив каждый второй его элемент (дополнительные массивы использовать не разрешается). 6. Найдите номер минимального и максимального элемента последовательности А1,А2,А3,...,АN. 7. Задан одномерный массив А(N), состоящий только из нулей и единиц. Проверьте, существует ли строгое чередование. 8. В массиве М(N) осуществите сдвиг на К<N элементов вправо без использования дополнительных массивов (первые К элементов при этом остаются на месте, последние К будут потеряны). 9. Заданы два одномерных массива А и В, состоящие из произвольного числа элементов. Сформируйте массив С, содержащий элементы обоих массивов, расположенные в порядке возрастания. 10. Ввести с клавиатуры n-элементный числовой массив А и число Т. Найти количество элементов массива, меньших Т. 11. Ввести с клавиатуры n-элементный числовой массив А и число Т. Найти сумму элементов массива, больших Т. 12. Объединить два массива А(N) и В(N) в один массив С(2*N) следующим образом: С(1)=А(1), С(2)=В(1),С(3)=А(2), С(4)=В(2),...,С(2*N-1)=А(N), С(2*N)=B(N). В этой задаче предполагается, что массивы заполняются с клавиатуры. 13.Изменить порядок следования элементов в массиве на обратный. 14.Для массива Х найти: среднее арифметическое положительных элементов массива. 15. Для массива Х найти: сумму элементов, стоящих четных местах. 16. Для массива X найти: среднее арифметическое элементов, лежащих в отрезке [1;2]. 17. Для массива X найти: количество положительных, отрицательных и равных нулю элементов. 18. Для массива X найти: количество элементов для которых ближайшим целым является 1. 19. Описать числовые массивы Х,Y,Z и выполнить преобразования: переписать элементы массива Х в массив Y в обратном порядке. 20.Описать числовые массивы X,Y,Z и выполнить преобразования: сформировать массив Y(1)=X(1)+X(N), Y(2)=X(2)+X(N-1), Y(3)=X(3)+X(N-2) и т.д. (N-четное) 21.Описать числовые массивы X,Y,Z и выполнить преобразования: запись в массив Y номера элементов массива X, лежащих в отрезке [0,1]. 22. Описать числовые массивы X,Y,Z и выполнить преобразования: записать в массив Y элементы массива X, имеющие четные индексы, а в массив Z элементы ,имеющие нечетные индексы. 23.Описать числовые массивы X,Y,Z и выполнить преобразования: записать в начало массива Y положительные, а в конец - отрицательные элементы массива X, сохраняя порядок элементов. 24. В массиве А поменять местами наибольший и наименьший по значению элементы. 25. Сформировать новый массив из элементов массива A, больших 7 и при этом имеющих индексы, кратные 4. 26. Данные о росте учеников класса представлены в виде массива. Рост девочек кодируется знаком "+" (положительные элементы), рост мальчиков знаком "-" (отрицательные элементы). Определить средний рост мальчиков и девочек по отдельности. 27. Ввести список участников соревнования по метанию диска и их результаты. Напечатать фамилию чемпиона и его результат. 28. Определить, имеется ли в одномерном числовом массиве хотя бы одна пара совпадающих по величине соседних чисел. 29. Определить в одномерном числовом массиве число соседств из взаимно обратных чисел. 30. Проверить, имеется ли в одномерном числовом массиве хотя бы одна пара взаимно противоположных соседних чисел. 31.Найти произведение ненулевых элементов одномерного числового массива размерностью N. 32.Задан одномерный числовой A(N) массив. Вычислить сумму произведений всех пар соседних чисел. 33. В массиве Z$(N), элементы которого буквы латинского алфавита, подсчитать количество и указать порядковые номера всех букв "A". 34. Задан символьный массив B $ (N) (элементы B $ (I)-буквы). Найти в этом 72 массиве все буквы "C" и указать их порядковые номера. 35. Символьный массив K $ (N) содержит N слов. Подсчитать сколько в этом массиве слов начинается с приставки при - . 36. Задан массив B(N). Каждому элементу массива присвоить значение соседнего с ним справа. Последнему элементу присвоить значение первого. 37. Сформировать массив размером N, если каждый элемент подсчитывается по формуле. 38. Проверить, является ли заданный одномерный числовой массив упорядоченным по возрастанию. 39. Сформировать два одномерных массива A и B размером N, в которых и вычислить их средние арифметическое (в каждом массиве). 40. Задан числовой массив A (N). Сосчитать и напечатать, сколько различных чисел в этом массиве. 41. Дан массив A(10). Упорядочить элементы массива по возрастанию. 42. Задан числовой массив A (1,N). Найти длину самой длинной последовательности подряд идущих элементов массива, равных нулю. 43. В массиве X (N) каждый элемент равен 0,1 или 2. представить элементы массива так, чтобы сначала располагались все нули, затем все единицы и, наконец, двойки. 44. Даны действительные числа А1, А2,...,А18. Получить:А1, А10, А2, А11, ...,А9,А18. 45. Даны символы S1,S2,...,S17. Получить: S17, S1, S16, S2,.... 46. Дано натуральное число M и целочисленный массив A(M). Сосчитать и напечатать сколько различных чисел в этом массиве. 47. Дан массив A(N) и массив B(N). Отпечатать массив Z(N), элементы, которого a(i)-b(i) Zi= --------и найти среднее арифметическое массива Z(N). 3i 48. В одномерном массиве A(N) подсчитать количество отрицательных элементов. 49. В одномерном числовом массиве C(N) найти max и min элементы. 50. Организовать циклическую перестановку элементов массива. 51. Подсчитать количество положительных и отрицательных элементов в массиве {f}. Размер массива вводиться с клавиатуры. 52. Заполните массив A[1:10] случайными числами, выведите на печать содержимое элементов массива с нечетными индексами. 53. В заданном массиве B[1:6]. Найдите индекс элемента, равного числу P. Предусмотрите случай, когда такого элемента не будет. 54. Дан массив натуральных чисел S[1:N]. Постройте на экране дисплея N столбиков так, чтобы высота была равна S[i]. 55. Заполните линейный массив из 15 элементов числами от-15 до 15 и выведите на экран сумму всех его отрицательных элементов. 56. Задан одномерный массив A[1:10]; A[1]=1, A[2]=2, каждый следующий элемент определяется из соотношения: A[n]=(A[n-1]+ A[n-2])/n. Выведите получившуюся последовательность на экран. 57. Постройте таблицу B, состоящую из элементов таблицы A[1:75], имеющих четные индексы. 58. Для целочисленного массива A[1:15] определите, является ли сумма его элементов четным числом. Выведите на печать "ДА" или "НЕТ". 59. Вычислите среднее геометрическое элементов массива A[1:40], имеющих четные индексы. 60. Введите таблицу оценок за контрольную работу по геометрии. Найдите среднее арифметическое оценок. Найдите среднее геометрическое. Какое значение больше? Проверьте на оценках за сочинение. 61. Заданы значения A,B,С и массив M[1:15]. Постройте алгоритм, который по вводимому коду операции K, принимающему значения 1, 2, 3, выполняет следующие действия: а) увеличивает значения элементов массива на A, при K=1; б) уменьшает значения элементов массива на B, при K=2; в) печатает индексы элементов, которые равны C, при K=3. 62. При предоставлении работнику ежегодно оплачиваемого отпуска в n трудовых дней ему начисляется "отпускные" следующим образом: вычисляется средняя зарплата за последние 12 месяцев, делится на 25,4 и умножается на n. Постройте алгоритм, запрашивающий необходимые данные и печатающий размер выплаты для n=12, n=24, n=36. 63. Заполните массив P[1:10] суммой соответствующих элементов массива A[1:10] и B[1:10]. Значения элементов массивов A[1:10] и B[1:10] можно задать датчиком случайных чисел. 64. Составьте алгоритм запроса 10 чисел, заполнения таблицы и выбора из них всех неотрицательных. 73 65. Создайте таблицу из 30 чисел, лежащих в промежутке от-13 до 13 и выведите на экран номера всех неотрицательных. 66. Подсчитайте для массива X[1:10] количество элементов, ближайшим целым числом, для которых является 1. 67. Определите, имеются ли в заданной последовательности два подряд идущих нулевых элемента. 68. В массиве A[1:10] определите: а) количество элементов меньших -3; б) номер первого такого элемента (если они есть); в) номер последнего такого элемента. 69. Дан ряд чисел:1,3,5,7,9,11,13,15,17,19. Составьте программу для вывода на печать двух соседних чисел: первого и второго, второго и третьего, третьего и четвертого и т.д., а также результаты их сложения или умножения, при чем при сумме чисел больше 15 выводить на печать их произведение. 70. В таблице из 20 чисел, лежащих в промежутке от -50 до 50, замените все отрицательные числа на их абсолютные значения. 71. Задан массив B[1:M], содержащий большое количество нулевых элементов. Замените каждую группу подряд идущих нулей на один нуль. 72. Имеются данные о ценах на 10 видов товаров. Определите номер самого дорогого товара, который может приобрести покупатель, имеющий заданную сумму денег. 73. Найдите самое длинное звено ломаной, координаты вершин которой сведены в две таблицы X[1:9], Y[1:9]. 74. Для данного одномерного массива укажите индексы тех его элементов, сумма которых равна заданному числу (если такие есть). 75. Переставьте элементы одномерного массива в обратном порядке. Нового массива не заводите. 76. Найдите максимальный элемент массива B[1:10]. 77. Найдите номер максимального и минимального элементов массива A[1:N], попавших в интервал (A,B). 78. Дана температура 6 месяцев (3-х осенних и 3-х весенних). Определите самый холодный месяц. 79. Экспертные оценки продукции имеют 4 пункта. Определите лучшее изделие по сумме экспертных оценок: T[i]= A[i] + B[i] + C[i] + D[i]. Напечатайте результат в порядке расположения от лучших показателей к худшим. Число изделий N. 80. В таблицу занесена последовательность из 10 чисел, взятых в промежутке от -5 до 5. Найдите: а) наименьший член последовательности; б) наименьший из положительных членов; в) наибольшее из всевозможных попарных произведений. 81. В массиве A[1:25] найдите максимальное и минимальное отношение элементов массива A[i] / A[i+1]. 82. Числовая прямая разбита на произвольные отрезки точками A1,A2,A3,..., AN. Выясните, какому из отрезков принадлежит данная точка X. 83. В таблице A[20] подсчитайте количество четверок A[i], A[i+1], A[i+2], A[i+3] идущих подряд членов, из которых: а) все члены равны; б) все члены различны. 84. Дан одномерный массив N[1:25]. Все его элементы, не равные 0, перепишите, сохраняя их порядок, в начало массива, а нулевые в конец массива. 85. Даны две таблицы по 10 чисел в каждой. Найдите наименьшее среди тех чисел первой таблицы, которые не входят во вторую таблицу(считается, что хотя бы одно число такое есть). 86. Расположите элементы произвольного одномерного массива в порядке возрастания (дополнительные массивы использовать не разрешается). 87. Заданы два одномерных массива A и B, состоящие из произвольного (не слишком большого) числа элементов. Сформируйте массив C, содержащий элементы обоих массивов, расположенные в порядке возрастания. 88. Из двух упорядоченных одномерных массивов (длины K и N) сформируйте массив размером K + N, упорядоченный: так же как исходные массивы. Используйте упорядоченность исходных массивов. 89. Из двух упорядоченных одномерных массивов (длины K и N) сформируйте массив размером K + N, упорядоченный: в обратную сторону. Используйте упорядоченность исходных массивов. 90. Элементы массива упорядочены по возрастанию. Требуется присвоить переменной K номер элемента массива, равного числу Y, или O, если такого элемента нет. Для поиска используйте следующий метод: сравнить Y со средним элементом массива (или элементом около середины, если количество элементов нечетно). Если они равны, поиск прекращается, если элемент массива меньше Y, то требуемый следует искать в правой половине. Если элемент массива больше Y, то следует искать в левой половине. ДВУМЕРНЫЕ МАССИВЫ. 74 1. Найти наибольший элемент двумерного массива. 2. В двумерном массиве найти суммы элементов в каждом столбце и сформировать из них одномерный массив. 3. Найти абсолютное значение разности минимального элементов двумерного массива. 4. Опишите двумерные массивы и заполните их следующими значениями: 11111 22222 33333 4 4 4 4 4. 5. Опишите двумерные массивы и заполните их следующими значениями: 1357 1357 1357 1 3 5 7. 6. Сформировать единичную матрицу. (Единичная матрица - это квадратная числовая таблица, у которой главная диагональ (идущая из левого верхнего угла в правый нижний состоит из единиц, а все остальные элементы равны нулю.) 7. Найти наибольший и наименьший элементы на главной диагонали двумерного массива (двумерный массив является квадратной числовой таблицей). 8.Заполните случайными числами в диапазоне от 0 до 10 таблицу 5*5. Выведите ее на экран. 9. Заполните случайными числами массив 6*6. Выведите на печать четвертую строку массива. 10. Составить программу вычисления произведения элементов двумерного массива, больших 10. 11. Определить, имеется ли в двумерном массиве элемент, равный числу В. Элементы массива вводятся с клавиатуры. 12. Составить программу вычисления суммы положительных элементов двумерного массива. 13. Сформировать двумерный массив, элементы которого равны 5, если сумма их индексов четная, и 0, если сумма индексов нечетная. 14. Составить программу, определяющую, содержится ли в двумерном массиве столбец, состоящий из одинаковых элементов. 15. Дан двумерный массив A(N,M). Вычислить сумму элементов данного двумерного массива и их среднее арифметическое. 16. В массиве A(M,N) напечатать все номера строк, элементы которых все положительные или все отрицательные. 17. Найти наибольший элемент каждой строки матрицы X(5,5) и записать их в массив Y. 18. Ввести число N и заполнить двумерный массив размером N*N числами 1,2,3,... по спирали. 19. Заполнить квадратную матрицу N*N последовательными числами от 1 до 100 по спирали. 20. Дан двумерный числовой массив N*M. Найти min в каждой строке и Вывести на экран. 21. Определить номера строк в двумерном массиве размером N*M, содержащие только положительные элементы. 22. В двумерном символьном массиве размерностью M*N найти все строки, содержащие только буквы "A" и "B". 23. В двумерном символьном массиве A$ (N,M). Найти сколько букв "A" в каждой строке и букв "B" в каждом столбце. 24. В двумерном массиве CES (N,M) найти max (максимальный элемент). 25. В заданном двумерном массиве BOX (N,M) подсчитать среднее арифметическое каждой строки. 26. В двумерном числовом массиве подсчитать количество и сумму положительных, и количество и сумму отрицательных. Задан массив MAG (N,M). 27. Дан двумерный символьный массив A $ (N,M). Подсчитать сколько в данном массиве букв "B" и "Д". 28. Дан двумерный массив A (N,M) вычислить сумму элементов каждой строки. 29. Дан двумерный символьный массив К $ (N,N). Подсчитать сколько в нем букв "А" всего, и сколько их в каждой строке. 30. В двумерном числовом массиве найти и отпечатать номера строк в которых среднее арифметическое больше заданного числа Т. 31. В двумерном числовом CES (N,M) подсчитать среднее арифметическое в каждой строке. ОБРАБОТКА ТЕКСТОВ. 1. В переменные A ,C, B записаны слова английского языка. Напечатать 75 данные слова в алфавитном порядке. 2. В переменные A, B, C записана текстовая информация. Расположить тексты в порядке убывания их длин в те же переменные. 3. Определить, сколько слов содержится в тексте, где разделителем слов служит один пробел. 4. Первое слово текста записать в переменную A, а последнее в переменную B. 5. Слова, записанные в массив A (n), расположить пирамидкой в порядке возрастания их длин. Взять 0<n<20. 6. Определить, сколько слов содержится в тексте T, где разделителем слов служит последовательность из трех пробелов. 7. Определить, сколько слов содержится в тексте, где слова отделены друг от друга n пробелами. (0<n<8). 8. Определить, сколько предложений содержит текст, если предложения могут оканчиваться знаками: ".", "!", "?". 9. Записать слово текста, где разделителем слов служит 1 пробел, в массив A (n). 10. Записать слова текста, где разделителем слов служит последовательность из n пробелов, в массив A (k). 11. Определить, сколько раз в тексте встречается буква "a". 12. Из текста выбрать и напечатать слова, содержащие букву "в". 13. Определить, сколько знаков препинаний содержит текст T. 14. Подсчитать, сколько различных цифр содержит текст. Распечатать таблицу тех цифр, которые в данном тексте не используются. 15. Подсчитать, сколько раз каждая десятичная цифра встречается в тексте . 16. Подсчитать, сколько раз каждая буква латинского алфавита встречается в тексте. 17. Подсчитать, сколько раз каждая буква латинского алфавита встречается в тексте T (n), состоящем из n предложений. 18. Определить, сколько гласных букв русского алфавита встречается в тексте. 19. Распечатайте введенную текстовую строку наоборот. 20. Подсчитайте количество слов и стоимость пересылки текста в телеграмме. Стоимость слова 1 руб. 30 коп. 21.Замените в тексте каждое вхождение одной буквы на другую. Например, замена "б" на "к" тексте "баран бьет в барабан" дает результат: "каран кьет в каракан". 22. В условии предыдущей задачи замените одно сочетание символов на другое. Например, замена "ба" на "пли" в тексте "барабан" даст "плираплин". 23. Составьте алгоритм, проверяющий правильность расстановки скобок в формуле. 24. Составьте алгоритм запрашивающий символьную строку и выводящий ее же, но в обратном порядке. Например: "коза"-"азок". 25. Назовем слово "перевертышем",если оно одинаково читается справа налево и слева направо (например: казак, шалаш). Требуется проверить, является ли введенное слово перевертышем. 26. Палиндром-это символьная строка, отличающаяся от перевертыша тем, что знаки пунктуации и пробелы при сравнении не учитываются. Составьте алгоритм, проверяющий, является ли данная строка палиндромом. Проверьте на строках: "МАДАМ"; "М АДАМ"; "А МАN, А PLA"; "A CANAL-PANAMA"; "ШАЛАШ"; "ША ? ЛАШ". 27. Дан текст: "У Мери маленький ягненок, Его шерстка бела как снег. Куда бы Мери ни ходила, Ягненок всюду рядом с ней". Напишите программу для подсчета числа слов в каждой строке этого текста. Ваша программа должна вывести также общее число слов в этом тексте. 28. Составьте алгоритм, подсчитывающий, сколько раз в тексте встречается заданный фрагмент (цепочка символов). Например, в тексте "банан упал на барабан", фрагмент "ба" встречается 3 раза, а "бан"- 2 раза. 30. Текст состоит из 240 символов. Слова отделяются друг от друга пробелами и запятыми, предложения- точкой. Проверьте, есть ли в тексте фраза "что и требовалось доказать". 31. Текст состоит из 240 символов. Слова отделяются друг от друга пробелами и запятыми, предложения - точкой. Замените в тексте фразу "что и требовалось доказать" на сочетание "чтд.", тем самым сжав текст. 32. Подсчитайте число гласных букв в слове "Прозаседавшиеся". 33. Выясните, сколько раз встречается каждая буква алфавита в предложенном тексте. 76 ПОДПРОГРАММА. 1. Подсчитайте 1! + 2! + 3! + ... + n!, используя вспомогательный алгоритм для вычисления k!. Обязательно ли при подсчете каждого слагаемого вычилять факториал ? 2. Вычислите значение выражений: x! + y!. 3. Составьте программу вычисления значения функции. Вычисления f(x) оформите во вспомогательном алгоритме. f(x)=(x+x^2+1), при x=1,8,15,21. 4. Составьте программу вычисления значения функции. Вычисления f(x) оформите во вспомогательном алгоритме. f(x)=(1/2y), при y=0,8,3,5,6. 5. Составьте программу вычисления значения функции. Вычисления f(x) оформите во вспомогательном алгоритме. f(x)=tg(a)-(a^2-3)/2, при a=5,18,4. 6. Составьте программу вычисления числа сочетаний из N по M. Число сочетаний определяется по формуле N!/(M!(N-M)!), где N-количество элементов перебора. Используйте подпрограмму вычисления факториала.(5!=1*2*3*4*5). 7. По координатам трех вершин некоторого треугольника найдите его площадь и периметр. Вычисление длины стороны оформите как вспомогательный алгоритм. 8. Даны отрезки а,б,с,д. Для каждой тройки отрезков, из которых можно построить треугольник, напечатайте площадь данного треугольника, воспользоваться вспомогательными алгоритмами определения возможности создания треугольника и вычисления площади. 9. Напишите программу, которая для данной функции, заданной вспомогательным алгоритмом, на отрезке (А,В) вычисляет сумму значений функции в N точках, делящих отрезок на N равных частей, умноженную на длину отрезка и деленную на N. 10. Четыре точки заданны своими координатами на плоскости. Найдите площадь параллелограмма, вершинами которого являются эти точки. Вычисление площади параллелограмма выполните в подпрограмме. 11. Составьте программу вычисления функции Z=(K1+K2)/(S1+S2), где S1 и K1 сумма и количество положительных элементов массива B[1:12].Для вычисления суммы и количества элементов используйте подпрограммы. 12. Даны два одномерных массива A[1:10] и B[1:10]. Замените все элементы, следующие за членом с наибольшим значением на 0.5, как в массиве A[1:10], так и в массиве B[1:10]. Используйте подпрограмму для нахождения максимального члена массива. 10. Методические указания по прохождению учебной, производственной и преддипломных практик, формы отчетной документации (Не предусмотрено программой) 11. Материалы по контролю и оценке учебных достижений обучающихся - схема оценки знаний - письменные контрольные задания - тестовые задания - перечень вопросов для самоподготовки Схема оценки знаний № п/п 1 2 3 4 5 6 7 Оценка вида Критерий оценки Кол-во выполненных работ балл за работу Активность на лекции Активность на семинаре (практическом занятии) Активность на лабораторном занятии Активность на занятии СРСП Выполнение заданий СРС Индивидуальные задания Коллоквиум Рубежный контроль Промежуточная аттестация (Р1, Р2) Текущий контроль Рейтинг допуска 100 100 15 15 100 15 100 15 100 100 100 100 100 15 6 2 2 Среднеарифметическая сумма всех оценок (Р1+Р2)/2 Текущий контроль 77 *0,6 100*0,4 Итоговый контроль(экзамен) Итого Рейтинг допуска + итоговый контроль В течение семестра проводятся рубежные контроли (коллоквиумы на 7 и 14 неделях). Максимальный показатель успеваемости студента по рубежным контролям составляет 60%. В конце семестра проводится экзамен в форме тестирования. Максимальный показатель успеваемости по экзамену составляет 40%. Итоговая экзаменационная оценка по дисциплине определяется как сумма максимальных показателей успеваемости по рубежным контролям (max 60%) и экзамену (max 40%) составляет 100%. Преподаватель в каждую 7 и 15 недели семестра выставляет результаты рейтингового контроля. Схема оценки знаний по дисциплине «Языки программирования» Итоговая оценка подсчитывается по формуле: U=(P1+P2)/2*0.6+E*0.4, где P1- цифровой эквивалент оценки первого рейтинга; P2- цифровой эквивалент оценки второго рейтинга; E - цифровой эквивалент оценки на экзамены Буквенная оценка и ее цифровой эквивалент в баллах определяется по %-ному содержанию правильных ответов: Оценка знаний По буквенной системе А А+ В+ В ВС+ С СД+ Д В баллах В %-ном содержании По традиционной системе 4,0 3,67 3,33 95-100 90-94 85-89 Отлично 3,0 2,67 2,33 2,0 1,67 1,33 1,0 0 80-84 75-79 70-74 65-69 60-64 55-59 50-54 0-49 Хорошо Удовлетворительно F Неудовлетворительно : Выставленную оценку можно апеллировать, при этом создается комиссия, назначенная зав. кафедрой, где происходит разбор ответов. Максимальный балл выставляется при выполнении всех заданий в срок (в этом случае не вычитываются штрафные баллы) работа должна соответствовать всем предъявленным требованиям. Поощрительные баллы могут быть назначены (+3 балла), если работа включает в себя дополнительные действия, не предусмотренные заданием, применяется особое оформление, выполнены рефераты по изучаемым темам (+5 баллов). В случаях пропусков, опозданий, низкой активности на занятиях, поздней отчетности (вне графика) работ студент штрафуется (по 0,5 за каждое нарушение в отдельности). Материалы для контроля знаний 1. Определить правильно записанный идентификатор а) MAX б) rus_disk в) # include г) 1B5C 1. а, в 2. б, в 3.б, г 4. а, б 2. Какие типов данных относится к базовым? а) char б) char в) char г) таких нет int long int unsigned int float float float double long double double 3. Деление по модулю осуществляет операция: а) / б) =/ в) % г) mod 4. Определить, какие значения получат переменные а, в, с в результате выполнения c=а + + *в + +, если первоначальное значение а=3; в=2; 78 а) а=4; в=3; с=12; б) а=3; в=2; с=6; в) а=4; в=2; с=8; г) нет правильного решения; 5. Записать логические выражение 0 < х ≤ =1 или х ≥ 2 а) 0 < х< =1 or х >=2 б) х >0 and х<=1 or х>=2 в) нет правильного ответа г) (х >0) && (х< =1) || (х >=2) 6. В результате выполнения операции 1100 <<2 получим: а) 110000 б) 001100 в) 1100 г) 101000 7. Формат оператора вызова функции scanf () : а) scanf (“% d”); б) scanf (“% d / n”,&а); в) scanf (“% d”,&а); г) scanf (&а); 8. Для подключения математических функций используется директива препроцессора. а) # include <stdio.h> б) include <conio.h> в) # include < math.h> г) нет такой директивы; 2. Запись printf (“а= %f \n“, к) означает. а) Вывод значения а; б) Ничего не означает в) Вывод значение а и перевод строки; г) Подачу звукового сигнала; 3. Что будет получено в результате выполнения следующих действий: х =5; х <0 ? -х: х; а) х=5; б) х = -5; в) х =<|5|; г) Ничего; 4. Указать ошибки при записи программы, которая вычисляет площадь треугольника по формуле Герона. # include <stdio. h> # include < math.h> float а, b, с, s; void main () { printf (”Ввести данные”); scanf (“%f %f %f“, а, b ,с); p=(a+b+c)/2; s=sqrt (p*(p-a) *(p-b) *(р -с)); printf (“s= %f ”,&s); } а) Нет описания p; б) в scanf () необходимо указать &а, &b, &с; нет описания p; в) в scanf () надо проставить &а, &b, &с; в printf() необходимо убрать & перед s, нет описания p. г) ошибок нет; y= Указать правильное выполнение действии; 5. 2 log3 (x +1)+ (arcctg x 1 ,если х>0 )/ecos(x) +lnx2 , если х<=0 x 1 2 а) # include <stdio. h> # include <math. h> float x,y; void main () { scanf ("%f", &x ); if (x>0) y=log (x*x+1)/ log (3)+ sqr(x+1); if (x>0) y=1/ atan (x*x+1) ^ (1/3)/ exp.(cos(x))+log(x *x);} б) # include <stdio. h> # include <math. h> float x,y; void main () { if (x>0) y=log (x*x+1)/ log (3)+ sqrt (x+1); if (x<=0) y=1/ atan (pow (x,2)+1^ (1/3)/ exp(cos(x))+log(pow(x,2));} в) # include <stdio. h> # include <math. h> float x,y; void main () { 79 if (x>0) y= log (pow (x,2)+1)/ log(3) + sqrt (x+1); if (x<=0) y=1/ pow (atan (x*x+1),1/3)/ exp(cos(x))+log(pow(x,2));} г) # include <studio. h> # include <math. h> float x,y; void main () { if (x>0) y= log (pow (x,2)+1)/ log(3) + sqrt (x+1); if (x<=0) y=1/ atan (pow (pow (x,2)+1),1/3)/ exp(cos(x))+ln (pow(x,2)); } 1. а.г 2. б.в 3. в.а 4. Нет правильного ответа. 12. Оператор break для оператора switch выполняет функцию а) прерывание б) продолжение в) остановки г) нельзя применять 13. Задан фрагмент циклической программы. Какой вариант соответствует этой записи. f=1; for (i=1; i<=n; i++) f=f+i; а) for (f=1, i=1; i<=n; i++) f=f+i; б) for (f=1, i=1; i<=n; f=f+i, i++) в) f=1; for (i=1; i<=n; f=f+i, i++) г) f=1; for (i=1; i<=n;) f=f+i; i++; 1. a 2.a,б 3.а,б,с 4.все 14. Запись while (1) означает: а) условие повторения ложно; б) условие повторения истинно; в) запись не верна; г) запись ничего не определяет; 1. а 2. б 3. в 4.г 15. Функции fmod (х, у) определяет: а) ближайшее целое не превышающее х; б) ближайшее целое не меньше х; в) остаток от деления нацело х на у; г) возведение в степень х у; 16. Составить программу вычисления объема куба по данной длине ребра. а) # include <stdio.h> б) # include <stdio.h> int a, v; int a, v; void main () void main () { { scanf (“% f”,&a); scanf (“%c”, &a); v = a^3; v=a*a*a; } } в) г) # include <stdio.h> int a, v; {void main () scanf (“%d”, &a); v=pow (a,3);} # include <stdio.h> # include <math.h> int a, v; {void main () scanf (“%d”, &a); v=pow (a,3); } 17. cosh (х) означает: 80 а) вычисление косинуса угла б) вычисление аркосинуса угла в) вычисление гиперболического косинуса г) неправильная запись 18. Что выполняет данная программа: # include <stdio.h> {void main () int i = 1; float eps, s=0; scanf (“%f”, &eps); while (1/n>eps) { S+=1/n ++; }} а) вычисляет сумму 1+1/2 + 1/3 + … с заданной точностью. б) Находит сумму в) Проверяет условие выхода из цикла г) Находит среднее арифметическое 19. Запись int a[10]; означает а) объявление переменой; б) объявление функции; в) объявляет массив; г) ничего не объявляет; 20. Указать описание внешней переменной: 1. # include <stdio.h> int m,n; void main () 2. а) 1 г) нет правильного ответа б) 2 в) 1, 2 # include <stdio.h> extern int m, n ; void main () 21. Какое значение получат в, с, d , если enum z= {a=5, b, c, d}; а) 1, 2, 3 б) 6, 7, 8 в) 0, 1, 2 г) нет правильного ответа. 22. Определить какое описание переменных является правильным: а) char s, i; б) long int a; в) long int a; г) unsigned int а; int а; short int в; long double в; long int в; float в, с; double с; float с; long float с; double е,в4; char d; char d; char d; unsigned int d; float f; int f; int е; 1. Все 2. а, б, в 3. а, б, г 4. б, в, г 23. Спецификатором формата ввода - вывода является: а) # include <stdio. h> б) «% d» в) # define n=5; г) = 24. Определить какие значения переменные а, в, с получат в результате выполнения следующих действий С = + + а * + + в, если а=3; в=2; а) а=3; в=3; с=9; б) а=4; в=2; с=8; в) а=4; в=3; с=12; г) нет решения; 25. К операциям отношения в языке Си относятся следующие: а) < б) < в) < г) < <= <= <= > > > > <= >= >= >= >= = == == = <> <> != != 26. Указать правильные операции присваивания: а) а + = 2; б) а= а+2; в) а =c+ +; г) r= r % 5; х - = а + в; р /=10; в = а * с; а = + +с; m * = n; r % =5; d =p / c; d = m*n; а = в = с = х + у; а = в = х + у; f = к - с; f = а + в; 1. а; 2. в; 3. Нет правильного ответа; 4.все варианты верны 81 27. В результате выполнение y=(х=3, 5*х) получим: а) х=3; у=15; б) у=15; в) х=3; г) нет решения; Координаты точки на плоскости заданы переменными x и y. Записать следующие условия в форме логических выражение: точка лежит в первой четверти координатной плоскости. а) if (х >0)&&(у>0); б) if ((х >=0)&&(у>=0)) в) if (х >=0)and(у>=0); г) if (х >0)and(у>0) 1. а; 2. б; 3. в; 4.г; 28. Оператором вывода являются следующие функции: а) printf (); б) printf (); в) puts (); г) printf (); puts (); scanf (); scanf(); 1. Управляющий символ \t в операторе printf () означает: а) перевод на новую строку; б) горизонтальную табуляцию; в) вертикальную табуляцию; г) сигнал - звонок; 2. Определить правильную запись функции puts (); а) puts ("\n Вывод"); б) puts ("Вывод"); в) puts ("Вывод = % f", к); г) puts (Вывод); 1. а, б; 2. б; 3. в; 4. в, г; 3. Найти большее из двух чисел а и b; а) if (а>b) then{maх =а; min=b;}else {maх =b; min=а;} б) if (а>b) {maх =а; min=b;}else {ma х=b; min=а;} в) if а>b {maх =а; min=b;}else {maх =b; min=а;} г) if а>b maх =а; min=b; else maх =b; min=а; 4. Составить программу для вычисления корней квадратного уравнения а) # include <stdio. h> б) # include <stdio.h> float а, в, с, d, х1, х2; float а, в, с, d, х1, х2; void main () void main () { { scanf ("%f%f%f",&а, &в, &с); scanf ("%f", &а ); d= в*в-4*а*с; scan f ("%f", &в ); if d>0 then scan f ("%f", &c ); x1= (-в + sqrt(d)/(2*а); d= pow (в,2)- 4*a*c; x2= (-в-sqrt(d)/ (2*а); if d>0 then x1= (-в+sqrt(d))/(2*a); printf ("x1=%f; x2=%f",x1,x2); x2= (-в-sqrt(d))/(2*a); } print f ("x1=%f; x2=%f",x1,x2); } в) # include <stdio. h> # include <math. h> float а, в, с, d, х1, х2; void main () { d= pow (в,2) - 4*a*c; if d>0 x1= (-в+sqrt(d))/(2*a); x2= (-в-sqrt(d))/(2*a); printf ("x1=%f; x2=%f",x1,x2); } 1.а,г 2.б,в 3.в,г г) # include <stdio. h> # include <math. h> float а, в, с, d, х1, х2; void main () {d=в*в-4*a*c if (d>0) then x1= (-в-sqrt(d))/(2*a); x2= (-в+sqrt(d))/(2*a); printf ("x1=%f; x2=%f",x1,x2); } 4. Нет правильного ответа 5. Запись на языке Си десятичного логарифма lgx соответствует: а) log (x) б) lg(x) в) ln (x) г) log 10(x) 34. Правильная запись условного оператора для выражения, если х>0, то y=x2; иначе y= а) if (x<0) then y=x*x; else y=sqrt(x); б) if x<0 y=x*x; else y=sqrt(x); в) if (x<0) y= pow (x,2) else y= sqrt(x); г) if (x<0) y= pow (x,2); else y= sqrt(x); 82 x 35. В результате выполнения программы include < stdio.h > int x; void main () scanf (“% d”,&x); switch (x) {case 1: puts (“кол”); case 2: puts (“два”); case 3: puts (“три”); case 4: puts (“четыре”); case 5: puts (“пять”); default: puts (“нет такой оценки”);}} На экране будет выведено при значении х=4 следующее сообщение: а) четыре б) четыре, пять в) четыре, пять, нет такой оценки г) ничего 1. а 2.б 3.в 4.г 36. Задана блок – схема, составить согласно этой схеме алгоритм: а) if (x<=0) if (x==1) y=0; у=1 else y = -1; б) y=1; if (x<=0) if (x=1) y=0; да нет else y=-1; х 0 в) y=1; if (x<=0) if (x==1) y=0; 1. а да 2. нет Б 3. В 4.г. х=1 else y=-1; г) y=1; 37. Сколько типов операторов цикла существует в Си: if (x<=0) then у=0 а) 1 у=- б) 2 в) 3 г) 4 if (x==1) then y=0; 1 y=-1; ограничения: 38. При использовании оператора goto необходимо else учитывать а) нельзя входить внутрь блока извне; б) нельзя входить внутрь условного оператора; в) нельзя входить внутрь переключателя; г) нельзя входить внутрь цикла; 1. а, б 2. а, в 3. а, в, г 4. а, б, в, г 39. Составить программу вычисления n!. Используя цикл с постусловием. а) # include <stdio.h> б) # include <stdio.h> int f, i, n; int f, i, n; void main () { void main () {f=i=1; f=1; i=1; do do f*= i++; f* = f*i; while (i<=n);} i=i+1;} while (i<=n);} в) # include <stdio.h> г) # include <stdio.h> int f, i, n; # include <math.h> {void main () { void main () {f=1; n=1; f=1; n=1; do do f = f*i; f=f*i; i=i+1; i=++; while (i<=n);} while (i<=n);} 1. а, б 2. а, в 3. а, г 4. все 83 40. Оператор continue используется, если надо: а) надо завершить очередной шаг цикла дo того, как будет достигнут конец цикла б) продолжить в) выйти из цикла г) не вызывает никаких действий 41. Задан фрагмент программы на языке Паскаль, определить, что будет соответствовать этому фрагменту на языке Си. f:=1; i:=1; repeat f:=f*i; i:=i+1 until i>n; а) f=i+1; б) f=i=1; в) f=1; i=1; do while (i<=n) do f*=i ++; {f*=i ++; } f=f*i; while (i<=n); i=i+1; while (i<=n); г) 1. а, б f=1; i=1; while (i<=n) { f=f*i; i=i+1; } 2. а, в 3. б, г 4. в, г 42. Задан алгоритм решения в виде блок – схемы, составить программу на языке Си в соответствии с блок – схемой: а) s=0; x=0.5; do s=s+x; x=x+0.5; while (x<=5); б) s=0; x=0.5; for (; x<=5; x + = 0.5) s=s+x; s=0; x=0.5 x<=5 s=s+x 1. а, б, г 2. б, в, г 3. а, в, г в) for (s=0; x=0.5; x<=0.5; x=x+0.5) s=s+0.5; 4. нет варианта x=x+0.5 г) for 43. Запись scanf (“% d % f % e % c”,&a, &b, &с, &d”) означает, что:(s=0, x=0.5; s=s+x; а) а – двойной точности (double) b – вещественное (float) c – экспоненциальное d – символьное (char) б) а – double – двойная точность b – float – вещественное c – экспоненциальное вещественное d – строковое (string) в) а – целое int b – вещественное – float c - экспоненциальное вещественное d – символьное char г) а – длинное целое b – вещественное c – двойная точность double d – строковое double 84 x<=5; x+=0.5) 44. Указать ошибки в фрагменте описания переменных, если они есть: а) # include <stdio.h> б) # include <stdio.h> int x, y; void main () float, a, b; { int x, y ; char c; float a, b; void main () char c;} { } в) # include <stdio.h> int x, y; char c; { void main () float a, b; } г) 1. б 3. г 2. в # include <stdio.h> int x, y ; float a; char c; { void main () int y; float b; } 4. ошибок нет. а) Элементы матрицы а присваиваются элементам матрицы b. б) Транспонирование матрицы а. в) Меняются знаки элементов матрицы а на противоположенного. г) транспонирование матрицы и смена знаков элементов на противоположенные. 45. Что выполняет программа? # include <stdio.h> int a [3][3], b [3][3]; int i, j; void main () { for (i=1; i<=3; i ++) for (j=1; j<=3; j ++) scanf (“%f”, &a[i][j]); for (i=1; i=<3; i ++) for (j=1; j<=3; j ++) b[i][j] = -a[j][i]; } Индивидуальные задания студенты выполняют по следующим темам и отчитываются по согласованию с графиком. 1. Операции в языке Си. 2. Условный оператор и переключатель 3. Циклы. 4. Массивы одномерные, массивы двумерные. 5. Функции. 6. Применение указателей. 7. Структуры и объединения 8. Работа со строковыми переменными. 9. Файлы. 10. Графика. Вопросы для проведения контроля знаний по материалам 1-7 недели Контрольные вопросы для подготовки к лекциям и практическим занятиям и к СРС 1. Алфавит языка Си 2. Существует ли ограничение на множество целых чисел. используемых в языке. 3. Перечислите основные операции, определенные для данных целочисленного типа. 4. Перечислите основные стандартные функции, определенные для данных вещественного типа. 5. Можно ли аргумент стандартной тригонометрической функции задавать в градусах. 6. Из каких символов может состоять идентификатор? 7. Можно ли ключевые слова использовать в качестве имен переменных? 8. Можно ли при записи арифметических выражений на языке Си использовать фигурные скобки? 9. Можно ли при записи арифметических выражений на языке Си использовать квадратные скобки? 10. Можно ли при записи идентификатора использовать русские буквы? 11. Каков приоритет выполнения арифметических операций? 12. Назовите операции отношения, которые применимы к данным целого типа. 13. Какие операции относятся к операциям присваивания? 14. Как записывается в программе восьмеричная константа? 15. Как записывается в программе шестнадцатеричная константа? 85 16. Как записываются десятичные константы? 17. Из каких частей состоит вещественная константа? 18. Что такое именованная константа? 19. Структура программы в языке Си. 20. Как и где можно записать комментарий в программе? 21. Для каких целей используется указание типа переменных? 22. Какими символами ограничивается текст комментария? 23. Назовите процедуру ввода информации. 24. Назовите процедуру вывода информации. 25. Как записывается список переменных при вводе и выводе? 26. Может ли быть пустым список ввода или вывода? 27. Как осуществляется вывод по формату? 28. Какие обозначения используются в форматах. 29. Какое служебное слово используется для описания данных логического типа? 30. Может ли булево выражение содержать несколько операций? 31. Какой оператор используется для организации ветвления? 32. Приведите пример составного оператора. 33. Переключатель, его организация. 34. Альтернативный переключатель и его организация. 35. Какой вид имеют краткая и полная формы условного оператора и их блок-схемы? 36. Какой оператор является оператором цикла с параметром? 37. Как осуществляется прерывание цикла? 38. Организация цикла с предусловием. 39. Организация цикла с постусловием. 40. Понятие внутреннего и внешнего цикла. Вопросы для проведения контроля знаний по материалам 8-14 недели 1. Что такое массив? И какими свойствами он обладает? 2. Формат описания двумерного и одномерного массивов. 3. В чем заключается инициализация массива? 4. Инициализация многомерных массивов. Особенности инициализации массивов в языке Си. 5. В каком случае можно не указывать размеры массива? 6. Назначение функций в языке Си. 7. Определение функции. Каким образом в программах записывается определение функции и где? 8. Формат определения функции. 9. Структура функции . 10. Что понимают под определением тело функции? 11. Каким образом указывается в функциях спецификация параметров? 12. Прототип функции. Его место расположения в программах. В каких случаях используется прототип функций? 13. Описание прототипа функции. 14. Использование библиотечных функций. 15. Как представляются в программах автоматические переменные? 16. Как представляются в программах внешние переменные? 17. Как представляются в программах статические переменные? 18. Что такое регистровая памяти и ее форма представления в программах. 19. Понятия локальных и глобальных переменных. 20. Ссылочный тип данных. 21. Что такое указатель? Представление указателей в программах на Си. 23. Описание указателя. 24. Операции над указателями. 25. Использование указателей для передачи параметров функции. 26. Как представлены строки в языке Си? 27. Какой символ всегда завершает строку ? 28. Какие основные функции существуют в языке Си для обработки символьных строк? 29.Составить функцию, определяющую тождественность двух строк. 30.Составить функцию слияния двух строк. 31. К какому типу можно отнести структуры? 32. Существует ли тип структура? 33. Объяснить правила использования структур. 34. Как называют элементы структуры? 35. Указать формат описания структурного типа. 36. Как осуществляется обращения к элементам структуры? 37. Что понимают под объединением? 38. Как организована внутренняя память для объединения? 39. Как описываются объединения в программе? 86 40. Что понимают под вводом-выводом в программировании? 41. При работе с потоками, что понимают под вводом и что понимается под выводом? 42. Что понимается под файлом в языке Си? 43. Что такое поток? 44. Должен ли быть поток связан с каким-либо внешним устройством? 45. Существует ли тип файл в языке Си? 46. Какое представление файлов используется в языке Си? 47. Какие стандартные потоки для ввода-вывода используется в Си? 48. Каким образом организуется работа с файлами на диске? 49. Как осуществляется открытие потока? 50. Указать режимы открытия потока. 51. Запись и чтение символов в поток. 52. Запись и чтение целых чисел. 53. Запись и чтение блоков данных. 54. Что понимают под ООП. 55. Что означают: инкапсуляция, полиморфизм, наследование? 56. Существует ли тип класс? 57. Для каких целей используются классы? 58. Формат объявления классов. 59. Режимы доступа к элементам класса. 60. Что такое конструкторы и деструкторы. Их назначение. 61. Графический режим в языке Си. 62. Основные компоненты, необходимые для определения графического режима. 63. Процедуры и функции для изображения линий, окружностей, точек. 64. Процедуры и функции для изображения окружностей линий, точек. 65. Процедуры и функции для закраски поверхностей. Вопросы для подготовки к экзамену 1. Алфавит языка Си 2. Существует ли ограничение на множество целых чисел. используемых в языке. 3. Перечислите основные операции, определенные для данных целочисленного типа. 4. Перечислите основные стандартные функции, определенные для данных вещественного типа. 5. Можно ли аргумент стандартной тригонометрической функции задавать в градусах. 6. Из каких символов может состоять идентификатор? 7. Можно ли ключевые слова использовать в качестве имен переменных? 8. Можно ли при записи арифметических выражений на языке Си использовать фигурные скобки? 9. Можно ли при записи арифметических выражений на языке Си использовать квадратные скобки? 10. Можно ли при записи идентификатора использовать русские буквы? 11. Каков приоритет выполнения арифметических операций? 12. Назовите операции отношения, которые применимы к данным целого типа. 13. Какие операции относятся к операциям присваивания? 14. Как записывается в программе восьмеричная константа? 15. Как записывается в программе шестнадцатеричная константа? 16. Как записываются десятичные константы? 17. Из каких частей состоит вещественная константа? 18. Что такое именованная константа? 19. Структура программы в языке Си. 20. Как и где можно записать комментарий в программе? 21. Для каких целей используется указание типа переменных? 22. Какими символами ограничивается текст комментария? 23. Назовите процедуру ввода информации. 24. Назовите процедуру вывода информации. 25. Как записывается список переменных при вводе и выводе? 26. Может ли быть пустым список ввода или вывода? 27. Как осуществляется вывод по формату? 28. Какие обозначения используются в форматах. 29. Какое служебное слово используется для описания данных логического типа? 30. Может ли булево выражение содержать несколько операций? 31. Какой оператор используется для организации ветвления? 32. Приведите пример составного оператора. 33. Переключатель, его организация. 34. Альтернативный переключатель и его организация. 35. Какой вид имеют краткая и полная формы условного оператора и их блок-схемы? 36. Какой оператор является оператором цикла с параметром? 37. Как осуществляется прерывание цикла? 38. Организация цикла с предусловием. 87 39. Организация цикла с постусловием. 40. Понятие внутреннего и внешнего цикла. 41. Что такое массив? И какими свойствами он обладает? 41. Формат описания двумерного и одномерного массивов. 42. В чем заключается инициализация массива? 43. Инициализация многомерных массивов. Особенности инициализации массивов в языке Си. 44. В каком случае можно не указывать размеры массива? 45. Назначение функций в языке Си. 46. Определение функции. Каким образом в программах записывается определение функции и где? 47. Формат определения функции. 48. Структура функции . 49. Что понимают под определением тело функции? 50. Каким образом указывается в функциях спецификация параметров? 51. Прототип функции. Его место расположения в программах. В каких случаях используется прототип функций? 52. Описание прототипа функции. 53. Использование библиотечных функций. 54. Как представляются в программах автоматические переменные? 55. Как представляются в программах внешние переменные? 56. Как представляются в программах статические переменные? 57. Что такое регистровая памяти и ее форма представления в программах. 58. Понятия локальных и глобальных переменных. 59. Ссылочный тип данных. 60. Что такое указатель? Представление указателей в программах на Си. 61. Описание указателя. 62.Операции над указателями. 63. Использование указателей для передачи параметров функции. 64. Как представлены строки в языке Си? 65. Какой символ всегда завершает строку ? 66. Какие основные функции существуют в языке Си для обработки символьных строк? 67. Составить функцию, определяющую тождественность двух строк. 68. Составить функцию слияния двух строк. 69. К какому типу можно отнести структуры? 70. Существует ли тип структура? 71. Объяснить правила использования структур. 72. Как называют элементы структуры? 73. Указать формат описания структурного типа. 74. Как осуществляется обращения к элементам структуры? 75. Что понимают под объединением? 76. Как организована внутренняя память для объединения? 77. Как описываются объединения в программе? 78. Что понимают под вводом-выводом в программировании? 79. При работе с потоками, что понимают под вводом и что понимается под выводом? 80. Что понимается под файлом в языке Си? 81. Что такое поток? 82. Должен ли быть поток связан с каким-либо внешним устройством? 83. Существует ли тип файл в языке Си? 84. Какое представление файлов используется в языке Си? 85. Какие стандартные потоки для ввода-вывода используется в Си? 86. Каким образом организуется работа с файлами на диске? 87. Как осуществляется открытие потока? 88. Указать режимы открытия потока. 89. Запись и чтение символов в поток. 90. Запись и чтение целых чисел. 91. Запись и чтение блоков данных. 92. Что понимают под ООП. 93. Что означают: инкапсуляция, полиморфизм, наследование? 94. Существует ли тип класс? 95. Для каких целей используются классы? 96. Формат объявления классов. 97. Режимы доступа к элементам класса. 98. Что такое конструкторы и деструкторы. Их назначение. 99. Графический режим в языке Си. 100. Основные компоненты, необходимые для определения графического режима. 101. Процедуры и функции для изображения линий, окружностей, точек. 88 102. Процедуры и функции для изображения окружностей линий, точек. 103. Процедуры и функции для закраски поверхностей. Тематика рефератов Список тем рефератов для докладов : 1. Использование манипуляторов. 2. Управление флагами форматирования. 3. Язык Си для создания операционных систем. 12. Программное и мультимедийное сопровождение учебных занятий 1. Borland C++ 2. Turbo C 13. Перечень специализированных аудиторий, кабинетов и лабораторий. Корпус №8 №8 №8 №8 №8 №1 №1 Аудитория 306 307 308 310 311 209 102 Назначение компьютерный класс компьютерный класс компьютерный класс компьютерный класс компьютерный класс Интернет-класс Электронный читальный зал 89