Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторная работа №5.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
1.18 Mб
Скачать

Лабораторная работа №5

Тема: Условные операторы в языке С. Преобразование типов.

Цель работы: Ознакомиться с логической конструкцией языка: switch.

Теоретическая часть

Хотя любые комбинации условий можно выразить с помощью оператора if, довольно часто запись становится неудобной и запутанной. Оператор выбора switch используется, когда для каждого из нескольких возможных значений выражения нужно выполнить определенные действия. Например, предположим, что в переменной code хранится целое число от 0 до 2, и нам нужно выполнить различные действия в зависимости от ее значения:

switch (code) {

case 0:

printf("код ноль");

x = x + 1;

break;

case 1 :

printf("код один");

y = y + 1;

break;

case 2:

printf("код два");

z = z + 1;

break;

default:

printf("Необрабатываемое значение");

}

В зависимости от значения code управление передается на одну из меток case. Выполнение оператора заканчивается по достижении либо оператора break, либо конца оператора switch. Таким образом, если code равно 1, выводится " код один ", а затем переменная y увеличивается на единицу. Если бы после этого не стоял оператор break, то управление "провалилось" бы дальше, была бы выведена фраза " код два ", и переменная z тоже увеличилась бы на единицу.

Если значение переключателя не совпадает ни с одним из значений меток case, то выполняются операторы, записанные после метки default. Метка default может быть опущена, что эквивалентно записи:

default:

; // пустой оператор, не выполняющий

// никаких действий

Очевидно, что приведенный пример можно переписать с помощью оператора if:

if (code == 0) {

printf("код ноль");

x = x + 1;

} else if (code == 1) {

printf("код один");

y = y + 1;

} else if (code == 2) {

printf("код два");

z = z + 1;

} else {

printf("Необрабатываемое значение");

}

Пожалуй, запись с помощью оператора переключения switch более наглядна. Особенно часто переключатель используется, когда значение выражения имеет тип набора.

Общая форма записи оператора switch:

switch (expression) {

case value1:

program statement;

...

break;

case value2:

program statement;

...

break;

...

case valuen:

program statement;

...

break;

default:

program statement;

...

break;

},

где

  1. expression - целое выражение (или выражение, которое может быть преобразовано в целое выражение);

  2. value1, value2,..., valuen - целое выражение с постоянным значением (или выражение, которое может быть преобразовано к такому выражению);

  3. program statement – обозначает операторы, число которых может быть больше или равно нулю.

Метки value1, value2,..., valuen, обозначающие альтернативы case, должны быть уникальными; двух одинаковых меток быть не может. Только одна альтернатива может получить префикс default.

Выражение заключенного в круглые скобки оператора последовательно сравнивается со значениями value1, value2,..., valuen, которые должны быть простыми константами или константными выражениями. В том случае, когда одно из этих значений равно значению, выполняются утверждения, которые следуют за данным значением.

Утверждение break сигнализирует об окончании выполнения утверждений и приводит к выходу из оператора switch. Утверждение break ставится в конце каждого варианта выбора. Если этого не сделать, то выполнение последовательности утверждений перейдет в следующий вариант выбора и будет выполняться до тех пор, пока не встретится утверждение break.

Специальный дополнительный вариант default будет выполнен в том случае, когда не будет найдено ни одного совпадения.

Операторы if и switch той или иной синтаксической конструкции существуют практически во всех языках программирования (в первую очередь языках высокого уровня), и их часто называют операторами ветвления.

Пример:

/* Реализация работы калькулятора. Сначала задается

число - сколько раз нужно подсчитать. Вводятся

левый операнд, операция, правый операнд. Оператор

выбора определяет, какой оператор должен работать.

Результат выводится на экран. */

#include <stdio.h>

#include <conio.h>

#include <process.h>

main()

{

float a,b;

char opr;

float result=0;

int i=0;

clrscr();

printf("Введите операнд, операцию, операнд:\n");

scanf("%f%c%f",&a,&opr,&b);

switch(opr)

{

case '+': result=a+b; break;

case '-': result=a-b; break;

case '*': result=a*b; break;

case '/': result=a/b; break;

default:

printf("Ошибка. Неверен знак операции ");

exit(1); /* функция берется

из заголовочного

файла process.h*/

}

textcolor (15); /* функция берется из

заголовочного файла conio.h*/

cprintf("Результат равен %g\n",result);

textcolor(12);

/* функция берется из заголовочного файла

conio.h */

cprintf("Конец работы\n");

/* текст печатается красным цветом*/

getchar () ;

exit(0);

/* функция берется из заголовочного файла

process.h */

}

Эквивалентность типов

Существует несколько схем для определения того, являются ли типы двух объектов эквивалентными. Две схемы, наиболее часто используемые, называются структурная эквивалентность типов и именная эквивалентность типов. В соответствии со схемой структурной эквивалентности типов два объекта относятся к одному и тому же типу только в том случае, если их компоненты имеют одинаковые типы. В соответствии со схемой именной эквивалентности типов два объекта имеют один и тот же тип только в случае их определения с использованием имени того же типа.

Большинство реализаций языка Си используют схему структурной эквивалентности типов. Однако в книге (Ritche, D.M. 1980/ The C Programming Language - Reference Manual/ AT&T Bell Laboratories, Murray Hill, N.J. 07974) вопрос об эквивалентности типов игнорируется, и при каждой реализации может быть выбрана своя схема определения эквивалентности типов. Следовательно, вполне возможно, что результаты правильно работающей программы станут неверными при замене компилятора!

Преобразование типов

В операторах и выражениях должны использоваться переменные и константы только одного типа. Если все же мы смешиваем типы в одном выражении, то компилятор языка Си не считает программу неправильной, как это произошло бы при программировании на языке Паскаль. Вместо этого компилятор использует набор правил для автоматического преобразования типов. Это очень удобно, но может оказаться и опасным, особенно если мы допустили смешение типов нечаянно. Приведем несколько основных правил, касающихся преобразования типов:

  1. Если операция выполняется над данными двух различных типов, обе величины приводятся к высшему из двух типов. Этот процесс называется повышением типа.

  2. Последовательность имен типов, упорядоченных от высшего типа к низшему, выглядит так: double, float, long, int, short, char. Применение ключевого слова unsigned повышает ранг соответствующего типа данных со знаком.

  3. В операторе присваивания конечный результат вычисления выражения в правой части приводится к типу переменной, которой должно быть присвоено это значение. Данный процесс может привести к повышению типа, как описано выше, или к понижению, при котором величина приводится к типу данных, имеющему более низкий приоритет.

Повышение типа обычно происходит гладко, в то время как понижение может привести к затруднениям. Причина этого проста: все число целиком может не поместиться в элементе данных низшего типа. Переменная типа char может иметь целое значение 101, но не 22225.

Пример, приведенный ниже, иллюстрирует применение этих правил:

/*преобразования*/

int main( )

{

char ch;

int i;

float f1;

f1=i=ch='A'; /***8***/

printf("ch=%c,i=%d,f1=%2.2f\n",ch,i,f1);

ch=ch+1; /***10***/

i=f1=f1+2*ch; /***11***/

f1=2.0*ch+i; /***12***/

printf("ch=%c,i=%d,f1=%2.2f\n",ch,i,f1);

ch=2.0e30;/***14***/

printf("Теперь ch=%c\n",ch);

}

Выполнив программу "преобразования", получим следующие результаты:

ch=A,i=65,f1=65.00

ch=B,i=197,f1=329.00

Теперь ch=

Разбор программы

Строки 8 и 9: величина ' A ' присваивается символьной переменной ch. Переменная i получает целое значение, являющееся преобразованием символа ' A ' в целое число, т.е. 65. Переменная f1 получает значение 65.00, являющееся преобразованием числа 65 в число с плавающей точкой.

Строки 10 и 13: значение символьной переменной ' A ' преобразуется в целое число 65, к которому затем добавляется 1. После этого получившееся в результате число 66 преобразуется в код символа В и помещается в переменную ch.

Строки 11 и 13: при умножении на 2 значение переменной ch преобразуется в целое число 66. При сложении с величиной переменной f1 получившееся в результате число 132 преобразуется в число с плавающей точкой. Результат 197.00 преобразуется в число целого типа и присваивается переменной i.

Строки 12 и 13: перед умножением на 2.0 значение переменной ch('B') преобразуется в число с плавающей точкой. Перед выполнением сложения величина переменной i(197) преобразуется в число с плавающей точкой, а результат 329.00 присваивается переменной f1.

Строки 14 и 15: здесь производится попытка осуществить преобразование типов в порядке убывания старшинства - переменная ch полагается равной сравнительно большому числу. Результаты оказываются неутешительными. Независимо от переполнения и усечения, которые имеют место, в итоге мы получили код, соответствующий какому-то непечатаемому знаку.

Существует еще один вид преобразования типов. Для сохранения точности вычислений при арифметических операциях все величины типа float преобразуются в данные типа double. Это существенно уменьшает ошибку округления. Конечный результат преобразуется обратно в число типа float, если это диктуется соответствующим оператором описания.