- •Глава 1 элементы языка
- •Вывод: Пробелы употреблять везде, где это допустимо и улучшает читабельность программы.
- •Введение в си
- •Глава 2 элементы данных
- •Глава 3 массивы и структуры
- •Глава 4 операции и выражения
- •Глава 5 основные операторы
- •Формат: ;
- •Глава 6. Ввод – вывод данных
- •Форма представления одного данного
- •6.2 Функции getchar(), putchar(), getch()
- •Глава 7. Блоки и процедуры
- •Глава 8 Препроцессор
- •Вычисление квадратичной формы
- •Глава 9 Символьная информация и строки
- •9.3 Строки или строковые константы
- •Глава 10 фAйлы
Формат: ;
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;
Составной оператор
Употребляется везде, где стандарт языка Си предусматривает один оператор, а для решении задачи требуется несколько.
Формат { <оператор>; [<оператор>;]... }
Пример:
Задача: x = max (a, b) y = min(a, b)
if ( a>b ) {
x = a;
y = b; }
else { x = b;
y = a; }
Циклы
Цикл 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 – это ложь, цикл выполняться больше не будет.
Цикл for
е1 – присваивание начального значения управляющей переменной.
е2 – проверка выполнения условия продолжения цикла.
е3 – изменение значения управляющей переменной.
В выражениях е1, е2, е3 фигурирует специальная переменная, называемая управляющей. По ее значению устанавливается необходимость повторения цикла, либо выхода из него.
е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]; }
Цикл do
Его особенность в том, что проверка условия происходит не перед выполнением тела цикла, а после него, поэтому тело цикла обязательно выполнится хотя бы один раз. Иногда это бывает полезно. В остальном, этот цикл сходен с while.
Формат
do {
< оператор > ;
} while (e);
Эквивалентная схема
label: <оператор>;
if ( e ) goto label;
Пример:
Дано: 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 );
Вложенные циклы.
В качестве <тела_цикла> в любом цикле может выступать другой цикл. Следует помнить только о составном операторе.
Умножение матриц
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; } }
}
Управляемые переходы
Оператор break
Break осуществляет немедленный безусловный выход из цикла, то есть переход на первый оператор, непосредственно следующий за циклом.
Формат break ;
Эквивалентная схема
for ( e1; e2; e3 ) { for ( e1; e2; e3 ) {
............ ............
if ( e4 ) break ; if ( e4 ) goto exit ;
............ ............
} }
................ exit : ...
Пример:
Дано 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; }
Оператор 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 */ … } … } }
Оператор 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 придает больше гибкости конструкции.
Еще одно замечание: в качестве меток 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 : <поместить в стек>; }
Основные операции с массивами и матрицами
Суммирование элементов одномерного массива a[i], i = 1,n.
for ( s=i=0; i<n; i++ )
s += a[i];
Суммирование элементов матрицы a[i][j], i,j = 1,n.
for ( s=i=0; i<n; i++ ) {
for ( j=0; j<n; j++ )
s += a[i][j]; }
Суммирование двух массивов (матриц) одинакового размера.
for ( i=0; i<n; i++ ) {
for ( j=0; j<n; j++ )
c[i][j] = a[i][j]+b[i][j]; }
Вычислить сумму элементов каждой строки матрицы b[i][j], размером nm. Результат записать в виде вектора d[i].
for ( i=0; i<n; i++ ) {
s=0;
for ( j=0; j<n; j++ )
s += b[i][j];
d[i]=s; }
Выполнить транспонирование матрицы а[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; }
Умножить матрицу а[i][j], размером nm, на матрицу b[i][j], размером km. Другими словами вычислить:
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 }
Удалить k-й элемент из массива а[i], размером n.
i=k,n–1 –сдвигаем хвост массива на одну позицию влево.
n = n–1; /*n– –*/
for ( i=k; i<n; i++)
a[i] = a[i+1];
Включить в k-ю позицию массива элемент.
i=n; n–1;…;k – передвигаем хвост массива на одну позицию вправо. Перемещение начинаем с конца, иначе весь хвост будет заполнен элементом a[k].
for (i=n; i>k; i– –)
a[i+1]=a[i];
a[k]=b;
n=n+1 /*n++*/
Включить в массив а[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++*/
Удалить из матрицы строку с номером k.
n=n–1; /*n– –*/
for ( i=k; i<n; i++ ) {
for ( j=0; j<n; j++ )
b[i][j]=b[i+1][j]; }
Включить в матрицу строку, заданную вектором с[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++;
Перестановка строк матрицы с номерами 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];