bmstu_iu6_Cpp1 (823967), страница 16
Текст из файла (страница 16)
Разработать две подпрограммы, формирующую матрицу переменногоразмера и меняющую отрицательные элементы матрицы на их абсолютное значение. Тестировать эти подпрограммы.Для увеличения степени универсальности подпрограмм объявим матрицу с дополнительным вектором адресов строк (см. рисунок 4.3)Указатель int **M указывает на массив указателей int *M, каждый из элементовкоторого, в свою очередь адресует одномерный массив элементов целого типа.Оглавление104Так как размеры массивов нигде не указаны, память под массивы статически не выделяем. Выделение памяти осуществим во время выполнения программы, когда размерымассива станут известны.M*M*M[0]M[0]M[1][3]=>*(*(M+1)+3)*M[1]+3M[1]M[2]Рисунок 4.3 – Структура данных примера#include <locale.h>#include <stdio.h>#include <conio.h>#include <stdlib.h>// Функция формирования и ввода матрицыint **matr(int &k,int &p){int **m,i,j;printf("Введите размеры матрицы:\n");scanf("%d %d",&k,&p);printf("Введите %2d строки по %2d елементов:\n",k,p);m=new int *[k];// выделение памяти под массив указателейfor (i=0;i<k;i++){m[i]=new int[p]; // выделение памяти под каждую строкуfor (j=0;j<p;j++)scanf("%3d",*(m+i)+j);}return m; // возврат сформированной матрицы}// Функция замены отрицательных элементов абсолютной величинойvoid sortmas(int **m,int n,int k){int i,j;for(i=0;i<n;i++)for(j=0;j<k;j++)if (m[i][j]<0) m[i][j]=abs(m[i][j]);}Оглавление105// Основная программаint main(int argc, char* argv[]){setlocale(0,"russian");int n,l,**mat,i,j;mat=matr(n,l);// вызов функции формирования матрицыprintf("\n===== Введеная матрица =====\n");for(i=0;i<n;i++)for(j=0;j<l;j++)printf("%4d%c",mat[i][j],(j==l-1)?'\n':' ');sortmas(mat,n,l);// вызов функции изменения матрицыprintf("\n=== Результирующая матрица ==\n"); for(i=0;i<n;i++)for(j=0;j<l;j++)printf("%4d%c",mat[i][j],(j==l-1)?'\n':' ');// удаление матрицы и освобождение памятиfor (i=0;i<n;i++) delete[] mat[i];delete[] mat;puts("Нажмите любую клавишу для завершения...");_getch();return 0;}4.3.2 Параметры-функцииКак уже отмечалось ранее, функция характеризуется типом возвращаемого значения,именем и сигнатурой.
Имя функции – это указатель, хранящий ее адрес, который можетбыть присвоен другому указателю. Однако при объявлении для нового указателя долженбыть задан тот же тип, что и возвращаемое функцией значение, и тот же список параметров с точностью до типов формальных параметров (имена параметров могут различаться).Указатель на функцию объявляется следующим образом:<Тип функции>(* <Имя>)(<Спецификация параметров>);Например:int (*ptrfun)(int,int);Оглавление106При объявлении указатель на функцию может быть инициализирован, но в качествезначения должен быть указан адрес функции, тип и сигнатура которой соответствуютопределяемому указателю, например:Описание функций:char f1(char){…}char f2(int){…}void f3(float){…}int f4(float){…}int f5(int){…}Объявление указателей на функции:void (*ptr1)(float)=f3; // инициализированный указательint (*ptr2)(int);char (*ptr3)(int);Присваивание указателей:ptr2=f5; ptr3=f2; // корректноеprt2=f4; ptr3=f1; // некорректное: несоответствие типов или спецификацийПример 4.12.
Разработать подпрограммы выполнения элементарных операций.#include <locale.h>#include <stdio.h>#include <conio.h>int add(int n,int m) {return n+m;}int sub(int n,int m) {return n-m;}int mul(int n,int m) {return n*m;}int div(int n,int m) {return n/m;}int main(int argc, char* argv[]){setlocale(0,"russian");int (*ptr)(int,int);// указатель на функциюint a=6, b=2; char c='+';while (c!=' '){printf("%d%c%d=",a,c,b);switch (c){case '+': ptr=add; c='-';break;case '-': ptr=sub; c='*';break;Оглавление107case '*': ptr=mul; c='/';break;case '/': ptr=div; c=' ';}printf("%d\n",a=ptr(a,b));// вызов функции по указателю}puts("Нажмите любую клавишу для завершения...");_getch();return 0;}Пример 4.13.
Написать подпрограмму вычисления значения интеграла произвольных функций одной переменной на отрезке a,b с точностью eps.#include <locale.h>#include <stdio.h>#include <conio.h>#include <math.h>float (* funuk)(float);// указатель на функцию// Функция расчета интеграла методом прямоугольниковfloat integral(float(*funuk)(float),float a,float b,float eps){int i,n=5,k=0; float s1,s2=1.0e+10,x,d;d=(b-a)/n;do{s1=s2;x=a;s2=0;n=n*2; d=d/2;k++;for(i=1;i<=n;i++){s2=s2+funuk(x);x=x+d;}s2=s2*d;}while(fabs(s2-s1)>eps);return s2;}Оглавление108// Описание функций, для которых считается интегралfloat f1(float x){return x*x-1;}float f2(float x){return 2*x;}int main(int argc, char* argv[]){setlocale(0,"russian");float a,b,eps;puts("Введите a,b,eps для функции y=x^2-1:");scanf("%f %f %f",&a,&b,&eps);//вызов функции расчета интеграла для функции f1printf("Значение интеграла=%10.5f\n",integral(f1,a,b,eps));puts("Введите a,b,eps для функции y=2*x:");scanf("%f %f %f",&a,&b,&eps);// вызов функции расчета интеграла для функции f2printf("Значение интеграла=%10.5f\n",integral(f2,a,b,eps));puts("Нажмите любую клавишу для завершения...");_getch();return 0;}Результаты работы программы (вводимые данные выделены полужирным):Введите a,b,eps для функции y=x^2-1:1 2 0,001Значение интеграла1,33285Введите a,b,eps для функции y=2*x:1 2 0,001Значение интеграла=2,99928Нажмите любую клавишу для завершения...Контрольные вопросы к главе 41.
Что такое объявление и описание функции и чем они отличаются? Что такое прототипфункции?Ответ.2. Назовите способы передачи данных в функции.Ответ.Оглавление1093. Как вернуть результат работы функции? Какую роль в этом играет оператор возврата?Ответ.4. Что такое класс памяти и что он определяет? Какие классы памяти Вы знаете?Ответ.5. Чем отличаются статические переменные от автоматических?Ответ.6. Как передать в подпрограмму параметр массив или строку?Ответ.7.
Что такое модуль в С++ и какова его структура?Ответ.8. Что такое заголовочный файл и как его подключить к программе?Ответ.9. Как передать в подпрограмму многомерный массив произвольного размера?Ответ.10.Что такое указатель на функции и как его можно использовать при работеподпрограмм?Ответ.Оглавление1105ФАЙЛОВАЯ СИСТЕМА5.1 Механизм выполнения операций ввода/вывода. Типы файловФайл – последовательность информационных записей. Такая последовательность может быть записана на дисках внешней памяти (магнитных, оптических и т.д.) или появляться в результате обмена информацией с внешними устройствами (клавиатура, устройство вывода на печать, дисплей и т.д.).
Соответственно различают дисковые файлы и логические устройства.Логически файлы представляют собой длинную строку байтов, которая разбиваетсяна части (записи) в зависимости от типа файла. В С++ определены два типа файлов: текстовые и двоичные.Текстовые файлы состоят из символьных строк переменной длины, заканчивающихся маркером «Конец строки» (двухбайтовый код: 13, 10).Двоичные файлы представляют собой последовательность компонентов фиксированного размера, например, целых чисел, структур и т. д., записанных в файл без преобразования к символьному виду.Операции ввода/вывода с файлами, как правило, выполняются через специальныеобласти оперативной памяти – буферы. При первом обращении к операции ввода файловая система переписывает в буфер блок информации размером с буфер, и затем ввод осуществляется уже из буфера.
При выводе – в буфере накапливается выводимая информация,а операция вывода выполняется при заполнении буфера. Это позволяет существенно сократить время выполнения операций ввода/вывода с медленными устройствами. Размербуфера, определяемый типом устройства, вместе с адресом буфера и прочей необходимойинформацией хранятся в специальной таблице, формат которой определен в структуретипа FILE.5.2 Объявление, открытие и закрытие файловПрограммирование операций ввода/вывода с файлами начинается с объявленияфайловой переменной:FILE *<Файловая переменная>; // объявляется указатель на таблицу FILEОглавление111Перед работой файл должен быть открыт. При открытии файла выделяется памятьпод таблицу, на которую указывает файловая переменная, и частично заполняются ее поля.Операцию выполняет специальная функция:<Файловая переменная>=fopen(<Имя файла>,<Операция [+] [Тип]>);где<Имя файла> – строковая переменная или константа – полное имя файла с путем –при указании имени файла без пути файл ищется только в текущем каталоге;<Операция[+]> – кодируется следующим образом:r – ввод из существующего файла;w – вывод с очисткой файла или создание нового файла для вывода;a – добавление к существующему файлу или создание файла для вывода;r+ – ввод/вывод в существующий файл;w+ – ввод/вывод в существующий или создание нового файла для ввода/вывода;a+ – ввод/добавление к существующему или создание файла для ввода/вывода.<тип> – тип файла:t – текстовый файл (принимается по умолчанию);b – двоичный файл.Примеры.а) объявление и открытие файла на текущем диске для записи:FILE *f;f=fopen(″abc.txt″,″w″); // файл в текущем каталогеб) открытие файла для чтения с проверкой существования:if((f=fopen(″f:\\iva\\text.txt″,″r″))!=NULL) ...Открытый файл обязательно должен быть закрыт.
При закрытии файла вывода остав-шиеся записи из буфера переписываются в файл, и если файл новый, то формируется соответствующий элемент оглавления. Поэтому, прежде чем переименовывать или удалятьфайл, его обязательно нужно закрыть:fclose(<Файловая переменная>); // функция возвращает 0, если закрытие// прошло успешно, и -1, если обнаружена ошибка.5.3 Работа с файловым указателемОсобую роль при программировании операций с файлом играет файловый указатель, который определяет, в какое место файла выводится запись или откуда она вводится. При последовательной обработке файла файловый указатель является счетчиком ужеОглавление112прочитанных или записанных байт.
Имеются специальные функции, которые позволяютработать с файловым указателем:а) определение значения файлового указателя:long ftell(FILE *stream); // возвращает текущее значение файлового// указателя;б) установка файлового указателя на начало файла:int rewind(FILE *stream); // файловый указатель устанавливается// на начало файла (см. пример в разделе 5.4.3);в) установка файлового указателя в указанное место:int fseek(FILE *stream,long offset,int whenсe);Параметр whenсe определяет, откуда отсчитывается смещение указателя offset:0 – от начала файла; 1 – от текущей позиции; 2 – от конца файла (см. пример в разделе5.4.1).5.4 Текстовые файлы. Стандартные текстовые файлыТекстовый файл представляет собой последовательность символьных записей переменной длины.