Программирование на языке Си Часть II 1.МассивыМассивы 2.Максимальный элемент массиваМаксимальный элемент массива 3.Обработка массивовОбработка массивов.

Презентация:



Advertisements
Похожие презентации
1 Программирование на языке Паскаль Файлы с последовательным доступом. Кулебякин В.В.
Advertisements

Строки Алтайский государственный университет Математический факультет Кафедра информатики Барнаул 2013.
1 Программирование на языке Паскаль Тема: Файлы. Integer, Real, Boolean, Character, String, Text.
Программирование на языке Си Часть II Тема 1. Массивы Учитель информатики: Корогод В.А.
1 Программирование на языке Паскаль Тема 4. Сортировка массивов.
К. Поляков, Программирование на алгоритмическом языке. Часть II Тема 6. Файлы.
К. Поляков, Программирование на алгоритмическом языке. Часть II Тема 4. Символьные строки.
Урок 2. Информационные процессы в обществе и природе.
Приложение 1 к решению Совета депутатов города Новосибирска от Масштаб 1 : 5000.
ОДНОМЕРНЫЕ МАССИВЫ. РАБОТА С ЭЛЕМЕНТАМИ СТРУКТУРИРОВАННЫЕ ТИПЫ ДАННЫХ.
Приложение 1 к решению Совета депутатов города Новосибирска от _____________ ______ Масштаб 1 : 5000.
К. Поляков, Программирование на алгоритмическом языке. Часть III 1.Обработка массивовОбработка массивов 2.Сортировка.
1 Программирование на языке Паскаль Часть II Символьные строки.
Программирование на языке Паскаль Часть II Тема 1. Массивы.
Алгоритмы сортировки. 2 Сортировка Сортировка – это расстановка элементов массива в заданном порядке (по возрастанию, убыванию, последней цифре, сумме.
Программирование на языке Паскаль Массивы.
Масштаб 1 : Приложение 1 к решению Совета депутатов города Новосибирска от _____________ ______.
К.Ю. Поляков, Е.А. Ерёмин, 2013 Программирование на языке Паскаль § 64. Сортировка 1.
Язык программирования Pascal Массивы А. Жидков. Массивы Массив – поименованный набор однотипных элементов, каждый из которых имеет свой номер, (индекс).
К. Поляков, Программирование на алгоритмическом языке. Часть II 1.МассивыМассивы 2.Максимальный элемент массиваМаксимальный.
Транксрипт:

Программирование на языке Си Часть II 1.МассивыМассивы 2.Максимальный элемент массиваМаксимальный элемент массива 3.Обработка массивовОбработка массивов 4.Сортировка массивовСортировка массивов 5.Поиск в массивеПоиск в массиве 6.Массивы в процедурах и функцияхМассивы в процедурах и функциях © К.Ю. Поляков, Практикум (моделирование)Практикум (моделирование) 8.Символьные строкиСимвольные строки 9.Рекурсивный переборРекурсивный перебор 10.МатрицыМатрицы 11.ФайлыФайлы

Программирование на языке Си Часть II Тема 1. Массивы © К.Ю. Поляков,

3 Массивы Массив – это группа однотипных элементов, имеющих общее имя и расположенных в памяти рядом. Особенности: все элементы имеют один тип весь массив имеет одно имя все элементы расположены в памяти рядом Примеры: список учеников в классе квартиры в доме школы в городе данные о температуре воздуха за год

4 Массивы A A массив НОМЕР элемента массива (ИНДЕКС) НОМЕР элемента массива (ИНДЕКС) A[0] A[1] A[2] A[3] A[4] ЗНАЧЕНИЕ элемента массива A[2] НОМЕР (ИНДЕКС) элемента массива: 2 ЗНАЧЕНИЕ элемента массива: 15 НУЛЯ Нумерация элементов массива в Си начинается с НУЛЯ! !

5 Объявление массивов Зачем объявлять? определить имя массива определить тип массива определить число элементов выделить место в памяти Пример: Размер через константу: имя размер массива (количество элементов) тип элементов тип элементов int A [ ]; const int N = 5; N int A [ 5 ];

6 Объявление массивов Еще примеры: int X[10], Y[10]; float zz, A[20]; char s[80]; int X[10], Y[10]; float zz, A[20]; char s[80]; С присвоением начальных значений: int A[4] = { 8, -3, 4, 6 }; float B[2] = { 1. }; char C[3] = { 'A', '1', 'Ю' }; int A[4] = { 8, -3, 4, 6 }; float B[2] = { 1. }; char C[3] = { 'A', '1', 'Ю' }; остальные нулевые! Если начальные значения не заданы, в ячейках находится «мусор»! !

7 Что неправильно? int N = 10; float A[N]; int N = 10; float A[N]; const int int X[4.5]; int A[10]; A[10] = 0; int A[10]; A[10] = 0; float X[5]; int n = 1; X[n-2] = 4.5; X[n+8] = 12.; float X[5]; int n = 1; X[n-2] = 4.5; X[n+8] = 12.; выход за границы массива (стираются данные в памяти) выход за границы массива (стираются данные в памяти) int X[4]; X[2] = 4.5; int X[4]; X[2] = 4.5; дробная часть отбрасывается (ошибки нет) дробная часть отбрасывается (ошибки нет) float B[2] = { 1., 3.8, 5.5 }; int A[2] = { 1, 3.8 }; float

8 Массивы Объявление: Ввод с клавиатуры: Поэлементные операции: Вывод на экран: const int N = 5; int A[N], i; const int N = 5; int A[N], i; printf("Введите 5 элементов массива:\n"); for( i=0; i < N; i++ ) { printf ("A[%d] = ", i ); scanf ("%d", & A[i] ); } printf("Введите 5 элементов массива:\n"); for( i=0; i < N; i++ ) { printf ("A[%d] = ", i ); scanf ("%d", & A[i] ); } A[0] = A[1] = A[2] = A[3] = A[4] = for( i=0; i < N; i++ ) A[i] = A[i]*2; printf("Результат:\n"); for( i=0; i < N; i++ ) printf("%4d", A[i]); printf("Результат:\n"); for( i=0; i < N; i++ ) printf("%4d", A[i]); Результат:

9 Программа #include main() { const int N = 5; int A[N], i; // ввод элементов массива // обработка массива // вывод результата getch(); } #include main() { const int N = 5; int A[N], i; // ввод элементов массива // обработка массива // вывод результата getch(); } Задача: ввести с клавиатуры массив из 5 элементов, умножить все элементы на 2 и вывести полученный массив на экран. на предыдущих слайдах

10 Задания «4»: Ввести c клавиатуры массив из 5 элементов, найти среднее арифметическое всех элементов массива. Пример: Введите пять чисел: среднее арифметическое «5»: Ввести c клавиатуры массив из 5 элементов, найти минимальный из них. Пример: Введите пять чисел: минимальный элемент 3 При изменении константы N остальная программа не должна изменяться! !

Программирование на языке Си Часть II Тема 2. Максимальный элемент массива © К.Ю. Поляков,

12 Максимальный элемент Задача: найти в массиве максимальный элемент. Алгоритм: Псевдокод: // считаем, что элемент A[0] – максимальный for ( i=1; i < N; i++ ) if ( A[i] > максимального ) // запомнить новый максимальный элемент A[i] // считаем, что элемент A[0] – максимальный for ( i=1; i < N; i++ ) if ( A[i] > максимального ) // запомнить новый максимальный элемент A[i] Почему цикл от i=1 ? ?

13 Максимальный элемент max = A[0]; // пока A[0]– максимальный iMax = 0; for ( i=1; i < N; i++ ) // проверяем остальные if ( A[i] > max ) { // нашли новый max = A[i]; // запомнить A[i] iMax = i; // запомнить i } max = A[0]; // пока A[0]– максимальный iMax = 0; for ( i=1; i < N; i++ ) // проверяем остальные if ( A[i] > max ) { // нашли новый max = A[i]; // запомнить A[i] iMax = i; // запомнить i } Дополнение: как найти номер максимального элемента? Как упростить? ? По номеру элемента iMax всегда можно найти его значение A[iMax]. Поэтому везде меняем max на A[iMax] и убираем переменную max. A[iMax]

14 Заполнение случайными числами RAND_MAX – максимальное случайное целое число (обычно RAND_MAX = 32767) Случайное целое число в интервале [0,RAND_MAX] x = rand(); // первое число x = rand(); // уже другое число Установить начальное значение последовательности: srand ( 345 ); // начнем с 345 #include // случайные числа

15 Целые числа в заданном интервале Целые числа в интервале [0,N-1] : Примеры: Целые числа в интервале [a,b] : int random(int N) { return rand()% N; } int random(int N) { return rand()% N; } x = random ( 100 ); // интервал [0,99] x = random ( z ); // интервал [0,z-1] x = random ( 100 ); // интервал [0,99] x = random ( z ); // интервал [0,z-1] x = random ( z ) + a; // интервал [a,z-1+a] x = random (b – a + 1) + a; // интервал [a,b] x = random ( z ) + a; // интервал [a,z-1+a] x = random (b – a + 1) + a; // интервал [a,b]

16 Заполнение случайными числами #include main() { const int N = 10; int A[N], i; printf("Исходный массив:\n"); for (i = 0; i < N; i++ ) { A[i] = random(100) + 50; printf("%4d", A[i]); }... } #include main() { const int N = 10; int A[N], i; printf("Исходный массив:\n"); for (i = 0; i < N; i++ ) { A[i] = random(100) + 50; printf("%4d", A[i]); }... } int random(int N) { return rand() % N; } int random(int N) { return rand() % N; } функция выдает случайное число от 0 до N-1 Какой интервал? ?

17 Программа #include main() { const int N = 5; int A[N], i, iMax; // заполнить случайными числами [100,150] // найти максимальный элемент и его номер printf("\nМаксимальный элемент A[%d] = %d", iMax, A[iMax]); getch(); } на предыдущих слайдах const Что дает const ? ?

18 Задания «4»: Заполнить массив из 10 элементов случайными числами в интервале [ ] и найти в нем максимальный и минимальный элементы и их номера. Пример: Исходный массив: максимальный a[4]=10 минимальный a[8]=-10 «5»: Заполнить массив из 10 элементов случайными числами в интервале [ ] и найти в нем два максимальных элемента и их номера. Пример: Исходный массив: максимальные a[4]=10, a[7]=8

Программирование на языке Си Часть II Тема 3. Обработка массивов © К.Ю. Поляков,

20 Реверс массива Задача: переставить элементы массива в обратном порядке (выполнить инверсию). Алгоритм: поменять местами A[0] и A[N-1], A[1] и A[N-2], … Псевдокод: 35…97 79…53 01…N-2N-1 01…N-2N-1 for ( i = 0; i < N; i++ ) // поменять местами A[i] и A[N-1-i] for ( i = 0; i < N; i++ ) // поменять местами A[i] и A[N-1-i] сумма индексов N-1 Что неверно? ? ; i++ ) N / 2N / 2

21 Как переставить элементы? Задача: поменять местами содержимое двух чашек. Задача: поменять местами содержимое двух ячеек памяти ? ? x y c c = x; x = y; y = c; c = x; x = y; y = c; x = y; y = x; x = y; y = x; Можно ли обойтись без c ? ?

22 Программа main() { const int N = 10; int A[N], i, c; // заполнить массив // вывести исходный массив for ( i = 0; i < N/2; i++ ) { c = A[i]; A[i] = A[N-1-i]; A[N-1-i] = c; } // вывести полученный массив }

23 Задания «4»: Заполнить массив из 10 элементов случайными числами в интервале [ ] и выполнить инверсию отдельно для 1-ой и 2-ой половин массива. Пример: Исходный массив: Результат: «5»: Заполнить массив из 12 элементов случайными числами в интервале [ ] и выполнить инверсию для каждой трети массива. Пример: Исходный массив: Результат:

24 Циклический сдвиг Задача: сдвинуть элементы массива влево на 1 ячейку, первый элемент становится на место последнего. Алгоритм: A[0]=A[1]; A[1]=A[2];… A[N-2]=A[N-1]; Цикл: 3581… …N-2N-1 581…973 for ( i = 0; i < N-1; i ++) A[i] = A[i+1]; Что неверно? ? почему не N ?

25 Программа main() { const int N = 10; int A[N], i, c; // заполнить массив // вывести исходный массив c = A[0]; for ( i = 0; i < N-1; i ++) A[i] = A[i+1]; A[N-1] = c; // вывести полученный массив }

26 Задания «4»: Заполнить массив из 10 элементов случайными числами в интервале [ ] и выполнить циклический сдвиг ВПРАВО. Пример: Исходный массив: Результат: «5»: Заполнить массив из 12 элементов случайными числами в интервале [ ] и выполнить циклический сдвиг ВПРАВО на 4 элемента. Пример: Исходный массив: Результат:

Программирование на языке Си Часть II Тема 4. Сортировка массивов © К.Ю. Поляков,

28 Сортировка Сортировка – это расстановка элементов массива в заданном порядке (по возрастанию, убыванию, последней цифре, сумме делителей, …). Задача: переставить элементы массива в порядке возрастания. Алгоритмы: простые и понятные, но неэффективные для больших массивов метод пузырька метод выбора сложные, но эффективные «быстрая сортировка» (Quick Sort) сортировка «кучей» (Heap Sort) сортировка слиянием пирамидальная сортировка сложность O(N 2 ) сложность O(N·logN) время N O(N 2 ) O(N·logN)

29 Метод пузырька Идея – пузырек воздуха в стакане воды поднимается со дна вверх. Для массивов – самый маленький («легкий») элемент перемещается вверх («всплывает») начиная снизу, сравниваем два соседних элемента; если они стоят «неправильно», меняем их местами за 1 проход по массиву один элемент (самый маленький) становится на свое место ый проход 2-ой проход 3-ий проход Для сортировки массива из N элементов нужен N-1 проход (достаточно поставить на свои места N-1 элементов).

30 Программа (1-ый проход) 5 2 … … N-2 N-1 сравниваются пары A[N-2] и A[N-1], A[N-3] и A[N-2] … A[0] и A[1] A[j] и A[j+1] for( j = N-2; j >= 0 ; j-- ) if ( A[j] > A[j+1] ) { c = A[j]; A[j] = A[j+1]; A[j+1] = c; } for( j = N-2; j >= 0 ; j-- ) if ( A[j] > A[j+1] ) { c = A[j]; A[j] = A[j+1]; A[j+1] = c; } 0

31 Программа (следующие проходы) 2-ой проход A[0] уже на своем месте! ! for ( j = N-2; j >= 1 ; j-- ) if ( A[j] > A[j+1] ) { c = A[j]; A[j] = A[j+1]; A[j+1] = c; } for ( j = N-2; j >= 1 ; j-- ) if ( A[j] > A[j+1] ) { c = A[j]; A[j] = A[j+1]; A[j+1] = c; } 1 (i+1) -ый проход for ( j = N-2; j >= i ; j-- )... for ( j = N-2; j >= i ; j-- )... i 1 5 … … N-2 N-1

32 Программа main() { const int N = 10; int A[N], i, j, c; // заполнить массив // вывести исходный массив for (i = 0; i < N-1; i ++){ for (j = N-2; j >= i ; j --) if ( A[j] > A[j+1] ) { с = A[j]; A[j] = A[j+1]; A[j+1] = с; } } // вывести полученный массив } Почему цикл для i < N-1, а не i < N ? ? элементы выше A[i] уже поставлены i меняем A[j] и A[j+1]

33 Метод пузырька с флажком Идея – если при выполнении метода пузырька не было обменов, массив уже отсортирован и остальные проходы не нужны. Реализация: переменная-флаг, показывающая, был ли обмен; если она равна 0, то выход. do { flag = 0; // сбросить флаг for (j = N-2; j >= 0; j --) if ( A[j] > A[j+1] ) { с = A[j]; A[j] = A[j+1]; A[j+1] = с; flag = 1; // поднять флаг } while ( flag ); // выход при flag = 0 do { flag = 0; // сбросить флаг for (j = N-2; j >= 0; j --) if ( A[j] > A[j+1] ) { с = A[j]; A[j] = A[j+1]; A[j+1] = с; flag = 1; // поднять флаг } } while ( flag ); // выход при flag = 0 flag = 0; flag = 1; ( flag ); int flag; Как улучшить? ?

34 Метод пузырька с флажком i = 0; do { flag = 0; // сбросить флаг for ( j = N-2; j >= i ; j -- ) if ( A[j] > A[j+1] ) { с = A[j]; A[j] = A[j+1]; A[j+1] = с; flag = 1; // поднять флаг } i ++; } while ( flag ); // выход при flag = 0 i = 0; do { flag = 0; // сбросить флаг for ( j = N-2; j >= i ; j -- ) if ( A[j] > A[j+1] ) { с = A[j]; A[j] = A[j+1]; A[j+1] = с; flag = 1; // поднять флаг } i ++; } while ( flag ); // выход при flag = 0 i = 0; i i ++;

35 Метод выбора Идея: найти минимальный элемент и поставить на первое место (поменять местами с A[0] ) из оставшихся найти минимальный элемент и поставить на второе место (поменять местами с A[1] ), и т.д

36 Метод выбора N for( i = 0; i < N-1 ; i ++ ) { nMin = i ; for ( j = i+1; j < N; j ++) if( A[j] < A[nMin] ) nMin = j; if( nMin != i ) { c = A[i]; A[i] = A[nMin]; A[nMin] = c; } } N-1 нужно N-1 проходов поиск минимального от A[i] до A[N-1] если нужно, переставляем Можно ли убрать if ? ? i+1 i

37 Задания «4»: Заполнить массив из 10 элементов случайными числами в интервале [0..100] и отсортировать его по последней цифре. Пример: Исходный массив: Результат: «5»: Заполнить массив из 10 элементов случайными числами в интервале [0..100] и отсортировать первую половину по возрастанию, а вторую – по убыванию. Пример: Исходный массив: Результат:

38 Формирование массива по условию Задача – найти в массиве элементы, удовлетворяющие некоторому условию (например, отрицательные), и скопировать их в другой массив. Примитивное решение: const int N = 5; int A[N], B[N]; // здесь заполнить массив A for( i = 0; i < N; i ++ ) if( A[i] < 0 ) B[i] = A[i]; const int N = 5; int A[N], B[N]; // здесь заполнить массив A for( i = 0; i < N; i ++ ) if( A[i] < 0 ) B[i] = A[i]; ? ? ? ? ? A B -5-5 выбранные элементы не рядом, не в начале массива непонятно, как с ними работать

39 Формирование массива по условию Решение: ввести счетчик найденных элементов count, очередной элемент ставится на место B[count]. int A[N], B[N], count = 0; // здесь заполнить массив A for( i = 0; i < N; i ++ ) if( A[i] < 0 ) { B[count] = A[i]; count ++; } // вывод массива B for( i = 0; i < count; i ++ ) printf("%d\n", B[i]); int A[N], B[N], count = 0; // здесь заполнить массив A for( i = 0; i < N; i ++ ) if( A[i] < 0 ) { B[count] = A[i]; count ++; } // вывод массива B for( i = 0; i < count; i ++ ) printf("%d\n", B[i]); ? ? ? ? ? A B -5-5 count

40 Задания «4»: Заполнить массив случайными числами и отобрать в другой массив все числа, у которых вторая с конца цифра (число десятков) – ноль. Пример: Исходный массив: Результат: «5»: Заполнить массив случайными числами и выделить в другой массив все числа, которые встречаются более одного раза. Пример: Исходный массив: Результат: 1 2

Программирование на языке Си Часть II Тема 5. Поиск в массиве © К.Ю. Поляков,

42 Поиск в массиве Задача – найти в массиве элемент, равный X, или установить, что его нет. Решение: для произвольного массива: линейный поиск (перебор) недостаток: низкая скорость Как ускорить? – заранее подготовить массив для поиска как именно подготовить? как использовать «подготовленный» массив?

43 Линейный поиск nX = -1; for ( i = 0; i < N; i ++) if ( A[i] == X ) { nX = i; break; //выход из цикла } nX = -1; for ( i = 0; i < N; i ++) if ( A[i] == X ) { nX = i; break; //выход из цикла } Что можно улучшить? ? Улучшение: после того, как нашли X, выходим из цикла. break; nX = -1; // пока не нашли... for ( i = 0; i < N; i ++) // цикл по всем элементам if ( A[i] == X ) // если нашли, то... nX = i; //... запомнили номер if (nX < 0) printf("Не нашли...") else printf("A[%d]=%d", nX, X); nX – номер нужного элемента в массиве

44 Двоичный поиск X = 7X = 7 X < 8X < X > 4X > X > 6 1.Выбрать средний элемент A[c] и сравнить с X. 2.Если X = A[c], нашли (выход). 3.Если X < A[c], искать дальше в первой половине. 4.Если X > A[c], искать дальше во второй половине.

45 Двоичный поиск Почему нельзя while ( R > L ) { … } ? ? 0LcR N-1 nX = -1; L = 0; R = N-1; // границы: ищем от A[0] до A[N-1] while ( R >= L ){ c = (R + L) / 2; if (X = = A[c]) { nX = c; break; } if (X < A[c]) R = c - 1; if (X > A[c]) L = c + 1; } if (nX < 0) printf("Не нашли..."); else printf("A[%d]=%d", nX, X); номер среднего элемента если нашли … выйти из цикла сдвигаем границы >

46 Сравнение методов поиска ЛинейныйДвоичный подготовканетотсортировать число шагов N = 222 N = N = N= N N log 2 N+1

47 Задания «4»: Написать программу, которая сортирует массив ПО УБЫВАНИЮ и ищет в нем элемент, равный X (это число вводится с клавиатуры). Использовать двоичный поиск. «5»: Написать программу, которая считает среднее число шагов в двоичном поиске для массива из 32 элементов в интервале [0,100]. Для поиска использовать 1000 случайных чисел в этом же интервале.

Программирование на языке Си Часть II Тема 6. Массивы в процедурах и функциях © К.Ю. Поляков,

49 Массивы в процедурах Задача: составить процедуру, которая переставляет элементы массива в обратном порядке. void Reverse ( int A[], int N ) { int i, c; for ( i = 0; i < N/2; i ++ ) { c = A[i]; A[i] = A[N-1-i]; A[N-1-i] = c; } void Reverse ( int A[], int N ) { int i, c; for ( i = 0; i < N/2; i ++ ) { c = A[i]; A[i] = A[N-1-i]; A[N-1-i] = c; } } int A[] параметр- массив размер массива

50 Массивы как параметры процедур Особенности: при описании параметра-массива в заголовке функции его размер не указывается (функция работает с массивами любого размера) размер массива надо передавать как отдельный параметр в процедура передается адрес исходного массива: все изменения, сделанные в процедуре влияют на массив в основной программе Почему здесь размер не обязателен? ?

51 Массивы в процедурах void Reverse ( int A[], int N ) {... } main() { int A[10]; // здесь надо заполнить массив Reverse ( A, 10 ); // весь массив // Reverse ( A, 5 ); // первая половина // Reverse ( A+5, 5 ); // вторая половина } void Reverse ( int A[], int N ) {... } main() { int A[10]; // здесь надо заполнить массив Reverse ( A, 10 ); // весь массив // Reverse ( A, 5 ); // первая половина // Reverse ( A+5, 5 ); // вторая половина } A или &A[0] это адрес начала массива в памяти A+5 или &A[5]

52 Задания «4»: Написать процедуру, которая сортирует массив по возрастанию, и показать пример ее использования. «5»: Написать процедуру, которая ставит в начало массива все четные элементы, а конец – все нечетные.

53 Массивы в функциях Задача: составить функцию, которая находит сумму элементов массива. int Sum ( int A[], int N ) { int i, sum = 0; for ( i = 0; i < N; i ++ ) sum += A[i]; return sum; } int Sum ( int A[], int N ) { int i, sum = 0; for ( i = 0; i < N; i ++ ) sum += A[i]; return sum; } результат – целое число int A[] параметр- массив размер массива

54 Массивы в процедурах и функциях int Sum ( int A[], int N ) {... } main() { int A[10], sum, sum1, sum2; // заполнить массив sum = Sum ( A, 10 ); // весь массив sum1 = Sum ( A, 5 ); // первая половина sum2 = Sum ( A+5, 5 ); // вторая половина... } int Sum ( int A[], int N ) {... } main() { int A[10], sum, sum1, sum2; // заполнить массив sum = Sum ( A, 10 ); // весь массив sum1 = Sum ( A, 5 ); // первая половина sum2 = Sum ( A+5, 5 ); // вторая половина... }

55 Задания «4»: Написать функцию, которая находит максимальный элемент в массиве. «5»: Написать логическую функцию, которая определяет, верно ли, что среди элементов массива есть два одинаковых. Если ответ «да», функция возвращает 1; если ответ «нет», то 0. Подсказка: для отладки удобно использовать массив из 5 элементов, задаваемых вручную: const int N = 5; int A[N] = { 1, 2, 3, 3, 4 }; const int N = 5; int A[N] = { 1, 2, 3, 3, 4 };

Программирование на языке Си Часть II Тема 7. Практикум (моделирование) © К.Ю. Поляков,

57 Моделирование кипения воды Задача: Построить компьютерную модель кипения воды. Хранение данных: координаты (центров) пузырьков хранятся в массивах X и Y : X[i], Y[i] – координаты центра пузырька с номером i.

58 Структура программы #include const int N = 100; int X[N], Y[N], r = 3; void Init (); // начальное положение void Draw ( int color ); // рисуем, стираем void Sdvig ( int dy ); // летят вверх void Zamena (); // ушли, пришли main() { initwindow (600, 400);... // основная часть программы closegraph(); }... // здесь сами процедуры глобальные константы и переменные объявления процедур

59 Основная программа Init(); // начальная расстановка while ( 1 ) // зацикливание ??? { Draw ( YELLOW ); // рисуем все пузырьки delay ( 10 ); // ждем 10 мс Draw ( BLACK ); // стираем все пузырьки Sdvig ( 4 ); // вверх на 4 пикселя Zamena(); // если за пределами экрана… } Init(); // начальная расстановка while ( 1 ) // зацикливание ??? { Draw ( YELLOW ); // рисуем все пузырьки delay ( 10 ); // ждем 10 мс Draw ( BLACK ); // стираем все пузырьки Sdvig ( 4 ); // вверх на 4 пикселя Zamena(); // если за пределами экрана… } if ( kbhit() ) if ( getch() == 27 ) break; if ( kbhit() ) if ( getch() == 27 ) break; выход по Esc (код 27)

60 Процедура Init void Init() { int i; for ( i = 0; i < N; i ++ ) { X[i] = random( *r) + r; Y[i] = random( *r) + r; } void Init() { int i; for ( i = 0; i < N; i ++ ) { X[i] = random( *r) + r; Y[i] = random( *r) + r; } Начальная случайная расстановка: r Интервал для x: [r, 600-r] 400 Интервал для y: [r, 400-r] X[i] = random( *r) + r; Y[i] = random( *r) + r;

61 Процедуры Draw, Sdvig Рисование и стирание: void Draw ( int color ) { int i; setcolor ( color ); for ( i = 0; i < N; i ++ ) circle ( X[i], Y[i], r ); } void Draw ( int color ) { int i; setcolor ( color ); for ( i = 0; i < N; i ++ ) circle ( X[i], Y[i], r ); } Сдвиг вверх: void Sdvig ( int dy ) { int i; for ( i = 0; i < N; i ++ ) Y[i] -= dy; } void Sdvig ( int dy ) { int i; for ( i = 0; i < N; i ++ ) Y[i] -= dy; }

62 Процедура Zamena Замена вышедших за границы экрана: 400 void Zamena () { int i; for ( i = 0; i < N; i ++ ) if ( Y[i] < r ) { X[i] = random( *r) + r; Y[i] = r; } void Zamena () { int i; for ( i = 0; i < N; i ++ ) if ( Y[i] < r ) { X[i] = random( *r) + r; Y[i] = r; } Y[i]< r Y[i] = r Условие выхода: Перебросить вниз: if ( Y[i] < r ) {... } X[i] = random( *r) + r; Y[i] = 400 – r; X[i] = random( *r) + r; Y[i] = 400 – r;

63 Задания «4»: Моделирование кипения воды в стакане (синий фон, рамка): «5»: Моделирование двустороннего потока: часть частиц двигаются влево, часть – вправо.

Программирование на языке Си Часть II Тема 8. Символьные строки © К.Ю. Поляков,

65 Чем плох массив символов? char A[4] = { 'A', '3', '[', 'Ж'}; char B[10]; char A[4] = { 'A', '3', '[', 'Ж'}; char B[10]; Это массивы символов: Для массива: каждый символ – отдельный объект; массив имеет длину N, которая задана при объявлении Что нужно: обрабатывать последовательность символов как единое целое строка должна иметь переменную длину

66 Символьные строки Привет!\0¤¤…¤¤¤ 0 79 рабочая часть s[0] s[1] s[2] s[3] char s[80]; признак окончания строки: символ с кодом 0 Символ '\0' имеет код 0 символ '0' имеет код 48 ! Символьная строка – это последовательность символов, которая заканчивается символом '\0'.

67 Объявление символьных строк Объявить строку = выделить ей место в памяти и присвоить имя. char s[80]; char s1[80] = "abc"; char qqq[] = "Вася"; char s[80]; char s1[80] = "abc"; char qqq[] = "Вася"; выделяется 80 байт, в строке – «мусор» (если она глобальная, то нули '\0) выделяется 80 байт, занято 4 байта (с учетом '\0') выделяется 5 байт (с учетом '\0') выделяется 5 байт (с учетом '\0') При выделении памяти надо учитывать место для символа '\0'. В строку нельзя записывать больше символов, чем выделено памяти. !

68 Ввод и вывод символьных строк Задача: ввести слово с клавиатуры и заменить все буквы «а» на буквы «б». main() { char q[80]; int i; printf("Введите строку\n"); scanf( "%s", q); i = 0; while ( q[i] != '\0' ) { if ( q[i] == 'а' ) q[i] = 'б'; i ++; } printf ( "Результат: %s ", q ); } %s не надо ставить &: q &q[0] не надо ставить &: q &q[0] %s – формат для ввода и вывода символьных строк (выводится только часть до '\0' "%s" пока не дошли до конца строки переход к следующему символу начали с q[0]

69 Ввод одного слова: Ввод строки с пробелами: char q[80]; printf ("Введите текст:\n"); scanf ( "%s", q ); printf ("Введено:\n%s", q ); char q[80]; printf ("Введите текст:\n"); scanf ( "%s", q ); printf ("Введено:\n%s", q ); Ввод символьных строк Введите текст: Вася пошел гулять Введено: Вася Введите текст: Вася пошел гулять Введено: Вася char q[80]; printf("Введите текст:\n"); gets ( q ); printf("Введено:\n%s", q ); char q[80]; printf("Введите текст:\n"); gets ( q ); printf("Введено:\n%s", q ); Введите текст: Вася пошел гулять Введено: Вася пошел гулять Введите текст: Вася пошел гулять Введено: Вася пошел гулять gets ( q );

70 Универсальный способ: Только для одной строки: printf ( "Результат: %s", q ); Вывод символьных строк puts ( q ); можно выводить сразу и другую информацию: надписи, значения переменных, … вывод только одной строки после вывода – переход на новую строку printf ( "%s\n", q );

71 Задания «4»: Ввести символьную строку и заменить все буквы "а" на буквы "б" и наоборот, как заглавные, так и строчные. Пример: Введите строку: ааббссААББСС Результат: ббаассББААСС «5»: Ввести символьную строку и проверить, является ли она палиндромом (палиндром читается одинаково в обоих направлениях). Пример: Пример: Введите строку: Введите строку: АБВГДЕ КАЗАК Результат: Результат: Не палиндром. Палиндром.

72 Функции для работы со строками Длина строки: strlen (string length) Подключение библиотеки: #include char q[80] = "qwerty"; int n; n = strlen ( q ); char q[80] = "qwerty"; int n; n = strlen ( q ); n = 6n = 6 n = 6n = 6 При определении длины символ '\0' не учитывается! !

73 Сравнение строк char q1[80], q2[80]; int n; gets ( q1 ); gets ( q2 ); n = strcmp ( q1, q2 ); char q1[80], q2[80]; int n; gets ( q1 ); gets ( q2 ); n = strcmp ( q1, q2 ); strcmp (string comparison): q1q2n "AA" 0 "AB""AA"1 "AB"– 1 "AA""A"65 Функция вычисляет разность между кодами первых двух отличающихся символов! !

74 Пример решения задачи Задача: ввести строку и определить, сколько в ней слов. Программа должна работать только при вводе правильного пароля. Идея решения: проверка пароля – через strcmp количество слов = количеству первых букв слова первая буква: пробел и за ним «не пробел» исключение: предложение начинается со слова (а не с пробела) Васяпошелгулять\0¤¤¤¤¤

75 Проверка пароля #include main() { char secret[] = "123", pass[20]; printf ( "Введите пароль\n" ); gets ( pass ); if ( strcmp ( pass, secret ) != 0 ) { printf ( "Пароль неверный" ); getch (); return 1; }... } если пароль неверный... сообщить об ошибке и выйти из программы аварийное завершение, код ошибки 1

76 Основная часть программы #include main() { char q[80]; int i, len, count = 0;... // проверка пароля printf ("Введите предложение\n"); gets ( q ); len = strlen( q ); if ( q[0] != ' ') count++; for ( i = 0; i < len - 1; i ++ ) if ( q[i] == ' ' && q[i+1] != ' ' ) count ++; printf ( "Найдено %d слов", count ); } особый случай если нашли пробел, а за ним не пробел… предыдущий слайд

77 Подсказка: для вывода одного символа используйте функцию putchar(символ). Например: Задания (везде – с паролем!) «4»: Ввести предложение и определить, сколько слов заканчиваются на букву 'а'. Пример: Введите предложение: Введите предложение: Мама мыла раму Декан пропил бутан Найдено слов: 2 Нет таких слов «5»: Ввести предложение и разобрать его на отдельные слова: Пример: Введите предложение: Мама мыла раму Результат: Мама мыла раму putchar(q[i]); putchar('\n'); // переход на новую строку putchar(q[i]); putchar('\n'); // переход на новую строку

78 Копирование строк strcpy (string copy) char q1[10] = "qwerty", q2[10] = "01234"; strcpy ( q1, q2 ); char q1[10] = "qwerty", q2[10] = "01234"; strcpy ( q1, q2 ); куда откуда Старое значение q1 стирается! ! копирование «хвоста» строки char q1[10] = "qwerty", q2[10] = "01234"; strcpy ( q1, q2+2 ); char q1[10] = "qwerty", q2[10] = "01234"; strcpy ( q1, q2+2 ); qwerty\0¤¤¤ ¤¤¤¤ q2 q1 q2 = &q2[0] q2+2 = &q2[2] 234\0

79 Копирование строк копирование в середину строки char q1[10] = "qwerty", q2[10] = "01234"; strcpy ( q1+2, q2 ); char q1[10] = "qwerty", q2[10] = "01234"; strcpy ( q1+2, q2 ); qwerty\0¤¤¤ ¤¤¤¤ q2 q1 q1+2 = &q1[2] 01234\0 char q1[10] = "qwerty", q2[10] = "01234"; strcpy ( q1+2, q2+3 ); char q1[10] = "qwerty", q2[10] = "01234"; strcpy ( q1+2, q2+3 ); qwerty\0¤¤¤ ¤¤¤¤ q2 q1 34\0 q2+3 = &q2[3] q1+2 = &q1[2]

80 Копирование строк strncpy – копирование нескольких символов char q1[10] = "qwerty", q2[10] = "01234"; strncpy ( q1+2, q2, 2 ); char q1[10] = "qwerty", q2[10] = "01234"; strncpy ( q1+2, q2, 2 ); qwerty\0¤¤¤ ¤¤¤¤ q2 q1 q1+2 = &q1[2] 01 Функция strncpy не добавляет символ '\0' в конце строки! !

81 Копирование строк копирование строки-константы char q1[10] = "qwerty"; strcpy ( q1+1, "ABCD"); char q1[10] = "qwerty"; strcpy ( q1+1, "ABCD"); qwerty\0¤¤¤ ABCD q1 ABCD\0 char q1[10] = "qwerty"; strcpy ( "ABCD", q1+2 ); char q1[10] = "qwerty"; strcpy ( "ABCD", q1+2 ); Первым параметром может быть константа! ! НЕ

82 Копирование строк копирование внутри одной строки char q[10] = "012345"; strcpy ( q, q+2 ); char q[10] = "012345"; strcpy ( q, q+2 ); \0¤¤¤ q 2345 char q[10] = "012345"; strcpy ( q+2, q ); char q[10] = "012345"; strcpy ( q+2, q ); \0¤¤¤ q Зацикливание и зависание компьютера!

83 Объединение строк strcat (string concatenation) = копирование второй строки в конец первой char q1[10] = "qwe", q2[10] = "0123"; strcat ( q1, q2 ); char q1[10] = "qwe", q2[10] = "0123"; strcat ( q1, q2 ); qwe\0¤¤¤¤¤¤ 0123 ¤¤¤¤¤ q2 q1 0123\0 char q1[10] = "qwe", q2[10] = "0123"; strcat ( q1, q2+2 ); char q1[10] = "qwe", q2[10] = "0123"; strcat ( q1, q2+2 ); qwe\0¤¤¤¤¤¤ 0123 ¤¤¤¤¤ q2 q1 23\0

84 что-то другое Проблемы Проблемы при копировании строк Транслятор не сообщает об этих ошибках! ! char q1[] = "qwer", q2[10] = "01234"; strcpy ( q1+2, q2 ); char q1[] = "qwer", q2[10] = "01234"; strcpy ( q1+2, q2 ); не хватает места для строки-результата qwer\ ¤¤¤¤¤ q2 q1 0123\0 зацикливание при копировании в ту же строку «слева направо» char q[10] = "01234"; strcpy ( q+2, q ); char q[10] = "01234"; strcpy ( q+2, q );

85 Пример решения задачи Задача: ввести имя файла (без пути) и поменять его расширение на ".exe". Пример: Введите имя файла: Введите имя файла: vasya.html vasya Результат: Результат: vasya.exe vasya.exe Алгоритм: найти точку в имени файла если она есть, скопировать в это место строку- константу ".exe" если точки нет, добавить в конец строки ".exe"

86 Программа main() { charfName[80]; int i; printf("Введите имя файла\n"); gets ( fName ); i = 0; while ( fName[i] != '.' ) { if ( fName[i] == '\0' ) break; i ++; } if ( fName[i] == '.' ) strcpy ( fName+i, ".exe" ); else strcat ( fName, ".exe" ); puts ( "Результат:" ); puts ( fName ); } поиск точки дошли до конца строки меняем или добавляем расширение

87 Задания «4»: Ввести полный адрес файла (возможно, без расширения) и изменить его расширение на «.exe ». Пример: Введите имя файла: Введите имя файла: C:\DOC.TXT\qqq C:\DOC.TXT\qqq.com Результат: Результат: C:\DOC.TXT\qqq.exe C:\DOC.TXT\qqq.exe «5»: Ввести в одной строке фамилию, имя и отчество. Вывести приветствие, где останутся имя и фамилия (см. пример). Пример: Введите ФИО: Пупкин Василий Иванович Результат: Привет, Василий Пупкин!

88 Поиск в символьных строках Задача: найти заданный символ или сочетание символов (подстроку) в символьной строке. Функции поиска в Си возвращают адрес найденного символа или подстроки! Если образец не найден, возвращается NULL (нулевой адрес). ! Указатель – это переменная в которую можно записать адрес другой переменной заданного типа.

89 Указатели char *p; // адрес любого символа или строки int *pI; // адрес целого числа float *pF; // адрес вещественного числа char *p; // адрес любого символа или строки int *pI; // адрес целого числа float *pF; // адрес вещественного числа Объявление: Целые переменные и массивы: int n = 6, A[5] = {0, 1, 2, 3, 4}; int *p; // указатель на целое p = &n; // записать адрес n *p = 20; // n = 20 p = A + 2; // записать адрес A[2] (&A[2]) *p = 99; // изменить A[2] p ++; // перейти к A[3] printf("Адрес: %p, число %d", p, *p); int n = 6, A[5] = {0, 1, 2, 3, 4}; int *p; // указатель на целое p = &n; // записать адрес n *p = 20; // n = 20 p = A + 2; // записать адрес A[2] (&A[2]) *p = 99; // изменить A[2] p ++; // перейти к A[3] printf("Адрес: %p, число %d", p, *p); Адрес: 6BCD:000C, значение 3 pointer – указатель

90 Указатели и символьные строки char str[10] = " "; char *p; p = str; *p = 'A'; p ++; *p = 'B'; p ++; strcpy ( p, "CD" ); strcat ( p, "qqq" ); puts ( p ); char str[10] = " "; char *p; p = str; *p = 'A'; p ++; *p = 'B'; p ++; strcpy ( p, "CD" ); strcat ( p, "qqq" ); puts ( p ); // указатель на символ // или & str[0] // "A12345" // перейти к str[1] // "AB2345 // перейти к str[2] // "ABCD" // "ABCDqqq"

91 Поиск символа strchr: найти первый заданный символ c начала строки strrchr: найти последний заданный символ в строке char q[10] = "abcdabcd"; char *p; int nomer; p = strchr(q, 'b'); if ( p == NULL ) printf ( "Не нашли..." ); else { nomer = p – q; printf ( "Номер символа %d", nomer ); } char q[10] = "abcdabcd"; char *p; int nomer; p = strchr(q, 'b'); if ( p == NULL ) printf ( "Не нашли..." ); else { nomer = p – q; printf ( "Номер символа %d", nomer ); } abcdabcd\0¤ q q q+1 q+5 p p reverse

92 Поиск подстроки strstr: найти первую подстроку c начала строки char q[10] = "abcdabcd"; char *p; int nomer; p = strstr(q, "bcd"); if ( p == NULL ) printf ( "Не нашли..." ); else { nomer = p – q; printf ( "Номер первого символа %d", nomer ); } char q[10] = "abcdabcd"; char *p; int nomer; p = strstr(q, "bcd"); if ( p == NULL ) printf ( "Не нашли..." ); else { nomer = p – q; printf ( "Номер первого символа %d", nomer ); } abcdabcd\0¤ q q q+1 q+5 p p

93 Пример решения задачи Задача: ввести предложение и определить, сколько раз в нем встречается имя «Вася». Проблема: функция strstr ищет только с начала строки. Алгоритм: 1.Записать адрес начала строки в указатель start. 2.Искать подстроку «Вася», начиная с адреса start. 3.Если не нашли, выход из цикла. 4.Увеличить счетчик найденных слов. 5.Переставить start на адрес после найденного слова. 6.Перейти к шагу 2. Вася иВасяВася!!!\0 start p p = strstr( start, "Вася");

94 Программа main() { char q[80], *start, *p; int count = 0; puts ( "Введите предложение" ); gets ( q ); start = q; // ищем с начала строки while ( 1 ) { p = strstr ( start, "Вася" ); if ( p == NULL ) break; count ++; start = p + 4; // отсюда ищем следующее слово } printf ( "Имя 'Вася' встречается %d раз", count ); } начало поиска адрес найденного слова

95 Задания «4»: Ввести предложение и заменить все имена «Вася» на «Юра». Пример: Введите предложение: Вася, Вася, Вася и Вася!!! Результат: Юра, Юра, Юра и Юра!!! «5»: Ввести предложение и заменить все имена «Юра» на «Вася». Пример: Введите предложение: Юра, Юра, Юра и Юра!!! Результат: Вася, Вася, Вася и Вася!!!

96 Строки в процедурах и функциях строки передаются в функции и процедуры так же, как и массивы; функции и процедуры могут изменять строки – параметры. ! Задача: составить процедуру, которая переставляет символы строки в обратном порядке. Алгоритм: определить длину строки len; все символы первой половины переставить с соответствующими символами второй половины: c = s[i]; s[i] = s[len-i-1]; s[len-1-i] = c; c = s[i]; s[i] = s[len-i-1]; s[len-1-i] = c; s[i]s[len-1-i]

97 Программа void Reverse ( char s[] ) { int len = strlen(s); char c; for ( i = 0; i < len/2; i ++ ) { c = s[i]; s[i] = s[len-i-1]; s[len-1-i] = c; } main() { char s[] = " "; Reverse ( s ); puts ( s ); Reverse ( s + 5 ); puts ( s ); } void Reverse ( char s[] ) { int len = strlen(s); char c; for ( i = 0; i < len/2; i ++ ) { c = s[i]; s[i] = s[len-i-1]; s[len-1-i] = c; } } main() { char s[] = " "; Reverse ( s ); puts ( s ); Reverse ( s + 5 ); puts ( s ); } Как сделать инверсию любой части строки? ? длину строки определяем на месте

98 Задания «4»: Разработать процедуру, которая переставляет пары соседних символов. Пример: Введите предложение: Вася пошел гулять! Результат: аВясп шолег лутя!ь «5»: Разработать процедуру, которая удаляет все лишние пробелы (в начале предложения и сдвоенные пробелы). Пример: Введите предложение: Вася пошел гулять! Результат: Вася пошел гулять!

99 Символьные строки в функциях Задача: составить функцию, которая находит количество цифр в строке. int NumDigits ( char s[] ) { int i, count = 0; for ( i = 0; i < strlen(s); i ++ ) if( strchr ( " ", s[i] ) ) count ++; return count; } int NumDigits ( char s[] ) { int i, count = 0; for ( i = 0; i < strlen(s); i ++ ) if( strchr ( " ", s[i] ) ) count ++; return count; } if ( strchr ( " ", s[i] ) != NULL ) или if ( '0'

100 Символьные строки в функциях Основная программа int NumDigits ( char s[] ) {... } main() { char s[80]; int n; printf ( "Введите строку\n" ); gets ( s ); n = NumDigits ( s ); printf ( "Нашли %d цифр.", s ); } int NumDigits ( char s[] ) {... } main() { char s[80]; int n; printf ( "Введите строку\n" ); gets ( s ); n = NumDigits ( s ); printf ( "Нашли %d цифр.", s ); }

101 Задания «4»: Разработать функцию, которая определяет, верно ли, что слово – палиндром. Пример: Введите слово: Введите слово: казак кунак Результат:Результат: Это палиндром.Не палиндром. «5»: Разработать функцию, которая определяет, верно ли, что предложение (с пробелами) – палиндром. Пример: Введите предложение: а роза упала на лапу азора Результат: Это палиндром.

Программирование на языке Си Часть II Тема 9. Рекурсивный перебор © К.Ю. Поляков,

103 Рекурсивный перебор Задача: Алфавит языка племени «тумба-юмба» состоит из букв Ы, Ц, Щ и О. Вывести на экран все слова из К букв, которые можно составить в этом языке, и подсчитать их количество. Число K вводится с клавиатуры. 0K-1 в каждой ячейке может быть любая из 4-х букв 4 варианта Количество вариантов:

104 Рекурсивный перебор Ы 0K-1 Рекурсия: Решения задачи для слов из К букв сводится к 4-м задачам для слов из K-1 букв. Щ 0K-1 О 0 Ц 0 перебрать все варианты

105 Процедура ???? 0K-1 p Глобальные переменные: char s[80]; int count, K; Глобальные переменные: char s[80]; int count, K; s p+1 рекурсивные вызовы А если букв много? ? окончание рекурсии void Rec( int p ) { if ( p >= K ) { puts ( s ); count ++; return; } s[p] = 'Ы'; Rec ( p + 1 ); s[p] = 'Ц'; Rec ( p + 1 ); s[p] = 'Щ'; Rec ( p + 1 ); s[p] = 'О'; Rec ( p + 1 ); } p символов уже на своих местах

106 Процедура void Rec ( int p ) { const char letters[] = "ЫЦЩО"; int i; if ( p >= K ) { puts ( s ); count ++; return; } for ( i = 0; i < strlen(letters); i ++) { s[p] = letters[i]; Rec ( p + 1 ); } const char letters[] = 'ЫЦЩО'; for ( i = 0; i < strlen(letters); i ++) { s[p] = letters[i]; Rec ( p + 1 ); } все буквы цикл по всем буквам локальная переменная

107 Программа char s[80]; int K, count = 0 ; main() { printf ( "Введите длину слов:\n" ); scanf ( "%d", &K ); Rec ( 0 ); printf ( "Всего %d слов.", count ); } char s[80]; int K, count = 0 ; main() { printf ( "Введите длину слов:\n" ); scanf ( "%d", &K ); Rec ( 0 ); printf ( "Всего %d слов.", count ); } void Rec ( int p ) {... } процедура глобальные переменные (обнуляются) глобальные переменные (обнуляются) count; 1. Как определяется конец строки? 2. Как обойтись без глобальных переменных? ?

108 Задания Алфавит языка племени "тумба-юмба" состоит из букв Ы, Ц, Щ и О. Число K вводится с клавиатуры. «4»: Вывести на экран все слова из К букв, в которых буква Ы встречается более 1 раза, и подсчитать их количество. «5»: Вывести на экран все слова из К букв, в которых есть одинаковые буквы, стоящие рядом (например, ЫЩЩО), и подсчитать их количество. Без глобальных переменных! !

Программирование на языке Си Часть II Тема 10. Матрицы © К.Ю. Поляков,

110 Матрицы Задача: запомнить положение фигур на шахматной доске abcdefgh c6 A[5][2]

111 Матрицы Матрица – это прямоугольная таблица однотипных элементов. Матрица – это массив, в котором каждый элемент имеет два индекса (номер строки и номер столбца) A строка 1 столбец 2 ячейка A[2][3]

112 Матрицы Объявление: const int N = 3, M = 4; int A[N][M]; float a[2][2] = {{3.2, 4.3}, {1.1, 2.2}}; char sym[2][2] = { 'a', 'b', 'c', 'd' }; const int N = 3, M = 4; int A[N][M]; float a[2][2] = {{3.2, 4.3}, {1.1, 2.2}}; char sym[2][2] = { 'a', 'b', 'c', 'd' }; Ввод с клавиатуры: for ( i = 0; i < N; i ++ ) for ( j = 0; j < M; j ++ ) { printf ( "A[%d][%d]=", i, j); scanf ( "%d", &A[i][j] ); } for ( i = 0; i < N; i ++ ) for ( j = 0; j < M; j ++ ) { printf ( "A[%d][%d]=", i, j); scanf ( "%d", &A[i][j] ); } Если переставить циклы? ? A[0][0]=25 A[0][1]=14 A[0][2]=14... A[2][3]=54 i i j j for ( j = 0; j < M; j ++ ) for ( i = 0; i < N; i ++ ) {

113 Матрицы Заполнение случайными числами for ( i = 0; i < N; i ++ ) for ( j = 0; j < M; j ++ ) A[i][j] = random(25)- 10; for ( i = 0; i < N; i ++ ) for ( j = 0; j < M; j ++ ) A[i][j] = random(25)- 10; Какой интервал? ? цикл по строкам цикл по столбцам Вывод на экран for ( i = 0; i < N; i ++ ) { for ( j = 0; j < M; j ++ ) printf("%5d", A[i,j]); printf("\n"); } for ( i = 0; i < N; i ++ ) { for ( j = 0; j < M; j ++ ) printf("%5d", A[i,j]); printf("\n"); } перейти на новую строку for ( j = 0; j < M; j ++ ) printf("%5d", A[i][j]); for ( j = 0; j < M; j ++ ) printf("%5d", A[i][j]); вывод строки Если переставить циклы? ? в той же строке

114 Обработка всех элементов матрицы Задача: заполнить матрицу из 3 строк и 4 столбцов случайными числами и вывести ее на экран. Найти сумму элементов матрицы. main() { const int N = 3, M = 4; int A[N][M], i, j, S = 0;... // заполнение матрицы и вывод на экран for ( i = 0; i < N; i ++ ) for ( j = 0; j < M; j ++ ) S += A[i][j]; printf("Сумма элементов матрицы S=%d", S); } main() { const int N = 3, M = 4; int A[N][M], i, j, S = 0;... // заполнение матрицы и вывод на экран for ( i = 0; i < N; i ++ ) for ( j = 0; j < M; j ++ ) S += A[i][j]; printf("Сумма элементов матрицы S=%d", S); } for ( i = 0; i < N; i ++ ) for ( j = 0; j < M; j ++ ) S += A[i][j]; for ( i = 0; i < N; i ++ ) for ( j = 0; j < M; j ++ ) S += A[i][j];

115 Задания Заполнить матрицу из 8 строк и 5 столбцов случайными числами в интервале [-10,10] и вывести ее на экран. «4»: Найти минимальный и максимальный элементы в матрице их номера. Формат вывода: Минимальный элемент A[3][4]=-6 Максимальный элемент A[2][2]=10 «5»: Вывести на экран строку, сумма элементов которой максимальна. Формат вывода: Строка 2:

116 Операции с матрицами Задача 1. Вывести на экран главную диагональ квадратной матрицы из N строк и N столбцов. A[0][N-1] A[1][1] A[2][2] A[N-1][N-1] for ( i = 0; i < N; i ++ ) printf ( "%5d", A[i][i] ); for ( i = 0; i < N; i ++ ) printf ( "%5d", A[i][i] ); Задача 2. Вывести на экран вторую диагональ. A[N-1][0] A[N-2][1] A[1][N-2] сумма номеров строки и столбца N-1 A[0][0] for ( i = 0; i < N; i ++) printf ( "%5d", A[i][ N-1-i ]); for ( i = 0; i < N; i ++) printf ( "%5d", A[i][ N-1-i ]); N-1-i

117 Операции с матрицами Задача 3. Найти сумму элементов, стоящих на главной диагонали и ниже ее. Одиночный цикл или вложенный? ? строка 0: A[0][0] строка 1: A[1][0]+A[1][1]... строка i: A[i][0]+A[i][2]+...+A[i][i] S = 0; for ( i = 0; i < N; i ++ ) for ( j = 0; j

118 Операции с матрицами Задача 4. Перестановка строк или столбцов. В матрице из N строк и M столбцов переставить 1-ую и 3-ю строки j A[1][j] A[3][j] for ( j = 0; j

119 Задания Заполнить матрицу из 7 строк и 7 столбцов случайными числами в интервале [-10,10] и вывести ее на экран. Обнулить элементы, отмеченные зеленым фоном, и вывести полученную матрицу на экран. «4»: «5»:

Программирование на языке Си Часть II Тема 11. Файлы © К.Ю. Поляков,

121 Файлы Файл – это область на диске, имеющая имя. Файлы только текст без оформления, не содержат управляющих символов (с кодами < 32), кроме перевода строки ACSII (1 байт на символ) UNICODE (2 байта на символ) *.txt, *.log, *.htm, *.html могут содержать любые символы кодовой таблицы *.doc, *.exe, *.bmp, *.jpg, *.wav, *.mp3, *.avi, *.mpg ТекстовыеДвоичные Папки (каталоги)

122 Принцип сэндвича I этап. открыть файл (сделать его активным, приготовить к работе) f = fopen("qq.dat", "r"); II этап: работа с файлом III этап: закрыть (освободить) файл fclose ( f ); fscanf ( f, "%d", &n ); // ввести значение n fprintf( f, "n=%d", n ); // записать значение n для чтения ( "r", англ. read) f = fopen("qq.dat", "w"); для записи ( "w", англ. write) f = fopen("qq.dat", "a"); для добавления ( "a", англ. append) Переменная типа «указатель на файл»: FILE *f;

123 Работа с файлами Особенности: имя файла упоминается только в команде fopen, обращение к файлу идет через указатель f ; файл, который открывается на чтение, должен существовать если файл, который открывается на запись, существует, старое содержимое уничтожается данные (этим способом) записываются в файл в текстовом виде когда программа заканчивает работу, все файлы закрываются автоматически после закрытия файла переменную f можно использовать еще раз для работы с другим файлом

124 Последовательный доступ при открытии файла курсор устанавливается в начало чтение выполняется с той позиции, где стоит курсор после чтения курсор сдвигается на первый непрочитанный символ конец файла (end of file, EOF) конец файла (end of file, EOF) f = fopen("qq.dat", "r"); fscanf ( f, "%d", &x ); Как вернуться назад? ?

125 Ошибки при открытии файла FILE *f; f = fopen("qq.dat", "r"); if ( f == NULL ) { puts("Файл на найден."); return; } FILE *f; f = fopen("qq.dat", "r"); if ( f == NULL ) { puts("Файл на найден."); return; } NULL неверное имя файла нет файла файл заблокирован другой программой неверное имя файла нет файла файл заблокирован другой программой Если файл открыть не удалось, функция fopen возвращает NULL (нулевое значение)! ! FILE *f; f = fopen("qq.dat", "w"); if ( f == NULL ) { puts("Не удалось открыть файл."); return; } FILE *f; f = fopen("qq.dat", "w"); if ( f == NULL ) { puts("Не удалось открыть файл."); return; } NULL неверное имя файла файл «только для чтения» файл заблокирован другой программой неверное имя файла файл «только для чтения» файл заблокирован другой программой

126 Пример Задача: в файле input.txt записаны числа (в столбик), сколько их – неизвестно. Записать в файл output.txt их сумму. Алгоритм: 1.Открыть файл input.txt для чтения. 2.S = 0; 3.Прочитать очередное число в переменную x. 4.Если не удалось, перейти к шагу 7. 5.S + = x; 6.Перейти к шагу 3. 7.Закрыть файл input.txt. 8.Открыть файл output.txt для записи. 9.Записать в файл значение S. 10.Закрыть файл output.txt. Можно ли обойтись без массива? ? цикл с условием «пока есть данные»

127 Как определить, что числа кончились? FILE *f; int n, x; f = fopen("input.txt", "r");... n = fscanf ( f, "%d", &x ); if ( n ! = 1 ) puts ( "Не удалось прочитать число" ); FILE *f; int n, x; f = fopen("input.txt", "r");... n = fscanf ( f, "%d", &x ); if ( n ! = 1 ) puts ( "Не удалось прочитать число" ); Функция fscanf возвращает количество удачно прочитанных чисел; 0, если была ошибка при чтении; – 1, если достигли конца файла. ! дошли до конца файла встретили «не число» дошли до конца файла встретили «не число»

128 Программа main() { FILE *f; int n, x, S = 0; f = fopen ( "input.txt", "r" ); if ( f == NULL ) { printf("Файл не найден."); return; } while ( 1 ) { n = fscanf ( f, "%d", &x ); if ( n != 1 ) break; S += x; } fclose ( f ); f = fopen ( "output.txt", "w" ); fprintf ( f, "S = %d", S ); fclose ( f ); } ошибка при открытии файла цикл чтения данных: выход при n 1. запись результата

129 Задания В файле input.txt записаны числа, сколько их – неизвестно. «4»: Найти среднее арифметическое всех чисел и записать его в файл output.txt. «5»: Найти минимальное и максимальное числа и записать их в файл output.txt.

130 Обработка массивов Задача: в файле input.txt записаны числа (в столбик), сколько их – неизвестно, но не более 100. Переставить их в порядке возрастания и записать в файл output.txt. Проблемы: для сортировки надо удерживать в памяти все числа сразу (массив); сколько чисел – неизвестно. Решение: 1)выделяем в памяти массив из 100 элементов; 2)записываем прочитанные числа в массив и считаем их в переменной N ; 3)сортируем первые N элементов массива; 4)записываем их в файл. Можно ли обойтись без массива? ?

131 Чтение данных в массив int ReadArray ( int A[], char fName[], int MAX ) { int N = 0, k; FILE *f; f = fopen ( fName, "r" ); while ( 1 ) { k = fscanf ( f, "%d", &A[N]); if ( k != 1 ) break; N ++; if ( N >= MAX ) break; } fclose(f); return N; } Функция, которая читает массив из файла, возвращает число прочитанных элементов (не более MAX): массив заканчиваем цикл если не удалось прочитать … имя файла предел … или заполнили весь массив

132 Программа main() { int A[100], N, i; FILE *f; N = ReadArray ( A, "input.txt", 100 );... // сортировка первых N элементов f = fopen("output.txt", "w"); for ( i = 0; i < N; i ++) fprintf ( f, "%d\n", A[i] ); fclose ( f ); } main() { int A[100], N, i; FILE *f; N = ReadArray ( A, "input.txt", 100 );... // сортировка первых N элементов f = fopen("output.txt", "w"); for ( i = 0; i < N; i ++) fprintf ( f, "%d\n", A[i] ); fclose ( f ); } int ReadArray(int A[], char fName[], int MAX) {... } вывод отсортированного массива в файл

133 Задания В файле input.txt записаны числа (в столбик), известно, что их не более 100. «4»: Отсортировать массив по убыванию последней цифры и записать его в файл output.txt. «5»: Отсортировать массив по возрастанию суммы цифр и записать его в файл output.txt.

134 Обработка текстовых данных Задача: в файле input.txt записаны строки, в которых есть слово-паразит "короче". Очистить текст от мусора и записать в файл output.txt. Файл input.txt : Мама, короче, мыла, короче, раму. Декан, короче, пропил, короче, бутан. А роза, короче, упала на лапу, короче, Азора. Каждый, короче, охотник желает, короче, знать, где... Результат – файл output.txt : Мама мыла раму. Декан пропил бутан. А роза упала на лапу Азора. Каждый охотник желает знать, где сидит фазан.

135 Обработка текстовых данных Особенность: надо одновременно держать открытыми два файла (один в режиме чтения, второй – в режиме записи). Алгоритм: 1. Открыть оба файла. 2. Прочитать строку. 3. Удалить все сочетания ", короче,". 4. Записать строку во второй файл. 5. Перейти к шагу Закрыть оба файла. пока не кончились данные

136 Работа с файлами main() { char s[80], *p; int i; FILE *fIn, *fOut; fIn = fopen("input.txt", "r"); fOut = fopen("output.txt", "w");... // обработать файл fclose(fIn); fclose(fOut); } main() { char s[80], *p; int i; FILE *fIn, *fOut; fIn = fopen("input.txt", "r"); fOut = fopen("output.txt", "w");... // обработать файл fclose(fIn); fclose(fOut); } файловые указатели открыть файл для чтения открыть файл для записи указатель для поиска закрыть файлы

137 Обработка текстовых данных Чтение строки s : while ( 1 ) { p = strstr ( s, ", короче," ); if ( p == NULL ) break; strcpy ( p, p + 9 ); } while ( 1 ) { p = strstr ( s, ", короче," ); if ( p == NULL ) break; strcpy ( p, p + 9 ); } искать ", короче," удалить 9 символов выйти из цикла, если не нашли char s[80], *p; FILE *fIn;... // здесь надо открыть файл p = fgets ( s, 80, fIn ); if ( p == NULL ) printf("Файл закончился."); else printf("Прочитана строка:\n%s", s); char s[80], *p; FILE *fIn;... // здесь надо открыть файл p = fgets ( s, 80, fIn ); if ( p == NULL ) printf("Файл закончился."); else printf("Прочитана строка:\n%s", s); Обработка строки s : строка длина файл

138 #include Полный цикл обработки файла while ( 1 ) { p = fgets ( s, 80, fIn ); if ( p == NULL ) break; while ( 1 ) { p = strstr ( s, ", короче," ); if ( p == NULL ) break; strcpy ( p, p + 9 ); } fputs ( s, fOut ); } while ( 1 ) { p = fgets ( s, 80, fIn ); if ( p == NULL ) break; while ( 1 ) { p = strstr ( s, ", короче," ); if ( p == NULL ) break; strcpy ( p, p + 9 ); } fputs ( s, fOut ); } while ( 1 ) { p = strstr ( s, ", короче," ); if ( p == NULL ) break; strcpy ( p, p + 9 ); } если нет больше строк, выйти из цикла обработка строки запись "очищенной" строки читаем строку

139 Задания В файле input.txt записаны строки, сколько их – неизвестно. «4»: Заменить во всем тексте «в общем» на «короче» и записать результат в файл output.txt. «5»: Заменить во всем тексте «короче» на «в общем» и записать результат в файл output.txt.

140 Двоичные файлы Особенности: данные хранятся во внутреннем машинном формате (в текстовом редакторе не прочитать) можно читать и записывать любой кусок памяти (просто биты…) принцип сэндвича (открыть – работать – закрыть) обращение к файлу через указатель Файловые указатели FILE *fp;

141 Открытие и закрытие двоичных файлов Открытие файла fp = fopen ( "input.dat", "rb" ); "rb" = read binary (чтение) "wb" = write binary (запись) "ab" = append binary (добавление) "rb" = read binary (чтение) "wb" = write binary (запись) "ab" = append binary (добавление) Ошибки при открытии if ( fp == NULL ) { printf("Файл открыть не удалось."); } if ( fp == NULL ) { printf("Файл открыть не удалось."); } Закрытие файла fclose ( fp );

142 Чтение по блокам Чтение в начало массива int A[100]; n = fread ( A, sizeof(int), 100, fp ); int A[100]; n = fread ( A, sizeof(int), 100, fp ); адрес области памяти («куда»): A &A[0] адрес области памяти («куда»): A &A[0] размер одного блока размер переменной целого типа количество блоков указатель на файл прочитано фактически Чтение в середину массива int A[100]; n = fread ( A+5, sizeof(int), 2, fp ); int A[100]; n = fread ( A+5, sizeof(int), 2, fp ); читается 2 целых числа: A[5], A[6] читается 2 целых числа: A[5], A[6]

143 Запись по блокам Запись с начала массива int A[100]; n = fwrite( A, sizeof(int), 100, fp ); int A[100]; n = fwrite( A, sizeof(int), 100, fp ); адрес области памяти («откуда»): A &A[0] адрес области памяти («откуда»): A &A[0] размер одного блока размер переменной целого типа количество блоков указатель на файл записано фактически Запись отдельных элементов массива int A[100]; n = fwrite( A+5, sizeof(int), 2, fp ); int A[100]; n = fwrite( A+5, sizeof(int), 2, fp ); записывается 2 целых числа: A[5], A[6] записывается 2 целых числа: A[5], A[6]

144 Работа с матрицами Хранение в памяти: по строкам (Си, Паскаль) Запись матрицы int A[3][3]; FILE *fp = fopen("output.dat", "wb");... // здесь заполняем матрицу n = fwrite( A, sizeof(int), 9, fp ); int A[3][3]; FILE *fp = fopen("output.dat", "wb");... // здесь заполняем матрицу n = fwrite( A, sizeof(int), 9, fp );

145 Пример Задача: прочитать массив из файла input.dat, умножить все элементы на 2 и вывести в файл output.dat. Структура программы: #include main() { const int N = 10; int i, A[N], n; FILE *fp; // чтение данных и файла input.dat for ( i = 0; i < n; i ++ ) A[i] = A[i] * 2; // запись данных в файл output.dat } #include main() { const int N = 10; int i, A[N], n; FILE *fp; // чтение данных и файла input.dat for ( i = 0; i < n; i ++ ) A[i] = A[i] * 2; // запись данных в файл output.dat } прочитано фактически

146 Работа с файлами fp = fopen( "input.dat", "rb" ); if ( fp == NULL ) { printf("Файл открыть не удалось."); return; } n = fread ( A, sizeof(int), N, fp ); if ( n < N ) printf("Не хватает данных в файле"); fclose ( fp ); fp = fopen( "input.dat", "rb" ); if ( fp == NULL ) { printf("Файл открыть не удалось."); return; } n = fread ( A, sizeof(int), N, fp ); if ( n < N ) printf("Не хватает данных в файле"); fclose ( fp ); Чтение данных: fp = fopen( "output.dat", "wb" ); fwrite ( A, sizeof(int), n, fp ); fclose ( fp ); fp = fopen( "output.dat", "wb" ); fwrite ( A, sizeof(int), n, fp ); fclose ( fp ); Запись данных: критическая ошибка некритическая ошибка сколько прочитали

147 Задания «4»: В текстовом файле input.txt записан массив целых чисел. Отсортировать его и записать в двоичный файл output.dat. «5»: В текстовых файлах input1.txt и input2.txt записаны два массива. Объединить их в один массив, отсортировать и записать результат в двоичный файл output.dat.

148 Конец фильма