
2. Функции в языке Си.
Функция — это независимая совокупность объявлений и
операторов, обычно предназначенная для выполнения
определенной задачи. Программы на Си состоят по крайней мере
из одной функции main, но могут содержать и больше функций.
Определение функции специфицирует имя функции, ее
формальные параметры, объявления и операторы, которые
определяют ее действия. В определении функции может быть
задан также тип возврата и ее класс памяти.
В объявлении задается имя, тип возврата и класс памяти
функции, чье явное определение произведено в другой части
программы. В объявлении функции могут быть также
специфицированы число и типы аргументов функции. Это
позволяет компилятору сравнить типы действительных
аргументов и формальных параметров функции. Объявления не
обязательны для функций, возвращающих величины типа int.
Чтобы обеспечить корректное обращение при других типах
возвратов, необходимо объявить функцию перед ее вызовом.
Вызов функции передает управление из вызывающей
функции к вызванной. Действительные аргументы, если они есть,
передаются по значению в вызванную функцию. При
выполнении оператора return в вызванной функции управление
и, возможно, значение возврата передаются в вызывающую
функцию.
3. Прототипы функций
Функции могут быть объявлены в программе так же как и переменная. Такие объявленные функции, обычно называемые прототипами. Позволяют компилятору выполнить проверку правильности передачи аргументов функции (количество, порядок и тип аргументов), а так же типа значения самой функции.
4.Глобальные (внешние) и локальные переменные
Локальные переменные
Переменные, объявленные внутри функций, называются локальными переменными. В некоторых книгах по С они называются динамическими переменными. В этой книге используется более распространенный термин локальная переменная. Локальную переменную можно использовать только внутри блока, в котором она объявлена. Иными словами, локальная переменная невидима за пределами своего блока. (Блок программы — это описания и инструкции, объединенные в одну конструкцию путем заключения их в фигурные скобки.)
Локальные переменные существуют только во время выполнения программного блока, в котором они объявлены, создаются они при входе в блок, а разрушаются — при выходе из него. Более того, переменная, объявленная в одном блоке, не имеет никакого отношения к переменной с тем же именем, объявленной в другом блоке.
Глобальные переменные
В отличие от локальных, глобальные переменные видимы и могут использоваться в любом месте программы. Они сохраняют свое значение на протяжении всей работы программы. Чтобы создать глобальную переменную, ее необходимо объявить за пределами функции. Глобальная переменная может быть использована в любом выражении, независимо от того, в каком блоке это выражение используется.
5. Функция Main
Каждая программа на СИ имеет одну и только одну функцию с именем main. Эта функция определяет, где начинаются и заканчиваются вычисления в вашей программе
Функция main вызывается ОС при запуске программы на выполнение. С помощью ОС функции main можно передавать и получить от нее значения. Вызывать функцию main из программы запрещено это приводит к зацыкливанию программы.
7. Оператор while. Примеры
Оператор цикла while называется циклом с предусловием и имеет следующий формат:
while (выражение) тело ;
В качестве выражения допускается использовать любое выражение языка Си, а в качестве тела любой оператор, в том числе пустой или составной. Схема выполнения оператора while следующая:
1. Вычисляется выражение.
2. Если выражение ложно, то выполнение оператора while заканчивается и выполняется следующий по порядку оператор. Если выражение истинно, то выполняется тело оператора while.
3. Процесс повторяется с пункта 1.
Оператор цикла вида
for (выражение-1; выражение-2; выражение-3) тело ;
может быть заменен оператором while следующим образом:
выражение-1;
while (выражение-2)
{ тело
выражение-3;
}
Так же как и при выполнении оператора for, в операторе while вначале происходит проверка условия. Поэтому оператор while удобно использовать в ситуациях, когда тело оператора не всегда нужно выполнять.
Внутри операторов for и while можно использовать локальные переменные, которые должны быть объявлены с определением соответствующих типов.
8. Оператор do
Оператор цикла 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);
9.Оператор if-else
Формат оператора:
if (выражение) оператор-1; [else оператор-2;]
Выполнение оператора if начинается с вычисления выражения.
Далее выполнение осуществляется по следующей схеме:
- если выражение истинно (т.е. отлично от 0), то выполняется оператор-1.
- если выражение ложно (т.е. равно 0),то выполняется оператор-2.
- если выражение ложно и отсутствует оператор-2 (в квадратные скобки заключена необязательная конструкция), то выполняется следующий за if оператор.
После выполнения оператора 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:
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.
10. Оператор 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.
11. Оператор switch в тетради
12.Оператор go to в тетради
13.Операторы break, continue
Оператор break применяется в двух случаях. Во-первых, в операторе switch с его помощью прерывается выполнение последовательности case (см. раздел "Оператор выбора — switch" ранее в этой главе). В этом случае оператор break не передает управление за пределы блока. Во-вторых, оператор break используется для немедленного прекращения выполнения цикла без проверки его условия, в этом случае оператор break передает управление оператору, следующему после оператора цикла.
Когда внутри цикла встречается оператор break, выполнение цикла безусловно (т.е. без проверки каких-либо условий.) прекращается и управление передается оператору, следующему за ним. Например, программа
#include <stdio.h>
int main(void)
{
int t;
for(t=0; t<100; t++) {
printf("%d ", t);
if(t==10) break;
}
return 0;
}
выводит на экран числа от 0 до 10. После этого выполнение цикла прекращается оператором break, условие t < 100 при этом игнорируется.
Оператор break часто используется в циклах, в которых некоторое событие должно вызвать немедленное прекращение выполнения цикла. В следующем примере нажатие клавиши прекращает выполнение функции look_up():
void look_up(char *name)
{
do {
/* поиск имени 'name' */
if(kbhit()) break;
} while(!found);
/* process match */
}
Библиотечная функция kbhit() возвращает 0, если клавиша не нажата (то есть, буфер клавиатуры пуст), в противном случае она возвращает ненулевое значение. В стандарте С функция kbhit() не определена, однако практически она поставляется почти с каждым компилятором (возможно, под несколько другим именем).
Оператор break вызывает выход только из внутреннего цикла. Например, программа
for(t=0; t<100; ++t) {
count = 1;
for(;;) {
printf("%d ", count);
count++;
if(count==10) break;
}
}
100 раз выводит на экран числа от 1 до 9. Оператор break передает управление внешнему циклу for.
Если оператор break присутствует внутри оператора switch, который вложен в какие-либо циклы, то break относится только к switch, выход из цикла не происходит.
Можно сказать, что оператор continue немного похож на break. Оператор break вызывает прерывание цикла, a continue— прерывание текущей итерации цикла и осуществляет переход к следующей итерации. При этом все операторы до конца тела цикла пропускаются. В цикле for оператор continue вызывает выполнение операторов приращения и проверки условия цикла. В циклах while и do-while оператор continue передает управление операторам проверки условий цикла. В следующем примере программа подсчитывает количество пробелов в строке, введенной пользователем:
/* Подсчет количества пробелов */
#include <stdio.h>
int main(void)
{
char s[80], *str;
int space;
printf("Введите строку: ");
gets(s);
str = s;
for(space=0; *str; str++) {
if(*str != ' ') continue;
space++;
}
printf("%d пробелов\n", space);
return 0;
}
Каждый символ строки сравнивается с пробелом. Если сравниваемый символ не является пробелом, оператор continueпередает управление в конец цикла for и выполняется следующая итерация. Если символ является пробелом, значение переменной space увеличивается на 1.
В следующем примере оператор continue применяется для выхода из цикла while путем передачи управления на условие цикла:
void code(void)
{
char done, ch;
done = 0;
while(!done) {
ch = getchar();
if(ch=='$') {
done = 1;
continue;
}
putchar(ch+1); /* печать следующего в алфавитном
порядке символа */
}
}
Функция code предназначена для кодирования сообщения путем замены каждого символа символом, код которого на 1 больше кода исходного символа в коде ASCII. Например, символ А заменяется символом В (если это латинские символы.). Функция прекращает работу при вводе символа $. При этом переменной done присваивается значение 1 и оператор continueпередает управление на условие цикла, что и прекращает выполнение цикла
14-15. Функция ввода scanf и вывода printf
Функция printf() является функцией стандартного вывода. С помощью этой функции можно вывести на экран монитора строку символов, число, значение переменной...
Функция printf() имеет прототип в файле stdio.h int printf(char *управляющая строка, ...);
В случае успеха функция printf() возвращает число выведенных символов.
Управляющая строка содержит два типа информации: символы, которые непосредственно выводятся на экран, и спецификаторы формата, определяющие, как выводить аргументы.
Функция printf() это функция форматированного вывода. Это означает, что в параметрах функции необходимо указать формат данных, которые будут выводиться. Формат данных указывается спецификаторами формата. Спецификатор формата начинается с символа % за которым следует код формата.
Спецификаторы формата:
%с |
символ |
%d |
целое десятичное число |
%i |
целое десятичное число |
%e |
десятичное число в виде x.xx e+xx |
%E |
десятичное число в виде x.xx E+xx |
%f |
десятичное число с плавающей запятой xx.xxxx |
%F |
десятичное число с плавающей запятой xx.xxxx |
%g |
%f или %e, что короче |
%G |
%F или %E, что короче |
%o |
восьмеричное число |
%s |
строка символов |
%u |
беззнаковое десятичное число |
%x |
шестнадцатеричное число |
%X |
шестнадцатеричное число |
%% |
символ % |
%p |
указатель |
%n |
указатель |
Кроме того, к командам формата могут быть применены модификаторы l и h.
%ld |
печать long int |
%hu |
печать short unsigned |
%Lf |
печать long double |
В спецификаторе формата, после символа % может быть указана точность (число цифр после запятой). Точность задаётся следующим образом: %.n<код формата>. Где n - число цифр после запятой, а <код формата> - один из кодов приведённых выше.
Например, если у нас есть переменная x=10.3563 типа float и мы хотим вывести её значение с точностью до 3-х цифр после запятой, то мы должны написать:
printf("Переменная x = %.3f",x);
Результат: Переменная x = 10.356
Вы также можете указать минимальную ширину поля отводимого для печати. Если строка или число больше указанной ширины поля, то строка или число печатается полностью. Например, если вы напишите:
printf("%5d",20);
то результат будет следующим: 20
Обратите внимание на то, что число 20 напечаталось не с самого начала строки. Если вы хотите чтобы неиспользованные места поля заполнялись нулями, то нужно поставить перед шириной поля символ 0. Например:
printf("%05d",20);
Результат: 00020
Кроме спецификаторов формата данных в управляющей строке могут находиться управляющие символы:
\b |
BS, забой |
\f |
Новая страница, перевод страницы |
\n |
Новая строка, перевод строки |
\r |
Возврат каретки |
\t |
Горизонтальная табуляция |
\v |
Вертикальная табуляция |
\" |
Двойная кавычка |
\' |
Апостроф |
\\ |
Обратная косая черта |
\0 |
Нулевой символ, нулевой байт |
\a |
Сигнал |
\N |
Восьмеричная константа |
\xN |
Шестнадцатеричная константа |
\? |
Знак вопроса |
Чаще всего вы будете использовать символ \n. С помощью этого управляющего символа вы сможете переходить на новую строку. Посмотрите примеры программ и вы всё поймёте.
Примеры программ.
/* Пример 1 */ #include <stdio.h> void main(void) { int a,b,c; // Объявление переменных a,b,c a=5; b=6; c=9; printf("a=%d, b=%d, c=%d",a,b,c); }
Результат работы программы: a=5, b=6, c=9
/* Пример 2 */ #include <stdio.h> void main(void) { float x,y,z; x=10.5; y=130.67; z=54; printf("Координаты объекта: x:%.2f, y:%.2f, z:%.2f", x, y, z); }
Результат работы программы: Координаты объекта: x:10.50, y:130.67, z:54.00
/* Пример 3 */ #include <stdio.h> void main() { int x; x=5; printf("x=%d", x*2); }
Результат работы программы: x=10
/* Пример 4 */ #include <stdio.h> void main(void) { printf("\"Текст в кавычках\""); printf("\nСодержание кислорода: 100%%"); }
Результат работы программы: "Текст в кавычках" Содержание кислорода: 100%
/* Пример 5 */ #include <stdio.h> void main(void) { int a; a=11; // 11 в десятичной равно b в шестнадцатеричной printf("a-dec=%d, a-hex=%X",a,a); }
Результат работы программы: a-dec=11, a-hex=b
/* Пример 6 */ #include <stdio.h> void main(void) { char ch1,ch2,ch3; ch1='A'; ch2='B'; ch3='C'; printf("%c%c%c",ch1,ch2,ch3); }
Результат работы программы: ABC
/* Пример 7 */ #include <stdio.h> void main(void) { char *str="Моя строка."; printf("Это %s",str); }
Результат работы программы: Это Моя строка.
/* Пример 8 */ #include <stdio.h> void main(void) { printf("Здравствуйте!\n"); // После печати будет переход на новую строку - \n printf("Меня зовут Павел."); // Это будет напечатано на новой строке }
Результат работы программы: Здравствуйте! Меня зовут Павел.