- •Часть 1
- •1. Основы программирования на языке Си
- •1.1. Структура программы на языке Си.
- •1.2. Структура простейшей одномодульной программы
- •1.2.1. Комментарии в программе на языке Си
- •1.2.2. Начальные сведения о препроцессоре
- •1.2.3. Определение функции main().
- •1.2.4. Пример простейшей программы
- •1.3. Алфавит, синтаксис и семантика
- •1.4. Алфавит языка Си
- •1.5. Понятие о типе
- •1.6. Система типов языка Си
- •1.7. Понятие об объекте
- •1.8. Лексемы
- •1.9. Зарезервированные слова
- •1.10. Идентификаторы
- •1.11. Литералы
- •1.11.1. Целочисленные литералы
- •1.11.2. Литерал вещественного типа
- •1.11.3. Символьные литералы
- •1.11.4. Строковый литерал
- •1.12. Переменные
- •1.13. Символические константы в языке Си
- •1.14. Операторы, выражения и инструкции. Общие сведения.
- •1.14.1. Классификация операторов
- •1.14.2. Приоритет и ассоциативность операторов.
- •1.14.3. Побочные эффекты при вычислении выражений
- •1.14.4. Порядок вычисления выражений
- •1.15. Арифметические операторы и выражения
- •1.15.1. Унарные операторы
- •1.15.2. Бинарные операторы
- •1.15.3. Преобразования типа при выполнении бинарных операторов
- •1.15.3.1. Автоматическое преобразование типов
- •1.15.3.2. Явное преобразование типа
- •1.15.4. Математические функции
- •1.16. Оператор присваивания и инструкция присваивания
- •1.16.1. Простой оператор присваивания
- •1.16.2.Множественное присваивание
- •1.16.3. Составной оператор присваивания
- •1.16.4. Преобразование типа при присваивании
- •1.17. Начальные сведения об указателях. Выходные параметры функции
- •1.18. Принятие решений и логические величины. Операторы отношения и сравнения на равенство
- •1.18.1. Логические операторы
- •1.18.2. Поразрядные операторы
- •1.19. Условные выражения (оператор ?:)
- •1.20. Оператор запятая
- •1.21. Оператор sizeof
- •1.22.4. Инструкция return
- •1.23. Составная инструкция
- •1.24. Инструкция if else
- •1.24.1. Полная и сокращенная формы инструкции if
- •1.24.2. Вложенные инструкции if
- •1.25. Инструкция switch
- •1.25.1. Синтаксис инструкции switch
- •1.25.2. Использование инструкции switch
- •1.26. Функциональные компоненты цикла
- •1.27. Арифметические и итерационные циклы
- •1.27.1. Задачи, приводящие к арифметическим циклам
- •1.27.2. Задачи, приводящие к итерационным циклам
- •1.28. Циклические управляющие инструкции
- •1.29. Цикл, управляемый инструкцией for
- •2. Примеры решенных задач
- •2.1. Линейные вычислительные процессы
- •2.2. Организация разветвлений
- •2.2.1. Простейшие разветвления
- •2.2.2. Многовариантные разветвления
- •2.2.2.1. Использование переключателя switch
- •2.2.2.2. Использование вложенных инструкций if else if
- •2.2.2.3. Использование вложенных инструкций if ... If
- •2.2.2.4. Использование сокращённых форм инструкции if
- •2.2.3. Рекомендации по программированию
- •2.3. Организация циклов
- •2.3.1. Простые циклы
- •2.3.2. Циклы и разветвления
- •2.3.2.1. Разветвление до цикла
- •2.3.2.2. Разветвление внутри цикла
- •2.3.2.3. Разветвление после цикла
- •2.3.2.4. Циклы в ветвях разветвлений.
- •2.3.3. Рекомендации по программированию
- •Содержание
- •1. Основы программирования на языке Си
- •Литература
2.2.2. Многовариантные разветвления
Будем считать, что набор возможных действий при организации многовариантных разветвлений содержит более двух действий.
Организация многовариантных разветвлений в языке Си может выполняться с помощью следующих средств:
● переключателя switch,
● нескольких инструкций if.
Наиболее удобным средством организации сложных разветвлений является использование инструкции switch. К сожалению, возможности этой инструкции в языке Си ограничены. Одним из наиболее перспективных способов организации сложных разветвлений в тех случаях, когда применение переключателя switch невозможно, является моделирование работы переключателя с помощью вложенных инструкций if.
Вначале рассмотрим пример, в котором для организации сложного разветвления используется переключатель switch. При этом представляет интерес исследовать особенности переключателя switch, которые обеспечивают удобство его использования. Затем будут рассмотрены возможные варианты моделирования этой инструкции с помощью вложенных инструкций if.
2.2.2.1. Использование переключателя switch
Постановка задачи.
Написать простейший калькулятор для выполнения четырёх арифметических действий.
Решение.
Определим состав входных и выходных данных для разрабатываемой программы. К ним, очевидно, можно отнести два операнда выполняемой операции, а также её оператор (знак операции). Для повышения общности решения будем считать операнды вещественными числами, выбрав для их представления в программе тип double. В связи с тем, что на клавиатуре имеются клавиши, соответствующие обычным знакам арифметических действий (+ , – , / , *), в качестве типа для представления оператора выберем тип char. Для повышения читабельности программы выберем для переменных, предназначенных для представления исходных данных, следующие имена: first и second – для операндов и operator – для оператора. Для результата вычислений будем использовать переменную result типа double.
Следует отметить, что при вводе исходных данных пользователем программы могут быть допущены ошибки. Такие ошибки при работе с калькулятором может иметь место, как при вводе чисел, так и при вводе оператора выполняемой операции. Ограничимся обработкой ситуации, связанной с вводом неправильного оператора. Потребуем, чтобы в этом случае программа перед своим завершением выводила для пользователя соответствующее сообщение.
Определим набор действий, из которого следует сделать выбор:
result = first + second; result = first – second; result = first * second; result = first / second; printf(“неправильный знак операции \n”);
Для выбора требуемого действия целесообразно использовать переключатель switch, в котором в качестве селектора использовать переменную operator. Переключатель switch должен содержать пять ветвей. Четыре ветви должны соответствовать штатным ситуациям, а последняя, выводящая сообщение о неправильном вводе оператора, соответствует нештатной ситуации. Вначале должны следовать ветви для штатных ситуаций. Последней должна быть записана с меткой default ветвь, соответствующая нештатной ситуации. Каждая штатная ветвь должна заканчиваться инструкцией break. Это необходимо для предотвращения “провала” в следующую ветвь. Нештатная ветвь должна заканчиваться инструкцией return. Это позволит завершить выполнение программы после вывода сообщения об ошибке ввода. Учитывая всё сказанное, получим следующий текст программы.
#include<stdio.h> #include<conio.h> int main(void) { double first, second, result; char operator; printf(“Введите значение первого операнда =”); scanf(“%lf”, &first); printf(“Введите значение второго операнда =”); scanf(“%lf%*c”, &second); printf(“Требуемая операция =”); scanf(“%c”, &operator) ; switch(operator) { case ‘+’ : result = first + second; break; case ‘-’ : result = first - second; break; case ‘*’ : result = first * second; break; case ‘/’ : result = first / second; break ; default : printf(“Некорректная операция \n”); return 1; } printf(“Результат выполнения операции = %0.4g\n”, result); getch(); return 0; }
Отметим одну особенность, которую следует учитывать при совместном вводе чисел и данных символьного типа. После ввода числа в буфере клавиатуры остаётся символ новой строки (\n). Этот символ может быть прочитан последующим вызовом функции scanf() в том случае, когда этот вызов используется для ввода переменной типа char. Для удаления этого символа из буфера клавиатуры во втором вызове функции scanf() введена дополнительная спецификация типа %c, предназначенная для чтения данных символьного типа. Символ *, расположенный между символами % и c, является указанием для компилятора, что прочитанный символ не надо записывать в память.
Остановимся на особенностях переключателя switch, которые обеспечивают удобство его использования:
▪ каждое из выбираемых действий в исходном тексте встречается только один раз,
▪ каждое из выбираемых действий выполняется только один раз,
▪ после выполнения выбранного действия работа переключателя switch прекращается,
▪ выбранное действие располагается рядом с условием, определяющим его выбор,
▪ порядок следования ветвей, соответствующих штатным ситуациям не влияет на корректность разветвления.
Особенность рассмотренной задачи состоит в том, что при её программировании удаётся легко найти селектор, необходимый для построения переключателя switch. Возникает вопрос, как быть в тех случаях, когда такой селектор не удается найти. Частичным ответом на этот вопрос является построение конструкций, позволяющих реализовать перечисленные выше свойства переключателя switch, например, с помощью вложенных инструкций if.
