КР по ОАиП для заочников. Основы алгоритмизации и программирования
Скачать 1.08 Mb.
|
MinMax (int a[],int n,int *min,int *max,int *imin,int *imax) { int i; *min=*max=a[0]; // Инициализация значений *imin=*imax=0; for (i=1; i // Поиск минимального элемента и его индекса *min=a[i]; *imin = i; } else if (a[i]>*max) { // Поиск максимального элемента и его индекса *max=a[i]; *imax = i; } } 33 Рисунок 5 – Результат выполнения программы 4.3. Индивидуальные задания Ввести одномерный статический массив из k чисел. Выполнить в соот- ветствии с номером варианта индивидуальное задание и вывести на экран ис- ходные данные и полученный результат. Предусмотреть использование функ- ции пользователя. 1. Найти произведение элементов массива, расположенных между макси- мальным и минимальным элементами. 2. Найти сумму элементов массива, расположенных после первого нулево- го элемента. 3. Найти среднее арифметическое элементов массива, расположенных до максимального элемента. 4. Найти количество элементов массива, расположенных после минималь- ного элемента. 5. Найти произведение и количество элементов массива, расположенных до первого отрицательного элемента. 6. Найти сумму и количество элементов массива, расположенных после первого положительного элемента. 7. Найти среднее арифметическое положительных кратных трем элементов массива, расположенных до минимального элемента. 8. Найти произведение четных отрицательных элементов массива, распо- ложенных после минимального элемента. 34 9. Найти сумму и количество нечетных элементов массива, расположенных до последнего положительного элемента. 10. Найти среднее арифметическое модулей кратных пяти элементов мас- сива, расположенных после максимального элемента. 11. Найти произведение модулей элементов массива, расположенных по- сле минимального элемента. 12. Найти сумму модулей элементов массива, расположенных после по- следнего нулевого элемента. 13. Найти среднее арифметическое модулей четных элементов массива, расположенных между первым отрицательным и последним положительным элементами. 14. Найти максимальное значение между суммами четных и нечетных элементов массива, расположенных до минимального элемента. 15. Расположить элементы массива в обратном порядке. 35 ЗАДАНИЕ №5 УКАЗАТЕЛИ. ПРОГРАММИРОВАНИЕ С ИСПОЛЬЗОВАНИЕМ ДИНАМИЧЕСКИХ ДВУМЕРНЫХ МАССИВОВ 5.1. Объявление указателя Для всех переменных выделяются участки памяти размером, соответст- вующим типу переменной. Программист имеет возможность работать непо- средственно с адресами, для чего определен соответствующий тип данных – указатель. Указатель имеет следующий формат: тип * имя_указателя; Например: int *a; double *b, *d; char *c; Знак «звездочка» относится к имени указателя. Значение указателя соот- ветствует первому байту участка памяти, на который он ссылается. На один и тот же участок памяти может ссылаться любое число указателей. В языке С существует три вида указателей: 1. Указатель на объект известного типа. Содержит адрес объекта опреде- ленного типа. Например: int *ptr; 2. Указатель типа void . Применяется, еcли тип объекта заранее не опреде- лен. Например: void *vptr; 3. Указатель на функцию. Адрес, по которому передается управление при вызове функции. Например: void (*func)(int); *func указатель на функцию, принимающей аргумент int и не возвра- щающей никаких значений. 5.2. Операции над указателями К указателям можно применять две унитарные операции: 1. & ( взятие адреса ) Указатель получает адрес переменной. Данная операция применима к пе- ременным, под которые выделен соответствующий участок памяти. Например: int *ptr, var=1; // ptr – указатель, var – переменная ptr = &var; // В ptr заносится адрес var 2. * (операция разадресации). Предназначена для доступа к значению, расположенному по данному ад- ресу. *ptr = 9; // В ячейку памяти, с адресом ptr записывается значение 9 var = *ptr; //Переменной var присваивается значение, 36 // расположенное по адресу ptr Над указателями можно выполнять арифметические операции сложения, инкремента (увеличения на 1), вычитания, декремента (уменьшения на 1) и операции сравнения ( > , >= , < , <= , == , != ). При выполнении арифметических операций с указателями автоматически учитывается размер данных, на которые он указывает. Например: ptr++; // Сдвиг указателя ptr на один элемент вперед (*ptr)++; // (или ++*ptr ;) Увеличение на 1 значения переменной, // на которую указывает указатель ptr *ptr = NULL; // Очистка указателя рtr1 Указатели, как правило, используются при работе с динамической памя- тью (heap или «куча»). Для работы с динамической памятью в языке С опреде- лены следующие функции: malloc , сalloc, realloc и free. В языке C++ для выделения и освобождения памяти определены операции new и delete соответственно. Используют две формы операций: 1. Тип * указатель = new тип ( значение ); – выделение участка памяти в соответствии с указанным типом и занесение туда заданного значения. delete указатель; – освобождение выделенной памяти. 2. Тип * указатель = new тип [n]; – выделение участка памяти размером n блоков указанного типа. delete [ ] указатель; – освобождение выделенной памяти. Пример работы с одномерным динамическим массивом: int *a; // Объявление указателя a a = new int[n]; // Выделение n блоков памяти целого типа … // Работа с массивом a delete [] a; // Освобождение выделенной памяти 5.3. Создание двумерного динамического массива Имя любого массива рассматривается компилятором как указатель на ну- левой элемент массива. Так как имя двумерного динамического массива явля- ется указателем на указатель, то сначала выделятся память под указатели, а затем под соответствующие этим указателям строки. Освобождение выделен- ной памяти происходит в обратном порядке. 5.4. Пример выполнения задания Написать программу перестановки минимального и максимального эле- ментов двумерного массива размером N x M. Память для массива выделить ди- намически. результат. Предусмотреть использование функции пользователя. #include #include #include // Прототип функции поиска минимального и максимального элементов 37 // двумерного массива void Poisk (double**, int, int, int*, int*, int*, int*); int main() { double **a, tmp; int i, j, n, m, imin, jmin, imax, jmax; cout << "Vvedite razmer massiva A:\n"; cout << "row n="; cin >> n ; cout << "column m="; cin >> m; a = new double*[n]; // Выделение памяти под массив указателей for(i=0; i a[i] = new double[m]; // этим указателям строки матрицы cout << "\nVvedite massiv A:\n"; // Ввод элементов двумерного массива for (i=0; i } cout << "\nMassiv A:\n"; // Вывод элементов двумерного массива for (i=0; i Poisk (a, n, m, &imin, &imax, &jmin, &jmax); // Вызов функции tmp = a[imin][jmin]; // Перестановка элементов a[imin][jmin] = a[imax][jmax]; a[imax][jmax] = tmp; cout << "\nResult massiv:\n" ; // Вывод результата for (i=0; i 38 for (j=0; j delete [] a[i]; delete []a; a = NULL; return 0; } // Функция поиска индексов минимального и максимального элементов массива void Poisk (double **a,int n,int m,int *imin,int *imax,int *jmin,int *jmax) { int i, j; *imin=*jmin=*imax=*jmax=0; // Инициализация значений индексов for (i=0; i *imin=i; *jmin=j; } if (a[i][j]>a[*imax][*jmax]) { // Поиск индексов максимального элемента *imax=i; *jmax=j; } } } 39 Рисунок 6 – Результат выполнения программы 5.5. Индивидуальные задания Ввести матрицу размером NxM . Память для массива выделить динами- чески. Выполнить в соответствии с номером варианта индивидуальное зада- ние и вывести на экран исходные данные и полученный результат. Предусмот- реть в программеиспользование функции пользователя. 1 . Определить количество положительных элементов, расположенных ни- же побочной диагонали матрицы. 2 . Определить количество отрицательных элементов, расположенных вы- ше главной диагонали матрицы. 3 .Определить сумму отрицательных элементов, расположенных выше по- бочной диагонали матрицы. 4 . Определить произведение положительных элементов, расположенных ниже главной диагонали матрицы. 5 . Определить сумму элементов, расположенных на главной диагонали матрицы, и произведение элементов, расположенных на побочной диагонали матрицы. 6 . Определить количество четных элементов, расположенных на главной и побочной диагоналях. 7 . Найти максимальный среди элементов, лежащих ниже побочной диаго- нали. 8 . Найти минимальный среди элементов, лежащих выше главной диагона- ли. 40 9 . Найти максимальный среди элементов, лежащих выше побочной диаго- нали. 10 . Найти минимальный среди элементов, лежащих ниже главной диаго- нали. 11 . Определить произведение кратных трем элементов матрицы, располо- женных выше ее главной диагонали, включая саму диагональ. 12 . Определить сумму отрицательных нечетных элементов матрицы, рас- положенных ниже ее побочной диагонали, включая саму диагональ. 13 . Найти сумму элементов, расположенных в четных (по номеру) строках матрицы. 14 .Найти произведение элементов, расположенных в нечетных (по номе- ру) столбцах матрицы. 15 . Подсчитать сумму четных элементов и произведение нечетных эле- ментов матрицы. 41 ЗАДАНИЕ №6 ПРОГРАММИРОВАНИЕ С ИСПОЛЬЗОВАНИЕМ ФАЙЛОВ И СТРУКТУР 6.1. Объявление структур Структура – это составной тип данных, в котором под одним именем объ- единены данные различных типов. Отдельные данные структуры называются полями. Объявление структуры осуществляется с помощью ключевого слова struct , за которым указывается ее имя и список элементов, заключенных в фи- гурные скобки: struct имя { тип_элемента_1 имя_элемента_1 ; тип_элемента_2 имя_элемента_2 ; тип_элемента_ n имя_элемента_ n; } ; Правила работы с полями структуры идентичны работе с переменными со- ответствующих типов. К полям структуры можно обращаться через составное имя. Формат обращения: имя_структуры . имя_поля или указатель_на_структуру– > имя_поля 6.2. Организация работы с файлами Различают два вида файлов: текстовые и двоичные (бинарные). Текстовые файлы хранят информацию в виде последовательности симво- лов. В текстовом режиме каждый разделительный символ строки автоматиче- ски преобразуется в пару (возврат каретки – переход на новую строку). Бинарные (или двоичные) файлы предназначены для хранения только числовых значений данных. Структура такого файла определяется программно. Функции для работы с файлами размещены в библиотеках stdio.lib ( #include ) и io.lib ( #include ). Каждый файл должен быть связан с указателем, который имеет тип FILE и используется во всех операциях с файлами. Формат объявления указателя на файл следующий: FILE *указатель на файл; Макрос NULL определяет пустой указатель. Макрос EOF , часто определяемый как – 1 , является значением, возвращае- мым тогда, когда функция ввода пытается выполнить чтение после конца файла. Макрос FOPEN_MAX определяет целое значение, равное максимальному числу одновременно открытых файлов. 42 6.3. Функции для работы с файлами Перед началом работы с файлом его необходимо открыть функцией FILE *fopen (const char * имя _ файла , const char * режим_открытия ); которая связывает файл с потоком и возвращает указатель на открытый файл. Имя_файла и режим_открытия – указатели на строки символов, содержащие соответственно путь к файлу, его имя и режим открытия файла. Допустимые режимы: r открытие текстового файла для чтения; w cоздание текстового файла для записи; a добавление информации в конец текстового файла. При работе с текстовыми файлами к символу, указывающему режим от- крытия, добавляется символ « t » (по умолчанию), а при работе с бинарными – « b ». Если необходимо читать и записывать в файл, то добавляется символ « + ». При возникновении ошибки во время открытия файла функция fopen возвра- щает значение NULL После завершения работы с файлом его необходимо закрыть функцией int fclose (FILE * указатель_на _файл ); которая закрывает поток, открытый с помощью вызова fopen () , и записывает в файл данные, оставшиеся в дисковом буфере. Результатом работы функции может быть значение нуля (успешная операция закрытия) или EOF (ошибка). Доступ к файлу после выполнения функции будет запрещен. Функция int fcloseall (void); закрывает все открытые файлы и возвращает количество закрытых файлов или EOF , если возникает ошибка. Функция int putc (int символ , FILE * указатель_на _файл ); записывает один символ в текущую позицию указанного открытого файла. Функция int getc (FILE * указатель_на _файл ); читает один символ из текущей позиции указанного открытого файла. Функция int feof (FILE * указатель_на _файл ); возвращает отличное от нуля значение ( true ), если конец файла не достигнут, и ноль ( false ), если достигнут конец файла. Функция int fputs (const char * строка , FILE * указатель_на _файл ); записывает строку символов в текущую позицию указанного открытого файла. Функция char *fgets (char * строка , int длина , FILE * указатель_на _файл ); 43 читает строку символов из текущей позиции указанного открытого файла до тех пор, пока не будет прочитан символ перехода на новую строку или количе- ство прочитанных символов не станет равным длина – 1 Функция int *fprintf (FILE * указатель_на _файл , const char * управляющая_строка ); записывает форматированные данные в файл. Управляющая_строка определя- ет строку форматирования аргументов, заданных своими адресами. Обычно эта строка состоит из последовательности символов « % », после которых следует символ типа данных: I или i десятичное, восьмеричное или шестнадцатеричное целое; D или d десятичное целое; U или u десятичное целое без знака; E или e действительное с плавающей точкой; s строка символов; c символ. Функция int *fscanf (FILE * указатель_на _файл |