- •Управляющие структуры
- •Массивы
- •Рекурсия. Макросы. Уловная компиляция
- •Операторы для работы с указателями
- •Присваивание указателей
- •Объектно-ориентированные модели. Составные части объектного подхода
- •Форматирование ввод/вывод
- •Использование манипулятора
- •Конструкторы и деструкторы
- •Множественное наследование
- •Полиморфизм, реализация полиморфизма через наследование
- •Перегрузка бинарных операторов
Операторы для работы с указателями
Существуют два оператора: разыменования указателя-*, второй- оператор получения адреса- &. Оператор получения адреса называется унарным
M=&count;
Является антиподом оператора получения адреса и возвращает значение хранящееся по указанному адресу
A=*m;
Указатель всегда ссылается на переменную правильного типа, например если в программе объявлен указатель на целочисленную переменную компилятор полагает, что адрес, который в нём содержится относится к переменной типа инт. При попытке сослаться на переменную другого типа или присвоить переменной другого типа, программа откомпилируется но результата не даст
Можно выполнять арифметические действия:
-увеличить/уменьшить
-складывать или вычитать с указателями целые числа
-указатели можно вычитать один из другого
-указатель можно присвоить один другому
-указатели можно сравнивать
-УМНОЖЕНИЕ И ДЕЛЕНИЕ УКАЗАТЕЛЕЙ ЗАПРЕЩЕНО
Присваивание указателей
Указатель можно присвоить другому указателю, если они оба имеют одинаковый тип. Исключением из этого правила является указатель на void*, который является общим и способен представлять указатель любого типа. Указатель на void* не может быть раименован (не увидим адреса)
Int v[10];
3000 |
3004 |
3008 |
3012 |
3016 |
|||
[0] |
[1] |
[2] |
[3] |
||||
Vptr=v;
Vptr=&v[0];
1.Определить сумму н чисел ряда Фибоначчи
Int mas[20]= {0};
Int main ()
{int n=0;
Cout<<fib(n)<<endl;
System (“pause”);
}
fib (int n)
Int a=0
If (n<3) return 1;
Else return 0;
2.Продемонистрировать возможности макросов с параметрами
Inline void func()
{cout<<”text”;
}
Int main
{func();
}
Указатели и массивы. Массивы указателей. Указатели на функции. Динамические массивы
Int Y[10];
*vptr= Y[0];
*(vptr+3)
Массивы могут содержать указатели типичным использованием такой структуры является формирование массива строк каждый элемент такого массива- строка, но поскольку по существу строка является указателем на первый символ в действительности в таком массиве каждый элемент будет указателем
Char *sait[4]= {“Червы ”,”Бубны”,”Трефы”,”Пики”}
Такое объявление позволяет обеспечить доступ к трокам разной длинны, т.е. реализуется одна из возможностей сипп- организация гибких программ.
Динамические массивы
Если не известно сколько элементов в массиве, следует использовать динамические массивы, т.к. память под каждый элемент выделается по мере его создания
New(malloc)
Delete(calloc)
Int n=10;
In t *a= new int [n];( Int *b= (int *) malloc(n*sizeof(int))- для другой среды)
int **a= new int*[nrow]
For (i=0; i<nrow;i++)
A[i]= new int[ncol];
Delite (a[]);
Указатели на функции
Указатель на функцию содержит адрес функции в памяти. Имя функции является начальным адресом её кода. Указателем на функции можно передавать функции, возвращать из функции, хранить в массивах и присваивать другим указателям на функции. Типичным применением указателей на функции являются системы меню. Каждая позиция обслуживается определённой функцией. Указатели на каждую функцию хранятся в массиве указателей на функцию. Индекс пользователя используется как индеек массива, а указатель массива для вызова массива
Void f1 (int);
Void f2 (int);
Void f3 (int);
Int main ()
{void (*f[3])(int)={f1,f2,f3}; // массив указатель так задаётся
Int ch;
Cout<<”Ввод числа между о и 2, 3- выход”;
While (ch>=0 && ch<3)
{*f[ch](ch);
Cin>>ch;}
Cout<<”Вы ввели 3 для выхода”;
Return 0;}
1.Определить сумму н элементов вещественного массива, расположенную правее последнего отрицательного
2. найти произведение элементов массива, расположенных между вторым и предпоследним отрицательным элементом массива
3. дана целочисленная матрица, отсортировать её по возрастанию или убыванию в зависимости от выбора пользователя
Задача 1:
Double* arr=new double;
Int n;
Cin>>n;
Int i=0;
For (double* a= arr; a<arr+n*8;A+=8)
{cout<<”A[“<<++I<<”]=”;
Cin>>*a;}
Double sum=-1;
For (double*A=arr;A<arr+n*8;A+=8)
{if (*A<0)
Sum=o;
Else if (sum>=0)
Sum=*A;
}
Sum=(sum<0)?0:sum;
Cout<<sum;
Задача 2:
Int n=10,k,m,kol=0,s=1;
Int*a=new int[n];
For(aint i=-;i<n;i++)
Cin>>a[i];
For (int i=0; i<=n;i++)
{if a[i]<0 {k=I;kol++}&&(kol=2)
Kol=0;
For ( int i=0;n>=0;i--)
If (a[i]<0)}
Динамические структуры данных
Динамические структуры бывают линейные и нелинейные линейные- списки, очереди стеки. Нелинейные – деревья.
Список- линейный набор ссылающихся на себя структур называемых узлами и объеденных указателем связкой. Доступ к связанному списку обеспечивается указателем на 1 узел списка. Доступ к последующим элементам производится через указатель связки хранящимся в каждом узле. По общему соглашению указатель связки устанавливается в нулл.
Примером списков
Пример.
/* операции над списком */
#include <stdio.h>
#include <stdlib.h>
struct listNode ( /*структура со ссылкой на себя */
char data;
struct listNode *nextPtr;
};
typedef struct listNode LISTNODE;
typedef LISTNODE *LISTNODEPTR;
void insert(LISTnoDEPTR *, char);
char delete (LISTNODEPTR *, char);
int isEmpty (LISTNODEPTR);
void printList (LISTNODEPTR);
void instructions (void);
main ()
{ LISTNODEPTR startPTr = NILL;
int choice;
char item;
instructions (); /* вывести меню */
printf (“? “);
scanf (“%d”, &choice);
while (choice !=3){
switch(choice){
case 1:
printf (“Enter a character: “);
scanf (“\n%c”, &item);
insert (&startPtr, item);
printList(startPtr);
break;
case 2:
if (1isEmpty(startPtr)){
printf(“Enter character to be deleted: “);
scanf (“\n%c”, &item);
if (delete (&startPtr,item)){
printf(“%c deleted.\n”, item);
printList (startPtr):
}
else printf(“%c not found.\n\n”,item);
}
else printf(“List is empty.\n\n”);
break;
default:
printf(“invalid chaice\n\n”);
instructions();
break;
}
printf(“? “);
scanf (“%d”, &choice);
}
printf(“End of run.\n”);
return 0;
}
/* Распечатка инструкции */
void instructions (void)
{ printf(“enter your choice:\n”
“ 1 to insert an element into the list. \n”
“2 to delete an element from the list. \n”
“3 to end. \n”);
}
/* Вставка нового значения в упорядоченный список */
void insert (LISTNODEPTR *sPtr, char value)
{head}
LISTNODEPTR newPtr, previousPtr, currentPtr;
newPtr=malloc (sizeof(LISTNODE));
if (newPtr=NULL) {/* доступна ли память? */
newPtr->data=value;
newPtr->nextPtr=NULL;
previousPtr=NULL;
currentPtr=*sPtr;
while (currentPtr !=NULL&&value>currentPtr->data) {
previousPtr=currentPtr; /* перейти … */
currentPtr=currentPtr->nextPtr; /* … к следующему */
}
if (previousPtr==NULL){
newPtr->nextPtr=*sPtr;
*sPtr=newPtr;
}
else {
previousPtr->nextPtr=newPtr;
newPtr->nextPtr=currentPtr;
}
}
else printf (“%c not inserted. No memory available. \n”, value);
}
/* Удаление элемента списка */
char delete (LISTNODEPTR *sPtr, char value)
{ LISTNODEPtR previousPtr, currentPtr, temPtr;
if (value == (*sPtr)->data) {
tempPtr=*sPtr;
*sPtr=(*sPtr)->nextPtr; /* отсоединить узел */
free(tempPtr); /* освободить узел */
return value;
}
else {
previousPtr = *sPtr;
currentPtr=(*sPtr)->nextPtr;
while (currentPtr !=NULL&¤tPtr->data !=value) {
previousPtr=currentPtr; /* перейти… */
currentPtr = currentPtr->nextPtr; /* … к следующему */
}
if (current Ptr!=NULL) {
tempPtr=currentPtr;
previousPtr->nextPtr=currentPtr->nextPtr;
free(tempPtr);
return value;
}
}
return ‘\0’;
}
/* Возвратить 1, если список пуст, в протином случае – 0 */
int isEmpty(LISTNODEPTR sPtr)
{
return sPtr==NULL;
}
/* Print the list */
void printList (LISTNODEPTR currentPtr)
{
if (currentPtr ==NULL)
printf(“List is empty.\n\n”);
else {
printf(“The list is:\n”);
while (currentPtr !=NULL) {
printf(“%c-> “,currentPtr->data);
currentPtr=currentPtr->nextPtr;
}
printf(“NULL\n\n”);
}
}
Деревья – нелинейная структура узлы которого содержат 2 или более связок. Потомки 1 узла называются узлами симблингами. Узел не имеющий потока называется листом. Дерево можно обойти способами:
Порядковая выборка- левая, корень, правая
Предварительна выборка- корень, левая, правая
Отложенная выборка- левая, правая, корень
0 |
1 |
2 |
3 |
|
|
|
|
|
|
… |
Маркер конца байт |
Файл- группа связанных записей
Файлы в С и С++ рассматриваются как последовательность байт, оканчивающаяся маркером конца байт . когда файл открывается, ему ставится в соответствие поток.
Поток- абстрактное понятие, относящееся к любому переносу данных от источника к приёмнику.
В начале исполнения программы автоматически открывается три файла и связанные с ними потоки стандартный ввод, стандартный вывод и стандартная ошибка. Открытый файл возвращает указатель на структуру FILE <stdio.h> или <iostream> {<ifstream>,<ofstream>,<fstream> }/ структура типа файл включает- дескриптор файла, т.е. индекс в массиве ОС, называемом таблицей открытых файлов
Режим открытия файлов(С) |
|
Режим |
Описание |
R |
Режим открытия файлов для чтения |
W |
Открытие файлов для записи(если файл существует- содержимое стирается) |
A |
Открывает или создаёт файл для записи в конец файла |
R+ |
Открывает файл для обновления |
W+ |
Создаёт файл для обновления ( если файл существует- его содержимое удаляется) |
A+ |
Открывает или создаёт файл для обновления, т.е. запись производится в конец файла |
В С не предусмотрено возможность задать структуру файла, реализованная как часть языка, т.е. вы сами заботитесь о том что бы создать файл для работы в конкретном приложении.
FILE *cfptr;
Режим открытия файлов(C++) |
|
Режим |
Описание |
Ios::in |
Открыть файл для ввода |
Ios::out |
Открыть файл для вывода |
Ios::app |
Записать данные в конец файла |
Ios::ate |
Переместиться в конец исходного открытого файла (данные могут записаться в любое место) |
Ios::trune |
Удалять содержимое файла, если он существует |
Ios::no create |
Если файл не существует, то операция его открытия не выполняется |
Ios::noreplace |
Если файл существует, то операция его открытия не выполняется |
Main()
{int account;
Char name [30];
Float balance;
FILE *cfptr;
If ((cfptr=fopen(“clients.dat”,”w”))==NULL)
Cout<<”file couldnot be open /n”
Else
{cout<< “enter the account, name and balance /n”;
Cin>>account>>name>>balance;
While(!feof(stdin))
{fprintf(cfptr,”%d %s %.2f /n”, account, name, balance);
Cin>>account>>name>>balance);}
Fclose(cfptr);
}
Return 0;
}
C++
Ofstream filename (“name.txt”,ios::app)
Filename.close();
Filename<<a<<i<<”write infothe file”;
filename>>a>>I;
Файлы с произвольным доступом обычно имеют фиксированную длину, что позволяет получить к ним непосредственный доступ без поиска по всем записям fwrite- пересылает в файл заданное число байт, начиная с указанного адреса памяти, fread- считывает из файла в память заданное число элементов
Seekg (n)- функция для пере
Seekg (n,ios::cur)
Seekg (n,ios::end)
Матрице размерностью mxn отсортировать элементы побочной диагонали в следующем порядке:
Сначала отрицательные значения, потом нули, потом положительные. Матрицу заполнить из файла вывод осуществить как из файла так и в файл
Ofstream(“file.txt”, ios.out);
P<<str;
