Лабораторная работа №1. Тема: Основні оператори: присвоєння, розгалуження, множинний вибір, цикл. Типи циклів та принципи їх застосування. Цель: Изучить структуру простейшей С-программы. Освоить программирование ввода-вывода с помощью стандартных библиотек. Приобрести навыки программирования вычислений. Литература: П. Франка С++: Учебный курс.– СПб: Питер Ком, 1999. И. М. Двоеглазов Язык программирования С++. Справочное руководство. – Киев, 1993. Теоретические сведения. Структура программы Программа на C++ обычно состоит из большого числа исходных файлов, каждый из которых содержит описания типов, функций, переменных и констант. Чтобы имя можно было использовать в разных исходных файлах для ссылки на один и тот же объект, оно должно быть описано как внешнее. Например: extern double sqrt(double); extern instream cin; Самый обычный способ обеспечить согласованность исходных файлов – это поместить такие описания в отдельные файлы, называемые заголовочными (или header) файлами, а затем включить, то есть скопировать, эти заголовочные файлы во все файлы, где нужны эти описания. Например, если описание sqrt хранится в заголовочном файле для стандартных математических функций math.h, и вы хотите извлечь квадратный корень из 4, можно написать: #include "math.h" //... x = sqrt(4); Поскольку обычные заголовочные файлы включаются во многие исходные файлы, они не содержат описаний, которые не должны повторяться. Например, тела функций даются только для inline-подставляемых функций и инициализаторы даются только для констант. За исключением этих случаев, заголовочный файл является хранилищем информации о типах. Он обеспечивает интерфейс между отдельно компилируемыми частями программы. В команде включения include имя файла, заключенное в угловые скобки, например, относится к файлу с этим именем в стандартном каталоге (часто это /usr/include/CC); на файлы, находящиеся в каких-либо других местах ссылаются с помощью имен, заключенных в двойные кавычки. Например: #include "math1.h" #include "/usr/bs/math2.h" включит math1.h из текущего пользовательского каталога, а math2.h из каталога /usr/bs. Здесь приводится очень маленький законченный пример программы, в котором строка определяется в одном файле, а ее печать производится в другом. Файл header.h определяет необходимые типы: // header.h extern char* prog_name; extern void f(); В файле main.c находится главная программа: // main.c #include "header.h" char* prog_name = "программирование"; main() { f(); } а файл f.c печатает строку: // f.c #include #include "header.h" void f() { cout << prog_name << "\n"; } main() { ... } определяет функцию, названную main. Каждая программа должна содержать функцию с именем main, и работа программы начинается с выполнения этой функции. Вывод Функция printf предназначена для вывода информации на экран, формат ее прост и гибок: printf(<форматная строка>,<аргумент>,<аргумент>,…); Форматная строка – это строка, которая начинается и заканчивается двойными кавычками (“вот так”). Целью функции printf является вывод этой строки на экран. До вывода аргументы, указанные в строке, преобразуются в соответствии со спецификаторами формата, указанными в самой строке. Все спецификаторы формата начинаются со знака % (процента), за которым обычно следует одна буква, указывающая тип данных и способ форматирования этих данных. Для каждого спецификатора формата должен быть указан один и только один аргумент. Если аргумент принадлежит типу данных, который не соответствует указанному в спецификаторе формата, то С попытается проделать соответствующее преобразование. Аргументами могут быть переменные, константы, выражения, вызовы функций. Спецификатор %d означает, что аргумент является целым. Ниже приведены наиболее часто используемые спецификаторы форматов: %u беззнаковое целое; %p значение указателя; %f с плавающей точкой; %e с плавающей точкой в экспоненциальном формате; %c символ; %s строка; %x или %X целое в шестнадцатеричном формате. Ширина поля может быть указана цифрой, помещенной между знаком % и буквой. Например, десятичное поле шириной 4 символа будет указано так: %4d. Значение будет напечатано выровненным вправо (с ведущими нулями), так что общая длина поля будет равна 4 символам. В форматной строке указываются также управляющие символы: \n – символ перехода на новую строку; \f – перевод формата или очистка экрана; \t – табуляция; \b – забой; \xhhh – вставить символ с шестнадцатеричным кодом hhh, где hhh – от одной до трех шестнадцатеричных цифр. Для вывода знака процента вставьте %%; для вывода обратной косой черты напечатайте две косых черты \\. Например: printf( “сумма %d \n”,sum); Другие функции вывода: puts и putchar Функция puts выводит на экран строку, оканчивающуюся символом перехода на новую строку. Например: puts(“Я изучаю С++”); Внимание: Символ \n в конце строки отсутствует, т. к. он добавляется самой функцией puts. Вторая функция, putchar, выводит на экран один символ и не добавляет \n. Оператор putchar(ch) эквивалентен printf(“%c”,ch), использование этих функций сделает вашу программу меньше и быстрее. Замечание: Функции printf( ), puts(), putchar() описаны в заголовочном файле stdio.h, а функция putch () – в заголовочном файле conio.h. Ввод В языке Си имеется несколько функций, обеспечивающих ввод информации, некоторые из них принимают входную информацию из файла, или из входного потока, другие – с клавиатуры. Функция scanf Основное назначение этой функции – интерактивный ввод информации. Вид функции scanf эквивалентен виду функции printf: scanf(<форматная строка>, <адрес>, <адрес>, …) Функция scanf использует многие из тех спецификаторов формата со знаком %, что и функция printf: %d для целых чисел, %f для чисел с плавающей точкой, %s для строк и т. д. Однако, у этой функции есть важная отличительная черта: за форматной строкой следуют не значения, а адреса. Например: scanf(“%d %d”,&a,&b); эта строка означает, что программа ожидает ввода двух десятичных целых значений, разделенных пробелом: первое значение будет присвоено переменной a, а второе – переменной b. Обратите внимание на то, что для передачи значений применяется адресный оператор &, при помощи которого функции scanf передаются адреса переменных a и b. Чтобы передавать в программу значения, разделяя их запятой, изменим строку таким образом: scanf(“%d,%d”,&a,&b); Использование для ввода функций gets и getch Функция gets воспринимает любую информацию до тех пор, пока вы не нажмете клавишу Enter. Код, соответствующий этой клавише, в строку не вводится, но в конце строки добавляется нулевой символ \0. Функция getch считывает с клавиатуры один символ, не отображая его на экране. Эта функция не передает символ в качестве параметра; она сама имеет тип char, и ее значение может быть непосредственно присвоено переменной типа char. Замечание: Функция scanf () описана в заголовочном файле stdio.h, а функция getch () – в заголовочном файле conio.h. Потоки ввода/ вывода в С++ Управлять вводом/ выводом в С++ можно двумя способами: с помощью функций и с помощью объектов. Объекты ввода/ вывода были специально разработаны в С++, и работать с ними гораздо проще и эффективнее, чем с функциями. Для вывода данных программа направляет данные в поток. Все данные, предназначенные для вывода, передаются в специальный объект (cout), который и отображает их на экране. Аналогично можно вызвать другой объект (cin), который будет собирать данные, набираемые на клавиатуре. Затем данные извлекаются из этого объекта и передаются переменным программы. Синтаксис потокового вывода строится из объекта cout, оператора << и переменной (или константы): cout <<идентификатор_переменной; Пример1: вывод на экран значения целой переменной number cout<<number; Если выводятся значения нескольких переменных, то перед каждой из них должен стоять свой оператор вывода (<<). Пример2: вывод на экран строки и значения целой переменной number cout<<”The result is: ”<<number; Пример3: вывод на экран строки и значения целой переменной number и переход на новую строку с помощью управляющего символа \n: cout<<”The result is: ”<<number<<”\n”; переход на новую строку с помощью манипулятора endl: cout<<”The result is: ”<<number<<endl; Синтаксис потокового ввода строится из объекта cin, оператора >> и переменной, которой присваивается вводимое значение: cin >>имя_переменной; Пример4: ввод значения целой переменной number cin>>number; С помощью одной инструкции ввода можно присвоить значения более чем одной переменной, например: cin>>number>>i>>j; Примечание Имена cin и cout произошли от слов C input (ввод С) и C output(вывод С). Чтобы использовать потоковый ввод и вывод, в программу необходимо включить заголовочный файл iostream.h. Это делается следующим образом: # include <iostream.h> Именно с помощью угловых скобок в программу включаются файлы из каталогов компилятора. В заголовочном файле iostream.h находятся объявления и определения классов для объектов cin и cout. Потоковый ввод/ вывод обрабатывает все встроенные типы данных С++. Непосредственно могут использоваться следующие типы данных: int char float double Сводка операций С++ Приоритет операций убывает с увеличением номера категории. Все операции одной категории имеют одинаковый приоритет. № Категория Операция Название или действие
Наивысшего приоритета ( ) [ ] -> :: . Вызов функции Индексирование Косвенное обращение к члену класса Спецификации доступа Прямое обращение к члену класса
Унарные ! ` + - ++ -- & * sizeof new delete Логическое отрицание Дополнение до единицы Унарный плюс Унарный минус Преинкремент или постинкремент Предекремент или постдекремент Адрес Обращение Размер Создание динамического объекта Удаление динамического объекта
Мультипликативные * / % Умножение Деление Деление по модулю
Косвенного обращения через указатель на член класса .* ->* Прямое косвенное обращение через указатель Косвенное косвенное обращение через указатель
Аддитивные + - Бинарный плюс Бинарный минус
Сдвига << >> Сдвиг влево Сдвиг вправо
Отношения < <= > >= Меньше Меньше или равно Больше Больше или равно
Равенства = = != Равно Не равно
& Побитовое И
^ Побитовое исключающее ИЛИ
| Побитовое включающее ИЛИ
&& Логическое И
|| Логическое ИЛИ
?: Условная
Присваивания = *= /= %= += -= &= ^= |= <<= >>= Простое присваивание Присваивание с умножением Присваивание с делением Присваивание с делением по модулю Присваивание с суммой Присваивание с разностью Присваивание с побитовым И Присваивание с побитовым исключающим ИЛИ Присваивание с побитовым включающим ИЛИ Присваивание с левым сдвигом Присваивание с правым сдвигом
Запятая , Последовательное выполнение
Блоки Блок - это возможно пустой список операторов, заключенный в фигурные скобки: { a=b+2; b++; } Блок позволяет рассматривать несколько операторов как один. Область видимости имени, описанного в блоке, простирается до конца блока. Имя можно сделать невидимым с помощью описаний такого же имени во внутренних блоках. Операторы if Условный оператор имеет вид if (выражение) оператор [else оператор] Выражение может иметь следующие типы: целое, указатель или класс, для которого определено преобразование в целый тип или в указатель. Вычисляется выражение, и если оно не ноль, то выполняется первый подоператор. Если используется else, то второй подоператор выполняется, если выражение есть ноль. Неоднозначность else разрешается посредством того, что else связывается с последним встреченным if, не имеющим else. Пример: if (x>1) if (y<=4) z=1; else z=2; Часть else относится ко второму if. Программа в следующем примере осуществляет преобразование дюймов в сантиметры и сантиметров в дюймы; предполагается, что вы укажете единицы измерения вводимых данных, добавляя i для дюймов и c для сантиметров: #include main() { const float fac = 2.54; float x, in, cm; char ch = 0; cout << "введите длину: "; cin >> x >> ch; if (ch == 'i') { // inch - дюймы in = x; cm = x*fac; } else if (ch == 'c') // cm - сантиметры in = x/fac; cm = x; } else in = cm = 0; cout << in << " in = " << cm << " cm\n"; } Заметьте, что условие в операторе if должно быть заключено в круглые скобки. Операторы switch Оператор switch производит сопоставление значения с множеством констант. Проверки в предыдущем примере можно записать так: switch (ch) { case 'i': in = x; cm = x*fac; break; case 'c': in = x/fac; cm = x; break; default: in = cm = 0; break; } Операторы break применяются для выхода из оператора switch. Константы в вариантах case должны быть различными, и если проверяемое значение не совпадает ни с одной из констант, выбирается вариант default. Программисту не обязательно предусматривать default. Оператор while Оператор while имеет вид: while (выражение) оператор Выполнение оператора повторяется, пока значение выражения остается ненулевым. Проверка производится перед каждым выполнением оператора. Выражение обрабатывается как в условном операторе. Рассмотрим копирование строки, когда заданы указатель p на ее первый символ и указатель q на целевую строку. По соглашению строка оканчивается символом с целым значением 0. while (p != 0) { *q = *p; // скопировать символ q = q+1; p = p+1; } *q = 0; // завершающий символ 0 скопирован не был Следующее после while условие должно быть заключено в круглые скобки. Условие вычисляется, и если его значение не ноль, выполняется непосредственно следующий за ним оператор. Это повторяется до тех пор, пока вычисление условия не даст ноль. Этот пример слишком пространен. Можно использовать операцию ++ для непосредственного указания увеличения, и проверка упростится: while (*p) *q++ = *p++; *q = 0; где конструкция *p++ означает: "взять символ, на который указывает p, затем увеличить p." Пример можно еще упростить, так как указатель p разыменовывается дважды за каждый цикл. Копирование символа можно делать тогда же, когда производится проверка условия: while (*q++ = *p++) ; Здесь берется символ, на который указывает p, p увеличивается, этот символ копируется туда, куда указывает q, и q увеличивается. Если символ ненулевой, цикл повторяется. Поскольку вся работа выполняется в условии, не требуется ни одного оператора. Чтобы указать на это, используется пустой оператор. Оператор do-while Оператор do-while имеет вид do оператор while (выражение); Выполнение оператора повторяется до тех пор, пока значение остается не нулем. Проверка выполняется после каждого выполнения оператора. Выражение обрабатывается так же, как в условном операторе. Пример: x=1; do cout<<”x=”<<x<<”\n”; while (++x<10); Содержание и требования к оформлению протокола работы Протокол работы должен содержать: краткий конспект теоретических сведений; файлы с исходными текстами программ и файлы с расширениями .exe(в соответствующих каталогах). Ход работы. Задача 1. Напишите программу, которая считывает символ и выводит соответствующий код. (Используйте различные способы ввода и вывода). Задача 2. Напишите программу, которая по введенным координатам двух точек на плоскости выводит уравнение прямой в виде ax+by+c=0. Задача 3. Дано действительное число x. Не пользуясь никакими другими арифметическими операциями, кроме умножения, сложения и вычитания, вычислить 2x4-3x3+4x2-5x+6. Разрешается использовать не более 4 умножений и 4 сложений и вычитаний. (Можно использовать только заголовочный файл iostream.h). Задача 4. Даны действительные числа x, y. Не пользуясь никакими другими арифметическими операциями, кроме умножения, сложения и вычитания, вычислить 3x2y2-2xy2-7x2y-4y2+15xy+2x2-3x+10y+6. Разрешается использовать не более 8 умножений и 8 сложений и вычитаний. (Можно использовать только заголовочный файл stdio.h). Задача 5. Дано действительное число x. Не пользуясь никакими другими арифметическими операциями, кроме умножения, сложения и вычитания, вычислить 1-2x+3x2-4x3 и 1+2x+3x2+4x3. Разрешается использовать не более 8 операций. Задача 6. Даны действительные положительные числа x, y, z. а) Выяснить, существует ли треугольник с длинами сторон x, y, z. б) Если треугольник существует, то ответить – является ли он остроугольным. Задача 7. Даны действительные числа a, b, c, d, s, t, u (s и t одновременно не равны нулю). Известно, что точки (a,b) и (c,d) не лежат на прямой l, заданной уранением sx+ty+u=0. Прямая l разбивает координатную плоскость на две полуплоскости. Выяснить, верно ли, что точки (a,b) и (c,d) принадлежат разным полуплоскостям. Задача 8. Даны действительные числа a, b, c, d, e, f, g, h. Известно, что точки (a,b) и (c,d) не лежат на прямой l, проходящей через точки (e,f) и (g,h). Прямая l разбивает координатную плоскость на две полуплоскости. Выяснить, верно ли, что точки (a,b) и (c,d) принадлежат одной и той же полуплоскости. Задача 9. Даны действительные числа x1, x2, x3, y1, y2, y3. Принадлежит ли начало координат треугольнику с вершинами (x1, y1), (x2, y2), (x3, y3)? Задача 10. Дано натуральное число (меньше 100), определяющее возраст человека в годах. Дать для этого числа наименования “год”, “года” или “лет”: например, 1 год, 23 года, 45 лет. Задача 11. Реализовать метод хорд для решения уравнения с заданной точностью. Реализовать метод касательных для решения уравнения. Реализовать метод хорд и касательных. Реализовать метод Симпсона численного интегрирования функции F(x) на отрезке [a, b] с заданной точностью Epsilon.