Поможем написать учебную работу
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
|
Лабораторная работа " Ввод и вывод символов" |
3/3 |
ЛАБОРАТОРНАЯ РАБОТА
Тема: Переключатели. Использование символьных строк
Цель работы: Освоить приемы использования оператора switch в различных ситуациях. Научиться работать со строковыми литералами и их массивами.
Оператор switch для ветвления по многим направлениям
Типичной для подавляющего большинства алгоритмов программ является ситуация, когда необходимо выбрать один из нескольких возможных путей продолжения вычислений (ветвление вычислительного процесса). Выбор основывается на проверке выполнения или невыполнения некоторого условия (или условий).
Традиционно в языках программирования для ветвления применяется условный оператор if, при выполнении которого выбор той или иной ветви основан на логическом значении специального выражения.
Так как таких значения может быть только два, то условный оператор (в полной форме if-else) позволяет направить вычисления по одной из двух ветвей:
if(лог.выр.) одна_ветвь;
else другая_ветвь;
Каждая ветвь вычислений это оператор, часто составной, который в Си ограничен фигурными (операторными) скобками.
if(лог.выр.) {операторы} else {операторы};
С помощью вложенных операторов if можно моделировать ветвление по нескольким направлениям:
if(условие1) {операторы1}
else{ if(условие2){операторы2}; else ... }
Однако, если ветвей несколько, и каждая объемна, то код программы становится трудно обозримым без комментариев сложно определить, где начинается и заканчивается каждая ветвь. Чтобы сделать код более очевидным, в языке Си предлагается использовать оператор switch (переключатель), имеющий следующую конструкцию:
switch(expr){
case конст-выр1: операторы1;
...
case конст-вырn: операторыn;
default: операторыn;
}
Выбор ветви основывается на значении выражения expr, которое должно быть одного из следующих целых типов: int, unsigned, char, unsigned или unsigned char.
Каждая ветвь начинается с уникальной метки, состоящей из служебного слова case и целого числа.
"Правая" граница ветви задается одним из операторов передачи управления:
break закончить работу оператора switch, и перейти к следующему за ним оператору программы,
goto закончить работу оператора switch и перейти к оператору, помеченному указанной в goto меткой,
return закончить не только работу оператора switch, но и выйти из функции, в которой он выполнялся.
Если такого оператора в конце ветви нет, то вычисления будут продолжены по следующей ветви (т.е. для очередного case), что часто является ошибкой.
Однако такое поведение оказывается полезным в тех случаях, когда для нескольких значений case нужно выполнить одни и те же действия, так как можно не дублировать несколько раз один и тот же код. Так, можно написать
case 1: case 2: case 3: операторы; break;.
Метка default обозначает ветвь, которую нужно выполнить, если для вычисленного выражения expr не нашлось подходящего case. Эта часть оператора switch является необязательной. Но, если она используется, то может быть только одна.
Хотя это необязательно, метку default обычно записывают поcле всех меток case.
Массивы строк
В тех случаях, когда необходимо работать с массивом символьных строк (литералов) имеется две основные возможности.
Во-первых, можно создать двумерный массив типа char, каждая строка которого будет хранить один литерал.
Так как каждая символьная строка в Си содержит нуль-терминатор, то в определении двумерного массива размер его строки должен быть указан, как минимум, на единицу больше длины самой большой символьной строки. Массив можно инициализировать строками:
char mas_str[][11]={"один","восемь", "пятнадцать"};
Так как двумерный массив это массив массивов, то mas_str[i] будет определять указатель на i-ую строку двумерного массива.
Второй способ использование массива указателей на char, который определяется следующим образом:
char *pmas[]={"один","восемь", "пятнадцать"};
ЗАДАНИЕ
Даны два массива. В одном содержатся фамилии студентов (Ivanov, Petrov, Sidorov, Kusnetsov), во втором их оценки на одном из экзаменов (2, 3, 4 или 5).
Задача: вывести результаты экзамена в табличном виде, т.е. в каждой строке выводится фамилия и оценка, преобразованная в текстовое представление (neudovl, udovl, horosho, otlichno, oshibka).
Значение oshibka предназначено для тех случаев, когда в функцию передано недопустимое значение оценки (например, 1).
Для построения таблицы в функции main организуется цикл, а преобразование представления (каждой) оценки выполняется в функции
char* convert(int mark),
Аргумент mark передает функции convert преобразуемую оценку, а результат преобразования (текстовое представление экзаменационной оценки) является возвращаемым значением функции.
Детали процедуры преобразования в разных пунктах задания реализуется по-разному. Функцию main можно использовать одну и ту же, а варианты функции преобразования можно назвать convert1, convert2, … . Для отладки каждого нового варианта функции достаточно подправлять в main имя функции преобразования (не забыть описать прототипы для всех функций).
Во всех случаях, кроме первого варианта, основу функции convert составляет переключатель switch, работа которого регулируется значением оценки. Создаются пять отдельных ветвей: для оценок 2, 3, 4, 5, а также общая ветвь для всех остальных случаев, т.е. для ошибочных ситуаций.
Написать следующие варианты функции convert.
Задание 1.1 (использование операторов if-else)
Каждое условие if определяет оператор возврата с соответствующим литералом.
Написать два варианта функции с короткими и вложенными операторами if. Как в каждом случае реализовать сообщение в случае ошибки?
Задание 1.2 (использование case в сочетании с return)
Каждая ветвь вычислений в переключателе состоит из одного оператора return, возвращающего литерал строковое представление оценки.
Задание 1.3 (использование массива указателей на строки)
В функции создается двумерный статический массив типа char, который инициализируется текстовыми названиями оценок (какую минимальную длину строки нужно задать для этого массива?).
Каждая ветвь, включая случай ошибки, состоит из одного оператора return, который возвращает указатель на первый элемент той строки двумерного массива, который содержит текстовое представление нужной оценки (как получить этот указатель через имя массива?). Этого указателя будет достаточно, чтобы прочесть весь литерал.
Добившись правильной работы программы, временно убрать из определения массива служебное слово static и объяснить, что изменилось в работе программы.
Задание 1.4 (использование массива указателей на строки)
Вариант предыдущего задания. В функции создается обычный (нестатический) массив указателей на строки pmarks, который инициализируется текстовыми названиями оценок. Этот массив используется для возврата строк. Почему здесь не требуется делать массив статическим?
Задание 1.5 (использование одного кода для нескольких case)
Это более компактный вариант программы для задания 1.3. Значения оценок легко пересчитать в значения индекса массива их текстовых названий. Поэтому для случаев 2, 3, 4 и 5 можно использовать одну и ту же ветвь вычислений (т.е. нескольким case будет соответствовать один и тот же оператор). По-прежнему остается отдельная ветвь для ошибочных ситуаций.
Задание 1.6 (использование case в сочетании с break)
В новом варианте используется единственный, общий для всех случаев оператор возврата return в конце функции.
В функции определяется вспомогательная переменная pc типа "указатель на char".
Для случаев 2, 3, 4, 5 и ошибок вновь создаются отдельные ветви, каждая из которых содержит один оператор присваивание переменной pc соответствующего литерала.
Функция возвращает значение pc.
Задание 1.7 (использование двумерного массива типа char)
Это вариант предыдущего задания.
Для хранения текстовых значений оценок использовать обычный двумерный массив символов. Какую длину строки массива нужно задать? Нужно ли сделать этот массив статическим? Что нужно присвоить переменной pc?
Контрольные вопросы
1. В чем преимущества использования массива указателей на строки перед двумерным массивом типа char?
2. Адреса из какой части среды выполнения программы будет содержать указатель pc в задании 1.5?