- •ЗАМЕЧАНИЕ <...> в описании правил записи (формата) конструкций языка означают понятие языка, в программе не записываются.
- •Пример
- •Формат
- •Значение
- •Содержание
- •Формат
- •if ( <выражение> )
- •Форма представления одного данного
- •Ввод двумерного массива
- •Вопрос? А как же передать результаты работы в вызывающую процедуру, если реально можно передать только одно значение?
- •Вызывающая
- •Вызываемая
- •ВЫЧИСЛЕНИЕ КВАДРАТИЧНОЙ ФОРМЫ
a[i][j]=i=i+1; i=2 a[2][3]=2
5.2 Оператор перехода
Формат goto <метка>; <помеченный оператор>
<метка> := <идентификатор>, полноценный идентификатор, созданный по правилам языка Си.
<помеченный оператор>:= <метка>: <оператор>;
Пример: goto label;
…
label: x++;
5.3 Условный оператор. Пустой оператор
Конструкции ветвления позволяет выполнять некоторые операторы только в том случае, если выполняется некоторое условие. Кроме того, расширенный оператор ветвления позволяет выполнить другой оператор в том случае, если условие не выполняется.
Формат
if ( <выражение> )
<оператор 1>;
[else
<оператор 2>; ] Конструкция работает предельно просто: если условие не равно нулю, то выполня-
ется оператор_1, в противном случае – оператор_2. Обратите внимание, что опера-
тор_1 и оператор_2 должны представлять собой только одно выражение. Как вы уже догадались, так как условие должно возвращать некоторое значение, то оно не мо-
жет быть составным.
Примеры: if (a>b) c=a;
else
|
c=b; |
|
|
• |
Обход |
|
if ( x*x + y*y > r*r ) z=0; /* без else */ |
• |
x+1 |
|
x<0 |
y= |
|
x>=0 |
|
|
1−x |
||
|
|
|
|
if (x<0) y=x+1;
else
y=1–x;
23
Вложенные if. |
|
|||||
• |
if |
(x > y) |
|
|||
|
|
if |
(z = = 0) |
|||
|
|
else |
x = 5; |
|||
|
|
x = –5; |
||||
|
else |
|
|
|
||
|
if |
(z > 10) |
||||
|
|
|||||
|
|
else |
y = 5; |
|||
|
|
|
|
|||
|
|
y = –5; |
|
|||
|
x2−5 |
|
||||
• |
y= |
|
|
+3 |
|
|
|
x |
|||||
|
|
x−7 |
|
|||
|
|
|
|
|
|
|
if |
(x < 0) |
|
|
|||
else |
y = x*x–5; |
|
||||
if |
(x<=5) |
|
||||
|
|
|||||
|
else |
y = sqrt(x)+3; |
||||
|
|
|
|
|
|
y=x–7;
Пустой оператор.
Формат:;
x<0 0<=x<=5 x>5
Не выполняет никакого действия.
if (x > y)
if (z = = w)
if( w<p ) y = 1;
else |
p = q; |
else ; // |
при x>y && z!=w переход к оператору с меткой m1 |
else x = 4; |
|
m1: z = 5; |
|
5.4 Составной оператор
Употребляется везде, где стандарт языка Си предусматривает один оператор, а для решении задачи требуется несколько.
Формат { <оператор>; [<оператор>;]... }
Пример:
Задача: x = max (a, b) y = min(a, b) if ( a>b ) {
x = a;
24
y = b; } else { x = b; y = a; }
5.5 Циклы
5.5.1.Цикл while
Формат: |
while |
(e) /* e–условие продолжения цикла */ |
<оператор>; |
/* Тело цикла */ |
Все требования у условию и к выражению такие же, как и в конструкции ветвления. Эквивалентная схема
label: |
if ( !e ) goto next; |
S; |
|
goto |
label; |
next:........... |
Пример: Дано: a[i], i=1...100. |
Найти сумму(a[i]>0) и сумму(a[i]<0). |
|
pol = otr = i = 0; |
|
|
while ( i <= 100 ){ |
|
|
if (a[i] > 0 ) |
pol += a[i]; |
|
if (a[i] < 0) |
otr += a[i]; |
|
i++ ;} |
|
|
Напечатать слова "Hello world" 100 раз. int c;
c = 100; while ( c-- )
printf ( "Hello world\n" );
Понятие истины в Си растяжимо: истинно все, что не равно нулю. В частности, 100 - это истина. А выражение c– –, стоящее в условии (помните постфиксную форму инкремента?), вернет значение переменной с, а затем уменьшит его на единицу. При выполнении цикла в сотый раз условие вернет 1, а в переменной с окажется 0. После этого условие выполнится в 101-й раз, вернет 0, запишет в с –1, и, так как 0 – это ложь, цикл выполняться больше не будет.
5.5.2Цикл for
е1 – присваивание начального значения управляющей переменной. е2 – проверка выполнения условия продолжения цикла.
е3 – изменение значения управляющей переменной.
В выражениях е1, е2, е3 фигурирует специальная переменная, называемая управляющей. По ее значению устанавливается необходимость повторения цикла, либо выхода из него.
25
е2 и е3 перевычисляются при каждом проходе цикла for это цикл с переменными границами!
for наиболее универсальный цикл в языке Си (и в других алгоритмических языках).
Формат for ( [e1]; [e2]; [e3] ) S;
Эквивалентная схема e1;
while ( e2 )
{S; e3; }
Пример:
1. Дано: a[i], i=1...100. Найти сумму(a[i]>0) и сумму(a[i]<0). pol = otr = 0;
for ( i = 0; i<100; i++ ) {
if ( a[i]>0 ) |
pol+=a[i]; |
if ( a[i]<0 ) |
otr+=a[i]; |
}
2. Определить количество цифр натурального числа L. for ( k=0; L!=0; L/=10 )
k++;
Пример: for ( ; e2; ) |
S; |
while ( e2 ) S; |
for ( ; ; ) S; while ( 1 ) |
S; |
3. Найти 1–й отрицательный элемент массива. Если его нет, то 0. for (i=0; i<100 && a[i] > = 0; i++ ) ;
if ( i= =100 ) { y = 0; } else {y = a[i]; }
5.5.3Цикл do
Его особенность в том, что проверка условия происходит не перед выполнением тела цикла, а после него, поэтому тело цикла обязательно выполнится хотя бы один раз. Иногда это бывает полезно. В остальном, этот цикл сходен с while.
Формат do {
< оператор > ;
}while (e);
Эквивалентная схема label: <оператор>; if ( e ) goto label;
26
Пример:
Дано: a[i], i=1...100. Найти сумму(a[i]) и произведение(a[i]). sum = i = 0;
pr=1;
do { sum + = a[i]; pr*=a[i];
i++;
} while ( i<100 );
5.5.4Вложенные циклы.
Вкачестве <тела_цикла> в любом цикле может выступать другой цикл. Следует помнить только о составном операторе.
• Умножение матриц for ( i=0; i<m; i++ ){
for ( j=0; j<l; j++ ) { c[i][j] = 0;
for (k=0; k<n; k++ ) {
c[i][j] + = a[i][k]*b[k][j]; } } }
• |
Сортировка массива методом "пузырька" |
|
pr=1; |
|
|
while (pr){ |
|
|
|
pr=0; |
|
|
for ( i=0; i<n–1; i++ ) |
{ |
|
if (a[i]>a[i+1] ) |
{ |
|
b = a[i]; |
|
|
a[i] = a[i+1]; |
|
|
a[i+1] = b; |
|
} |
pr = 1; } |
} |
|
|
5.6 Управляемые переходы
5.6.1Оператор break
Break осуществляет немедленный безусловный выход из цикла, то есть переход на первый оператор, непосредственно следующий за циклом.
Формат |
break ; |
|
|
Эквивалентная схема |
|
|
|
for ( e1; e2; e3 ) { |
|
for ( e1; e2; e3 ) { |
|
............ |
|
|
............ |
if ( e4 ) break ; |
|
if ( e4 ) goto exit ; |
|
............ |
|
|
............ |
} |
|
|
} |
................ |
|
exit : |
... |
27
Пример:
Дано x[i], i=1...30. Найти длину 1–й подпоследовательности положительных элемен-
тов.
for ( pr = kol = i = 0; i<30; i++) { if (x[i] > 0) {
kol++; |
} |
pr = 1; |
if (x[i]<=0 && pr) break; }
5.6.2Оператор continue
Формат continue
Эквивалентная схема |
|
|
||
for ( e1; e2; e3 ) |
{ |
|
for ( e1; e2; e3 ) |
{ |
............ |
|
|
............ |
|
if ( e4 ) continue; |
|
|
if ( e4 ) goto next ; |
|
............ |
|
|
............ |
|
} |
next: |
; |
} |
|
|
|
|
|
|
ЗАМЕЧАНИЕ. Почти всегда можно обойтись.
for ( i=0; i<n; i++ ) { |
|
for ( i=0; i<n; i++ ) { |
|
|
if ( a[i]<=0 ) continue ; |
|
if ( a[i]>0 ) { /* Обработка a[i]>0 */ |
||
/* Обработка a[i]>0 */ … |
} |
… |
} |
} |
5.7 Оператор switch
Реализует ситуацию множественного выбора, когда в зависимости от значения переменной ( e ) выполняется одно из нескольких условий.
Формат
switch ( e ) {
case c_e1: [<оператор_1>;][break;] case c_e2: [<оператор_2>;][break;]
...................
case c_en: [<оператор_n>;][break;]
[default: <оператор_n+1>;]
}
Как работает эта конструкция? Как вы можете догадаться, она ищет строку "case значение_переменной_e" и исполняет участок кода от нее до конца блока switch или до зарезервированного слова break. Если соответствий не найдено, исполняется блок default.
Присутствие в формате break придает больше гибкости конструкции.
28
Еще одно замечание: в качестве меток case могут выступать только целочисленные константы. Поэтому если вам необходимо сравнивать значение с переменной или с дробной величиной - вам придется пользоваться конструкцией if.
Например: switch ( a ) { |
|
|
case 1: |
b = 5; // строка без break |
|
case 2: |
printf ( "a = 1 или a = 2\n" ); break; |
|
case 3: |
printf ( "a = 3\n" ); |
} |
Как он будет себя вести? Если a = 1, то переменная b получит значение 5, а затем будет выведена строка "a = 1 или a = 2". Если же a = 2, то будет выведена так же строка. Таким образом, одно действие включает в себя другое, при этом в коде нет повторяющихся участков.
Частным случаем может служить тот вариант, когда в ответ на несколько значений переменной предусмотрена одинаковая реакция. В таком случае достаточно поста-
вить несколько слов case подряд: |
|
|||
Например: |
switch (a) |
{ |
|
|
case 1: |
|
|
|
|
case 2: printf ("a = 1 или a = 2\n"); |
break; |
|||
case 3: |
|
|
|
|
case 4: printf ("a = 3 или a = 4\n"); |
break; |
|||
} |
|
|
|
|
Пример: |
|
|
|
|
switch ( symb ) |
{ |
|
|
|
case '+': <сложить>; |
break; |
|
|
|
case '–': <вычесть>; |
break; |
|
|
|
case '*': <умножить>; break; |
|
|
||
case '/': <разделить>; |
break; |
|
||
case '%': <найти остаток>; break; |
|
|||
default : <поместить в стек>; |
} |
|
5.8Основные операции с массивами и матрицами
1)Суммирование элементов одномерного массива a[i], i = 1,n. for ( s=i=0; i<n; i++ )
s += a[i];
2)Суммирование элементов матрицы a[i][j], i,j = 1,n.
for ( s=i=0; i<n; i++ ) |
{ |
for ( j=0; j<n; j++ ) |
|
s += a[i][j]; |
} |
3) Суммирование двух массивов (матриц) одинакового размера. for ( i=0; i<n; i++ ) {
for ( j=0; j<n; j++ )
c[i][j] = a[i][j]+b[i][j]; }
29
4) Вычислить сумму элементов каждой строки матрицы b[i][j], размером n×m. Результат записать в виде вектора d[i].
for ( i=0; i<n; i++ ) { s=0;
for ( j=0; j<n; j++ ) s += b[i][j]; d[i]=s; }
5) Выполнить транспонирование матрицы а[i][j], т.е. заменить строки матрицы ее столбцами, а столбцы строками.
for ( i=0; i<n; i++ ) { for ( j=0; j<m; j++)
b[i][j] = a[j][i]; }
Для квадратной матрицы. |
|
|
for ( i=0; i<n; i++) |
{ |
|
for ( j=i+1; j<n; j++) |
{ |
|
p=a[i][j]; |
|
|
a[i][j]=a[j][i]; } |
|
|
a[j][i] = p; |
} |
|
6) Умножить матрицу а[i][j], размером n×m, на матрицу b[i][j], размером k×m. Другими словами вычислить:
k
Cij=l∑1ail*bij; i=1,n; j=1,m;
=
for ( i=0; i<n; i++) { for ( j=0; j<m; j++ ){ s=0;
for ( l=0; l<k; l++ )
s += a[i][j]*b[l][j];
}
c[i][j] = s }
8)Удалить k-й элемент из массива а[i], размером n.
i=k,n–1 –сдвигаем хвост массива на одну позицию влево.
n = n–1; /*n– –*/ for ( i=k; i<n; i++) a[i] = a[i+1];
9)Включить в k-ю позицию массива элемент.
ai+1=ai |
i=n; n–1;…;k – передвигаем хвост массива на одну позицию вправо. |
Перемещение начинаем с конца, иначе весь хвост будет заполнен элементом a[k]. for (i=n; i>k; i– –)
a[i+1]=a[i];
a[k]=b;
30
n=n+1 /*n++*/
10) Включить в массив а[i], размером n элемент b. Сохранить упорядоченность массива по возрастанию.
i=0; |
|
|
met: if ( i>n ) |
{ |
|
a[i+1] = b; |
|
|
n=n+1; |
} |
|
if ( b >= a[i] ) |
{ |
|
i = i+1; |
|
|
goto met |
} |
|
for ( j=n; j>i; j– –) |
||
a[j+1]=a[j]; |
|
|
a[i]=b; |
|
|
n=n+1; |
/*n++*/ |
11) Удалить из матрицы строку с номером k. n=n–1; /*n– –*/
for ( i=k; i<n; i++ ) { for ( j=0; j<n; j++ ) b[i][j]=b[i+1][j]; }
12) Включить в матрицу строку, заданную вектором с[i].
for ( i=n; i>k; i– –) |
{ |
for (j=1; j<m; j++) |
|
b[i+1][j] = b[i][j]; |
} |
for ( j=0; j<m; j++) |
|
b[k][j]=c[j]; |
|
n++; |
|
13) Перестановка строк матрицы с номерами i и j с использованием вспомогатель-
ной переменная.
for (k=0; k<m; k++) { p=a[i][k]; a[i][k]=a[j][k]; a[j][k]=p; }
Используется вспомогательный массив.
for ( k=0; k<m; k++ ) |
{ |
c[k]=a[i][k]; |
|
for (k=0; k<m; k++) |
{ |
a[i][k]=a[j][k];} |
|
a[j][k]=c[k]; |
|
31
Глава 6. ВВОД – ВЫВОД данных
Ввод–вывод – это передача данных между переменными программы(ОП) и внешней памятью(ВП).
В Си предусмотрен только форматный обмен. <stdio.h> – файл прототипа.
Ввод:
клавиатура |
|
|
буфер |
|
|
переменная в памяти |
|
||||
|
|
|
|
|
|||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
переменная в памяти |
|
|
буфер |
|
|
Экран|принтер|файл |
|
||||
|
|
|
|
||||||||
|
|
|
|
|
|
|
|
|
|
|
|
Вывод:
Буфер имеет конечный размер и считывание из него происходит только после нажатия клавиши <Enter>.
Формат основных функций
{scanf | printf}(<управляющая строка>[, <список_данных>] );
<управляющая строка> := “[<произвольный текст>][<спецификации>]” <список_данных> := <имя_переменной> [ , <имя_переменной> [, …] ]
Элементы списка данных scanf( ) – адреса переменных, значения которых задаются, поэтому необходимо использовать операцию &(нахождение адреса).
Возвращаемые значения: printf ( )– число выводимых символов (байтов), scanf( ) – число введенных скалярных значений.
6.1 Управляющая строка
Содержит спецификации для функций ввода-вывода. Формат ОДНОЙ спецификации
% |
[ <флаги> ] [W] [. D][l] <тип> |
% |
[признаки] [ширина_поля] [ .точность ] [модификатор] с_n. |
Флаги для printf (для scanf не используются):
–данное прижимается к левой границе поля вывода;
+число ВСЕГДА со знаком (актуально для положительных данных, в которых по умолчанию знак опускают, отрицательные всегда изображаются со знаком).
W – размер поля данного в символах (байтах).
D – обычно характеризует точность представления значения при выводе, ПРИ ВВОДЕ НЕ ИСПОЛЬЗУЕТСЯ (количество цифр, которые необходимо вывести справа от десятичной точки для типов float и double).
Модификаторы:
l – модификатор "длинных"(long для целых, double для чисел с плавающей точкой), указывает, что соответствующий элемент имеет тип long.
32
h – модификатор “коротких”, указывает, что соответствующий элемент имеет тип short int.
6.1.1Спецификация d (целые десятичные цифры)
ВВОД Формат спецификации
% [W] [l] d
W – максимальное число считываемых символов. l – модификатор для long.
Пример.
Внешнее представление |
|
Спецификация |
Значение в памяти |
|
||
165<пробел> |
|
d |
165 |
|
||
+165<Enter> |
|
d |
165 |
|
||
165 |
|
|
2 d |
16 |
|
|
165 |
|
|
1 d |
1 |
|
|
431921 |
|
|
l d |
431921 |
|
|
– 431921 |
|
4 l d |
– 431 |
|
||
+ 431921<пробел> |
|
10 l d |
431921 |
|
||
ВЫВОД Формат спецификации |
|
|
||||
% [<флаги>] [W] [ .D] [l] d |
|
|
|
|
||
D – минимальное число выводимых символов. |
|
|
||||
Пример. |
|
|
|
|
||
Значение в памяти |
|
Спецификация |
|
Внешнее представление |
||
2475 |
|
|
d |
|
2475 |
|
2475 |
|
|
+ d |
|
+ 2475 |
|
2475 |
|
|
<пробел> d |
|
<пробел> 2475 |
|
– 2475 |
|
d |
|
–2475 |
||
– 2475 |
|
+d |
|
–2475 |
||
–2475 |
|
<пробел>d |
|
–2475 |
||
–2475 |
|
3d |
|
–2475 |
||
2475 |
|
|
10d |
|
_ _ _ _ _ _ 2475 |
|
2475 |
|
|
+10d |
|
_ _ _ _ _+2475 |
|
2475 |
|
|
–10d |
|
2475_ _ _ _ _ _ |
|
2475 |
|
|
–+10d |
|
+2475_ _ _ _ _ |
|
2475 |
|
|
10.5d |
|
– – – – – 02475 |
|
–24 |
|
10.5d |
|
_ _ _ _ – 00012 |
||
–24 |
|
.5d |
|
–00024 |
||
3 |
|
|
5.0d |
|
_ _ _ _ 3 |
|
–478126 |
|
10ld |
|
_ _ _–478126 |
||
–478126 |
|
–10ld |
|
–478126_ _ _ |
||
478126 |
|
|
+–10ld |
|
+478126_ _ _ |
|
6.1.2.Спецификация f (вещественные числа с плавающей точкой)
ВВОД Формат спецификации
% [W] [l] f
33