Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
КПиЯП.docx
Скачиваний:
13
Добавлен:
25.09.2019
Размер:
75.59 Кб
Скачать

Операторы для работы с указателями

Существуют два оператора: разыменования указателя-*, второй- оператор получения адреса- &. Оператор получения адреса называется унарным

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&&currentPtr->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 узла называются узлами симблингами. Узел не имеющий потока называется листом. Дерево можно обойти способами:

  1. Порядковая выборка- левая, корень, правая

  2. Предварительна выборка- корень, левая, правая

  3. Отложенная выборка- левая, правая, корень

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;