Операторы языка Си
Кафедра: Автоматика и Вычислительная Техника
ОПЕРАТОРЫ ЯЗЫКА СИ
Содержание
ХАРАКТЕРИСТИКИ ОПЕРАТОРОВ
ОПИСАНИЯ ОПЕРАТОРОВ
Пустой оператор
Оператор безусловного перехода
Операторы условного перехода
Оператор if
Оператор if-else
Оператор if-else if
Оператор переключатель switch
Операторы цикла
Оператор цикла for
Оператор цикла с предусловием while
Оператор цикла с постусловием do-while
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
Убираем оператор goto
Упрощаем логические выражения
Взаимозаменяемость циклов
Компактный for
Обходимся без операторов условного перехода
ЛАБОРАТОРНЫЕ ЗАДАНИЯ
Линейное уравнение
Ввод русской буквы
Таблица умножения
ASCII-таблица
Машинный ноль и машинный эпсилон
ДОПОЛНИТЕЛЬНЫЕ ЗАДАНИЯ
БИБЛИОГРАФИЧЕСКИЙ СПИСОК
Характеристики операторов
Все операторы языка С могут быть условно разделены на следующие категории:
- условные операторы, к которым относятся оператор условия if и оператор выбора switch;
- операторы цикла (for,while,do while);
- операторы перехода (break, continue, return, goto);
- другие операторы (оператор "выражение", пустой оператор).
Операторы в программе могут объединяться в составные операторы с помощью фигурных скобок. Любой оператор в программе может быть помечен меткой, состоящей из имени и следующего за ним двоеточия.
Все операторы языка С, кроме составных операторов, заканчиваются точкой с запятой ";".
Описания операторов
Пустой оператор
Пустой оператор состоит только из точки с запятой. При выполнении этого оператора ничего не происходит. Он обычно используется в следующих случаях:
- в операторах do, for, while, if в строках, когда место оператора не требуется, но по синтаксису требуется хотя бы один оператор;
- при необходимости пометить фигурную скобку.
Синтаксис языка С требует, чтобы после метки обязательно следовал оператор. Фигурная же скобка оператором не является. Поэтому, если надо передать управление на фигурную скобку, необходимо использовать пустой оператор.
Пример:
int main ( )
{
;
{
if (...) goto a; /* переход на скобку */
{ ...
}
a:;
}
return 0;
}
Оператор безусловного перехода
Использование оператора безусловного перехода goto в практике программирования на языке С настоятельно не рекомендуется, так как он затрудняет понимание программ и возможность их модификаций.
Формат этого оператора следующий:
goto имя-метки;
...
имя-метки: оператор;
Оператор goto передает управление на оператор, помеченный меткой имя-метки. Помеченный оператор должен находиться в той же функции, что и оператор goto, а используемая метка должна быть уникальной, т.е. одно имя-метки не может быть использовано для разных операторов программы. Имя-метки - это идентификатор.
Любой оператор в составном операторе может иметь свою метку. Используя оператор goto, можно передавать управление внутрь составного оператора. Но нужно быть осторожным при входе в составной оператор, содержащий объявления переменных с инициализацией, так как объявления располагаются перед выполняемыми операторами и значения объявленных переменных при таком переходе будут не определены.
Операторы условного перехода
Оператор if
Формат оператора:
if (выражение) оператор;
Выполнение оператора if начинается с вычисления выражения.
Далее выполнение осуществляется по следующей схеме:
- если выражение истинно (т.е. отлично от 0), то выполняется оператор.
- если выражение ложно, то выполняется следующий за if оператор.
После выполнения оператора if значение передается на следующий оператор программы, если последовательность выполнения операторов программы не будет принудительно нарушена использованием операторов перехода.
Пример: if (i < j) i++:
Оператор if-else
Формат оператора:
if (выражение) оператор-1; else оператор-2;
Выполнение оператора if начинается с вычисления выражения.
Далее выполнение осуществляется по следующей схеме:
- если выражение истинно (т.е. отлично от 0), то выполняется оператор-1.
- если выражение ложно (т.е. равно 0),то выполняется оператор-2.
После выполнения оператора if значение передается на следующий оператор программы, если последовательность выполнения операторов программы не будет принудительно нарушена использованием операторов перехода.
Пример:
if (i < j) i++:
else { j = i-3; i++; }
Этот пример иллюстрирует также и тот факт, что на месте оператор-1, так же как и на месте оператор-2 могут находиться сложные конструкции.
Допускается использование вложенных операторов if. Оператор if может быть включен в конструкцию if или в конструкцию else другого оператора if. Чтобы сделать программу более читабельной, рекомендуется группировать операторы и конструкции во вложенных операторах if, используя фигурные скобки. Если же фигурные скобки опущены, то компилятор связывает каждое ключевое слово else с наиболее близким if, для которого нет else.
Примеры:
int main ( )
{
int t=2, b=7, r=3;
if (t>b)
{
if (b < r) r=b;
}
else r=t;
return (0);
}
В результате выполнения этой программы r станет равным 2.
Если же в программе опустить фигурные скобки, стоящие после оператора if, то программа будет иметь следующий вид:
int main ( )
{
int t=2,b=7,r=3;
if ( a>b )
if ( b < c ) t=b;
else
r=t;
return (0);
}
В этом случае r получит значение равное 3, так как ключевое слово else относится ко второму оператору if, который не выполняется, поскольку не выполняется условие, проверяемое в первом операторе if.
Оператор if-else if
Следующий фрагмент иллюстрирует вложенные операторы if:
char ZNAC;
int x,y,z;
:
if (ZNAC == '-') x = y - z;
else if (ZNAC == '+') x = y + z;
else if (ZNAC == '*') x = y * z;
else if (ZNAC == '/') x = y / z;
else ...
Из рассмотрения этого примера можно сделать вывод, что конструкции использующие вложенные операторы if, являются довольно громоздкими и не всегда достаточно надежными. Другим способом организации выбора из множества различных вариантов является использование специального оператора выбора switch.
Оператор переключатель switch
Оператор switch предназначен для организации выбора из множества различных вариантов. Формат оператора следующий:
switch ( выражение )
{ [объявление]
:
[ case константное-выражение1]: [ список-операторов1]
[ case константное-выражение2]: [ список-операторов2]
:
:
[ default: [ список операторов ]]
}
Выражение, следующее за ключевым словом switch в круглых скобках, может быть любым выражением, допустимыми в языке С, значение которого должно быть целым.
Значение этого выражения является ключевым для выбора из нескольких вариантов. Тело оператора smitch состоит из нескольких операторов, помеченных ключевым словом case с последующим константным-выражением. Следует отметить, что использование целого константного выражения является существенным недостатком, присущим рассмотренному оператору.
Так как константное выражение вычисляется во время трансляции, оно не может содержать переменные или вызовы функций. Обычно в качестве константного выражения используются целые или символьные константы.
Все константные выражения в операторе switch должны быть уникальны. Кроме операторов, помеченных ключевым словом case, может быть, но обязательно один, фрагмент, помеченный ключевым словом default.
Список операторов может быть пустым, либо содержать один или более операторов. Причем в операторе switch не требуется заключать последовательность операторов в фигурные скобки.
Отметим также, что в операторе switch можно использовать свои локальные переменные, объявления которых находятся перед первым ключевым словом case, однако в объявлениях не должна использоваться инициализация.
Схема выполнения оператора switch следующая:
- вычисляется выражение в круглых скобках;
- вычисленные значения последовательно сравниваются с константными выражениями, следующими за ключевыми словами case;
- если одно из константных выражений совпадает со значением выражения, то управление передается на оператор, помеченный соответствующим ключевым словом case;
- если ни одно из константных выражений не равно выражению, то управление передается на оператор, помеченный ключевым словом default, а в случае его отсутствия управление передается на следующий после switch оператор.
Отметим интересную особенность использования оператора switch: конструкция со словом default может быть не последней в теле оператора switch. Ключевые слова case и default в теле оператора switch существенны только при начальной проверке, когда определяется начальная точка выполнения тела оператора switch. Все операторы, между начальным оператором и концом тела, выполняются вне зависимости от ключевых слов, если только какой-то из операторов не передаст управления из тела оператора switch. Таким образом, программист должен сам позаботится о выходе из case, если это необходимо. Чаще всего для этого используется оператор break.
Для того, чтобы выполнить одни и те же действия для различных значений выражения, можно пометить один и тот же оператор несколькими ключевыми словами case.
Пример:
int i=2;
switch (i)
{
case 1: i += 2;
case 2: i *= 3;
case 0: i /= 2;
case 4: i -= 5;
default: ;
}
Выполнение оператора switch начинается с оператора, помеченного case 2. Таким образом, переменная i получает значение, равное 6, далее выполняется оператор, помеченный ключевым словом case 0, а затем case 4, переменная i примет значение 3, а затем значение -2. Оператор, помеченный ключевым словом default, не изменяет значения переменной.
Рассмотрим ранее приведенный пример, в котором иллюстрировалось использование вложенных операторов if, переписанной теперь с использованием оператора switch.
char ZNAC;
int x,y,z;
switch (ZNAC)
{
case '+': x = y + z; break;
case '-': x = y - z; break;
case '*': x = y * z; break;
case '/': x = u / z; break;
default : ;
}
Использование оператора break позволяет в необходимый момент прервать последовательность выполняемых операторов в теле оператора switch, путем передачи управления оператору, следующему за switch.
Отметим, что в теле оператора switch можно использовать вложенные операторы switch, при этом в ключевых словах case можно использовать одинаковые константные выражения.
Пример:
switch (a)
{
case 1: b=c; break;
case 2:
switch (d)
{
case 0: f=s; break;
case 1: f=9; break;
case 2: f-=9; break;
}
case 3: b-=c; break;
:
}
Операторы цикла
Оператор цикла for
Оператор for - это наиболее общий способ организации цикла. Он имеет следующий формат:
for ( выражение 1 ; выражение 2 ; выражение 3 ) тело
Выражение 1 обычно используется для установления начального значения переменных, управляющих циклом. Выражение 2 - это выражение, определяющее условие, при котором тело цикла будет выполняться. Выражение 3 определяет изменение переменных, управляющих циклом после каждого выполнения тела цикла.
Схема выполнения оператора for:
1. Вычисляется выражение 1.
2. Вычисляется выражение 2.
3. Если значения выражения 2 отлично от нуля (истина), выполняется тело цикла, вычисляется выражение 3 и осуществляется переход к пункту 2, если выражение 2 равно нулю (ложь), то управление передается на оператор, следующий за оператором for.
Существенно то, что проверка условия всегда выполняется в начале цикла. Это значит, что тело цикла может ни разу не выполниться, если условие выполнения сразу будет ложным.
Пример:
int main()
{
int i,b;
for (i=1; i<10; i++) b="i*i;" return 0; }
В этом примере вычисляются квадраты чисел от 1 до 9.
Некоторые варианты использования оператора for повышают его гибкость за счет возможности использования нескольких переменных, управляющих циклом.
Пример:
int main()
{
int top, bot;
char string[100], temp;
for ( top=0, bot=100 ; top < bot ; top++, bot--)
{
temp=string[top];
string[bot]=temp;
}
return 0;
}
В этом примере, реализующем запись строки символов в обратном порядке, для управления циклом используются две переменные top и bot. Отметим, что на месте выражение 1 и выражение 3 здесь используются несколько выражений, записанных через запятую, и выполняемых последовательно.
Другим вариантом использования оператора for является бесконечный цикл. Для организации такого цикла можно использовать пустое условное выражение, а для выхода из цикла обычно используют дополнительное условие и оператор break.
Пример:
for (;;)
{
...
... break;
...
}
Так как согласно синтаксису языка С оператор может быть пустым, тело оператора for также может быть пустым. Такая форма оператора может быть использована для организации поиска.
Пример:
for (i=0; t[i]<10 ; i++) ;
В данном примере переменная цикла i принимает значение номера первого элемента массива t, значение которого больше 10.
Оператор цикла с предусловием while
Оператор цикла while называется циклом с предусловием и имеет следующий формат:
while (выражение) тело ;
В качестве выражения допускается использовать любое выражение языка Си, а в качестве тела любой оператор, в том числе пустой или составной. Схема выполнения оператора while следующая:
1. Вычисляется выражение.
2. Если выражение ложно, то выполнение оператора while заканчивается и выполняется следующий по порядку оператор. Если выражение истинно, то выполняется тело оператора while.
3. Процесс повторяется с пункта 1.
Оператор цикла вида
for (выражение-1; выражение-2; выражение-3) тело ;
может быть заменен оператором while следующим образом:
выражение-1;
while (выражение-2)
{
тело
выражение-3;
}
Так же как и при выполнении оператора for, в операторе while вначале происходит проверка условия. Поэтому оператор while удобно использовать в ситуациях, когда тело оператора не всегда нужно выполнять.
Внутри операторов for и while можно использовать локальные переменные, которые должны быть объявлены с определением соответствующих типов.
Оператор цикла с постусловием do-while
Оператор цикла do while называется оператором цикла с постусловием и используется в тех случаях, когда необходимо выполнить тело цикла хотя бы один раз. Формат оператора имеет следующий вид:
do тело while (выражение);
Схема выполнения оператора do while :
1. Выполняется тело цикла (которое может быть составным оператором).
2. Вычисляется выражение.
3. Если выражение ложно, то выполнение оператора do while заканчивается и выполняется следующий по порядку оператор. Если выражение истинно, то выполнение оператора продолжается с пункта 1.
Чтобы прервать выполнение цикла до того, как условие станет ложным, можно использовать оператор break.
Операторы while и do while могут быть вложенными.
Пример:
int i,j,k;
...
i=0; j=0; k=0;
do { i++;
j--;
while (a[k] < i) k++;
}
while (i<30 && j<-30);
Практические задания
Убираем оператор goto
Запишите без оператора goto следующий фрагмент
m: if(A)
{
B;
goto m;
}
Упрощаем логические выражения
Перепишите операторы условного перехода так, чтобы их условия не содержали логических операций.
if(A && B || !C)
D;
else if(B || C)
E;
else
F;
Взаимозаменяемость циклов
Вычислить факториал n! тремя способами с помощью трех видов цикла.
Компактный for
Запишите двойной цикл
for (int i = 0; i<5; i++)
{
printf(“\n”);
for (int j = 0; j<4; j++)
printf(“%3d”, i*j);
}
с помощью одинарного цикла с теми же счетчиками i, j.
Обходимся без операторов условного перехода
Замените оператор
if(A)
B;
Эквивалентным оператором цикла for.
Лабораторные задания
Линейное уравнение
Операторы if-else if, switch. Написать программу, которая решает линейное уравнение a ∙ x + b = 0. Использовать операторы if-else if. Логические выражения в условиях этих операторов не должны содержать логических операций && и ||. Предусмотреть четыре возможных исхода при решении уравнения:
нет решения,
найдено единственное решение,
любое число является решением,
решение единственное, но не входит в диапазон типа переменной x.
В операторе if-else if определить некоторую переменную flag, которая принимает четыре значения, соответствующих возможному исходу решения. Вывод текстовой информации с результатами решения организовать с использованием оператора switch, условие которого содержит flag. Выход из программы должен быть единственным.
Организовать проверку корректности данных при вводе коэффициентов a и b.
Ввод русской буквы
Операторы while, switch. С клавиатуры вводятся символы. После анализа символа программа выводит на экран одно из следующих сообщений:
русская гласная буква такая-то,
русская согласная буква такая-то,
английская буква такая-то,
символ псевдографики такой-то,
другой символ.
В программе вместо числовых констант вида 128 использовать символьные константы вида ‘А’. Обработать символы с расширенным кодом. Выход из программы происходит по нажатию клавиши Escape.
Таблица умножения
Использование двойного цикла for. В программе вводятся шестнадцатеричные числа m и n, после чего на экран выводится таблица умножения в шестнадцатеричной системе счисления следующего вида
Таблица 1.
-
1
2
…
n
1
2
…
m
Из таблицы должно быть видно, что например, 112 = 121, 122 = 144, 132 = 169.
При больших размерах таблицу целесообразно выводить в файл. Это можно сделать из командной строки DOS с помощью команды
tabl.exe >> tabl.txt
ASCII-таблица
Использование двойного цикла for. Вывести на экран ascii-таблицу без управляющих символов в следующем виде
Таблица 2.
-
2
3
E
F
0
1
2
F
Символ с шестнадцатеричным кодом 0xST находится на пересечении столбца S и строки T.
Для вывода на экран графических представлений управляющих символов необходимо записывать их коды напрямую в видеопамять, без использования стандартных функций типа printf (см. [1]).
Машинный ноль и машинный эпсилон
Операторы while. Найти машинный ноль и машинный эпсилон для вещественных типов данных: float, double, long double.
Сравнить с теоретическими результатами и со справочной информацией в Help оболочки.
Учесть, что в арифметических выражениях вида 1+x>1 компилятор использует повышенную точность во внутренних вычислениях. Поэтому значение 1+x необходимо запомнить во вспомогательной переменной того же типа, который имеет переменная x.
Дополнительные задания
Найдите сумму цифр целого числа типа unsigned long. Число вводится с клавиатуры.
Найдите вероятность счастливого шестизначного трамвайного билета. У такого билета сумма первых трех цифр равняется сумме трех последних.
С клавиатуры вводится число типа int. Найдите сумму битов этого числа.
Вывести на экран все простые числа до N включительно. Число N имеет тип unsigned int и вводится с клавиатуры.
БИБЛИОГРАФИЧЕСКИЙ СПИСОК
Керниган Б., Ритчи Д., Фьюэр А. Язык программирования Си: Задачи по языку Си. М.: Финансы и статистика, 1985. – 192с.
Керниган Б., Ритчи Д. Язык программирования Си. М.: Финансы и статистика, 1992. - 272с.
Подбельский В.В., Фомин С.С. Программирование на языке Си. Учеб. пособие. М.: Финансы и статистика, 2004. 600 с.
1