Лекция 2. Базовые конструкции языка С. Типы данных. Ветвления Суперкомпьютерные технологии в математике и математическом образовании М.А.Сокольская Рекомендуемая литература: 2 Дональд Э. Кнут. Искусство программирования. В 3-х томах Роберт У. Себеста. Основные концепции языков программирования Герберт Шилдт. Полный справочник по С++. Четвертое издание. Бъёрн Страуструп. «Язык программирования C++» Джефф Элджер. «C++ For Real Programmers» Хэзфилд Р., Кирби Л. Искусство программирования на C. Фундаментальные алгоритмы, структуры данных и примеры приложений. Энциклопедия программиста. «Большинство хороших программистов делают свою работу не потому, что ожидают оплаты или признания, а потому что получают удовольствие от программирования.» Линус Торвальдс (создатель ядра Linux) 3 Основные конструкции структурного программирования Линейная (функциональный блок). Операторы ввода, вывода и присваивания, следующие строго друг за другом. 1. 4 Основные конструкции структурного программирования Условная или ветвление. Предполагает проверку некоторого условия, в зависимости от которого выполняется то или иное действие 2. 5 Основные конструкции структурного программирования 3. Циклическая. Обеспечивает многократное повторение набора операторов, пока не будет выполнено некоторое условие 6 Доказано, что любая программа может быть построена на основе трех базовых конструкций. 7 Блок-схема алгоритма поиска корней квадратного уравнения 8 С — это причудливый, несовершенный, но невероятно успешный язык. Dennis M. Ritchie. 9 Сотрудник фирмы Bell Labs Денис Ритчи создал язык Си в 1972 году во время совместной работы с Кеном Томпсоном, как инструментальное средство для реализации операционной системы Unix Среда Visual Studio 2008 Для работы мы будем использовать среду программирования, разработанную Microsoft : Microsoft Visual C++ 2008 Express Edition. 10 Где взять? Скачать дистрибутивы с сайта http://www.microsoft.com/ru-ru/default.aspx Версия Express Edition распространяется бесплатно. 11 Создание проекта 12 13 14 15 16 Структура программы 17 Основные разделы 1. Подключение внешних файлов 2. Объявление глобальных переменных, констант и пользовательских типов данных 3. Описание вспомогательных функций или их прототипов. 4. Заголовок функции main (). a) Объявления локальных переменных b) Тело основной программы Замечание: переменные могут быть объявлены в любом месте программы до их использования. Основные библиотеки Ядро языка С включает в себя: типы данных, основной набор операторов и служебные слова языка (например: if, for, while и т.д.). Все остальные функции распределены по внешним библиотекам. Библиотеки содержат функции, сгруппированные по области действия. 18 19 Базовые типы данных в С 20 Модификаторы базовых типов данных К модификаторам базовых типов относятся следующие спецификаторы, предшествующие типам в тексте программы: signed – тип данных со знаком; unsigned – беззнаковый тип long – «длинный» тип данных short – «короткий» тип данных 21 Перед типом данных может комбинация спецификаторов. находиться Тип данных Примерный объем Диапазон значений char unsigned char 8 8 от –127 до 127 от 0 до 255 signed char int unsigned int 8 16 или 32 16 или 32 от –127 до 127 от –32 767 до 32 767 от 0 до 65 535 signed int short int 16 или 32 16 от –32 767 до 32 767 от –32 767 до 32 767 unsigned short int signed short int 16 16 от 0 до 65 535 от –32 767 до 32 767 long int 32 от –2 147 483 647 до 2 147 483 647 22 Тип данных Примерный Диапазон значений объем long long int 64 от –(263–1 ) до (263–1) для С99 signed long int 32 от –2 147 483 647 до 2 147 483 647 unsigned long int 32 от 0 до 4 294 967 295 unsigned long long int 64 от 0 до (264–1) для С99 float 32 от 1Е–37 до 1Е+37 (с точностью не менее 6 значащих десятичных цифр) double 64 от 1Е–37 до 1Е+37 (с точностью не менее 10 значащих десятичных цифр) long double 80 от 1Е–37 до 1Е+37 (с точностью не менее 10 значащих десятичных цифр) 23 !!! Объем зависит от реализации компилятора и фиксирован только для типа char !!! Переменные Переменная – имя ячейки памяти, которую можно использовать для хранения изменяемого значения. Переменные объявляются до своего использования в любом месте программы. Синтаксис: тип список переменных; Например: int i, I, j, k=3; float srednee, SrEdNee, balance; 24 Квалификатор const 25 Использование квалификатора позволяет определить переменную, значение которой нельзя изменить в дальнейшей программе, но можно инициализировать (задать начальное значение). Например: const int f=10; const также можно использовать для запрета изменений параметров, передаваемых в функцию. Оператор присваивания 26 Синтаксис: имя_переменной = выражение; Выражение может состоять из: 1. Отдельной константы 2. Комбинации операторов любой сложности. Оператор может быть использован в любом корректном выражении. Разрешается присваивать одно значение одновременно нескольким переменным: x = y = z = 1; Преобразования типов в операторе присваивания Если в выражении смешаны различные типы чисел и переменных, то компилятор преобразует их в один тип: Все char и short int значения автоматически преобразуются в тип int. Этот процесс называется целочисленным расширением (integral promotion). Все операнды преобразуются в тип самого большого операнда. Этот процесс называется расширением типа (type promotion). 27 Арифметические операторы + * / % -++ 28 вычитание сложение умножение деление (результат зависит от типа) остаток от деления уменьшение на 1 (декрементация) увеличение на 1 (инкрементация) Средства ввода-вывода Вывод данных - printf. Прототип (заголовок) функции printf() имеет вид: int printf(const char *format, ?); 29 Функция printf() записывает в стандартный поток stdout (стандартный выходной поток данных консоль) значения аргументов из заданного списка аргументов в соответствии со строкой форматирования (параметр format). Спецификаторы формата функции printf() %c Символ %d Десятичное целое число со знаком %i Десятичное целое число со знаком %e Экспоненциальное представление числа (в виде мантиссы и порядка, е — на нижнем регистре) %E Экспоненциальное представление числа (в виде мантиссы и порядка, Е — на верхнем регистре) %f Десятичное число с плавающей точкой %F Десятичное число с плавающей точкой (только стандарт С99) %% Выводит знак процента 30 %g Использует более короткий из форматов %e или %f %G Использует более короткий из форматов %E или %F %o Восьмеричное число без знака %s Символьная строка %x Шестнадцатеричное без знака (строчные буквы) %X Шестнадцатеричное без знака (прописные буквы) %p Выводит указатель %n Соответствующий аргумент должен быть указателем на целое число. 31 Функции ввода-вывода – getchar() Прототип функции getchar() имеет следующий вид: int getchar(void); Функция getchar() возвращает из стандартного потока stdin (входного потока данных - консоли) следующий символ. Можно использовать для организации задержки экрана. 32 Функции ввода – scanf() Прототип функции scanf() имеет следующий вид: int scanf(const char *format, ?); 33 Функция scanf() представляет собой функцию для ввода данных общего назначения, которая читает поток stdin и сохраняет информацию в переменных, перечисленных в списке аргументов. Все переменные должны передаваться посредством своих адресов, например, с помощью символа &. Управляющая строка, задаваемая параметром format, состоит из символов трех категорий: спецификаторов формата, пробелов, символов, отличных от пробелов. Спецификация формата начинается знаком % и сообщает функции scanf() тип значения, которое будет прочитано. 34 Пример 1. 35 #include <stdio.h> #include <conio.h> int main (void) { // Объявления char ch, str[79+1]; // С учетом одного места для символа '\0' int x, y, z; float a, b, c; double A, B, C; // Выполнение программы printf("\n\t Enter a symbol: "); ch = getchar(); 36 printf("\t The symbol is: %c\n", ch); _flushall();//найти смысл функции самостоятельно printf("\n\t Enter a string: "); gets_s(str, 79); printf("\t The string is: %s\n", str); a = 2.42F; b = 3.58F; c = a + b; printf("\n\t The sum %1.2f and %1.2f (as float) is equal: %1.4f\n", a, b, c); A = 12.1234567796602; B = 2.7182818284509; C = A + B; printf("\n\t The sum %1.13f and %1.13f \n\t is equal (as double): %1.13f\n", A, B,C); x = 2; y = 7; z = x*y; printf("\n\t Multiplication %d on %i (as an integer) is equal: %d\n", x, y, z); printf("\n\n Press any key: "); _getch(); return 0; } 37 Оператор return 38 Используется для возврата управления из функции в точку её вызова. Если после оператора return стоит некоторое значение, то оно становится результатом работы функции. return 4; // результат работы функции – 4 return f; // результат работы функции равен значению f return sin(k)+10; /* результат работы функции равен значению выражения*/ Внутри функции можно использовать несколько операторов return, но при достижении первого из них работа функции завершается. Условные операторы языка С 39 В языке программирования С используются несколько конструкций для принятия решений: • оператор if; • оператор switch; • условный оператор ? (оператор условия) Для прерывания программного цикла при некотором условии применяется утверждение (оператор) break, для продолжения итераций цикла при выполнении некоторых условий применяется утверждение (оператор) continue, для перехода к заданному месту программы применяется оператор goto Логические операторы и операторы сравнения 40 В основе операторов лежат понятия «истина» и «ложь». Ложным в С считается значение, равное нулю, все остальные значения – истинные. Соответственно, выражения содержащие логические операторы возвращают 0, если результат ложен и 1, если истинен. Операторы сравнения и логические операторы имеют более низкий приоритет, чем арифметические. Т.е. в выражении без скобок сначала выполняются арифметические вычисления, а потом сравнения. 41 Оператор Действие > Больше >= Больше или равно < Меньше <= Меньше или равно == Равно != Не равно && И || ИЛИ ! НЕ Оператор if-else Общая форма записи конструкции if–else: if (expression) program1 statement1; else program2 statement2; Если выполняется условие expression, то будет выполняться фрагмент программы program1 statement1, в противном случае будет выполняться program2 statement2. 42 Оператор if-else 43 Каждая из «веток» оператора может содержать несколько функций (операторов, выражений). В таком случае применяются фигурные скобки: if (expression) { program1 statement1; program2 statement2; ... } else { program3 statement3; program4 statement4; ... } Пример 2. Решение квадратного уравнения #include <stdio.h> #include <conio.h> #include <math.h> 44 int main(void) { float a, b, c; float D, x1, x2, x; printf("\n\t Equation a*x^2 + b*x + c = 0\n"); printf("\n\t Enter the coefficient a: "); scanf("%f”, &a); printf("\t Enter the coefficient b: "); scanf_s("%f", &b); printf("\t Enter the coefficient c: "); scanf_s("%f", &c); 45 D = b*b - 4*a*c; if (D >= 0 && a != 0) { x1 = -b/(2*a) + (float)sqrt(D)/(2*a); x2 = -b/(2*a) - (float)sqrt(D)/(2*a); printf("\n\t The roots of the equation: \n\t x1 = %1.4f, x2 = %1.4f\n", x1, x2); }; if (D < 0) printf("\n\t The roots complex\n"); 46 if (a == 0 && b != 0) { x = -c/b; printf("\n\t As a = %1.0f,\n\t the solution of the equation is: %1.4f\n", a, x); }; printf("\n Press any key: "); _getch(); return 0; } Условный оператор ? Cпецифический оператор условия является тернарным оператором. Это означает, что у него может быть три операнда. Общий формат записи оператора условия: условие ? выражение_1 : выражение_2 47 Если в результате вычисления условия будет получено значение TRUE (истина, не нуль), то выполняется выражение_1. Если в результате вычисления условия будет получено значение FALSE (ложь, т.е. нуль), то выполняется выражение_2. Пример 3.Наибольшее из двух чисел #include <stdio.h> #include <conio.h> #include <stdlib.h> // Для функций случайных чисел #include <time.h> 48 int main (void) { int a, b, maxab; unsigned int some; srand((unsigned) time(NULL)); a = rand(); b = rand(); printf("\n\t Random numbers: a = %d; b = %d\n", a, b); /*Оператор условия для определения максимального числа */ maxab = (a > b) ? a : b; printf("\n\t Maximum number: %d\n", maxab); printf("\n Press any key: "); _getch(); return 0; 49 } Оператор switch Оператор многовариантного ветвления или множественного выбора. Оператор последовательно сравнивает значение выражения со списком целых чисел или символов. Если обнаружено совпадение, то выполняется соответствующий оператор или группа операторов. 50 Оператор switch. Общая форма записи 51 switch (expression) { case value1: program statement; break; case value2: program statement; break; ... case valueN: program statement; break; default: program statement; break; } Выражение заключенного в круглые скобки оператора последовательно сравнивается со значениями value1, value2,..., valueN. В том случае, когда одно из этих значений равно значению выражения, выполняются утверждения, которые следуют за данным значением. break сигнализирует об окончании выполнения утверждений и приводит к выходу из оператора switch. break ставится в конце каждого варианта выбора. 52 Специальный дополнительный вариант default будет выполнен в том случае, когда не будет найдено ни одного совпадения. Пример 4. Расчет арифметического выражения 53 #include <stdio.h> #include <conio.h> int main (void) { float value1, value2; char operat; printf ( "\n\t Printed on the keyboard expression: "); scanf ( “%f%c%f", &value1, &operat, &value2); switch (operat) { case '+': printf ( "\n\t Result: %1.4f\n", value1 + value2); break; 54 case '-': printf("\n\t Result: %1.4f\n", value1 - value2); break; case '*': printf( "\n\t Result: %1.4f\n", value1 * value2); break; case '/': if (value2 == 0.0) printf("\n\t Division by zero. \n"); else printf("\n\t Result: %1.4f \n", value1 / value2); break; 55 default: printf("\n\t Unknown arithmetic operator\n\t error or enter a number. Break!\n"); break; } // End switch printf("\n Press any key: "); _getch(); return 0; } В программе использована полная форма оператора switch. Оператор break инициирует немедленный выход из оператора switch. Возможно использование вложенных операторов switch. Свойства оператора switch 1. 2. 3. 56 Значение его выражения можно сравнивать только с константами, т.е. нельзя использовать выражения в части case. Две константы в разных разделах case не могут иметь одинаковое значение, за исключением случая, когда один оператор switch вложен в другой. Если в операторе switch используются символьные константы, то они автоматически преобразуются в целочисленные Пример 5. Создание текстового меню void main () { char ch; printf(“1. Ввод данных/n”); printf(“2. Расчёт/n”); printf(“3. Вывод результата/n”); printf(“4. Выход/n”); printf (“Выберите пункт меню”); ch=getchar();//считываем символ с клавиатуры 57 58 switch (ch) { case ‘1’: inp(); //вызов функции ввода данных break; case ‘2’: calc(); //вызов функции расчета break; case ‘3’: outp(); //вызов функции вывода данных break; case ‘4’: return; default: printf(“Не выбран ни один пункт.”); } } Итоги Мы рассмотрели • Основные алгоритмические конструкции • Базовые операторы ввода-вывода • Типы данных и библиотеки • Способы организации ветвлений 59