WWW.DISSERS.RU

БЕСПЛАТНАЯ ЭЛЕКТРОННАЯ БИБЛИОТЕКА

   Добро пожаловать!


Pages:     | 1 |   ...   | 4 | 5 || 7 | 8 |   ...   | 11 |

i1 j// P= \Pi_{i=1}^n \Sigma_{j=1}^m a_{ij} #include "stdafx.h" #include #include // для srand() using namespace std;

const int N=5;

const int M=6;

int main(int argc, _TCHAR* argv[]) { double a[N][M]; int i,j;

// заполняем матрицу случайными числами srand(time(NULL)); /* значение времени в генератор случайных чисел */ for (i=0;i

double p,s;

p=1.0;// произведение for (i=0;i

p *= s;

} // Вывод результатов for (i=0;i cout<<"\n"; // новая строка матрицы } cout<<"\n p = "<

return 0;

} Пример. Элементы матрицы вводятся с клавиатуры. Вычисляется след матрицы (сумма диагональных элементов).

// След матрицы const int N=3;

double a[N][N]; int i,j;

// Блок ввода значений for (i=0;i

Многомерные массиы могут быть безразмерными – можно не указывать размер самого левого измерения, если при объявлении используется инициализатор.

Пример. Безразмерный двумерный массив.

// Магический квадрат const int M=4; /* граница 2-го измерения массива*/ int mag[][M] ={ {16,3,2,13}, {5,10,11,8}, {9,6,7,12}, {4,15,14,1} };

// Вычисляем границу первого измерения:

int n = /* граница 1-го измерения массива*/ sizeof(mag)/* память под весь массив*/ /(sizeof(int)*M)/* память, занятая строкой массива*/;

for (int i=0;i

cout<<"\n"; // новая строка матрицы } Указатели Указатель – это переменная, содержащая адрес другой переменной.

Применяя операцию * (операция разыменования), получаем значение, записанное по данному адресу. С помощью операции &, применнной к переменной, можно узнать адрес, по которому эта переменная хранится в памяти.

При объявлении указателя также используется *, кроме того, указывается тип данных, на которые ссылается указатель.

Тип_данных *имя_указателя;

Пример. Объявление указателей и обращение к памяти. Значение переменной px – адрес памяти, а *px – данные, записанные по адресу px.

int x=100; // переменная cout<<"\n x="<

int* px; // указатель на int px = &x; // указателю присвоили адрес переменной x *px =200; /* Изменения значения, записанного по адресу px */ cout<<"\n px="<

cout<<"\n *px="<<*px<<" x="<

При создании указателя память выделяется только для хранения адреса. Для выделения памяти под данные используется оператор new (или функция malloc()). Выделение памяти оператором new:

указатель = new Тип Оператор new выделяет память в количестве, необходимом для хранения данных указанного типа. Указатель в левой части оператора присваивания должен быть указателем на тот же тип данных.

Пример. Оператором new выделена память для данных типа int, с помощью оператора delete выполнено освобождение памяти.

#include using namespace std;

int main() { setlocale(LC_CTYPE, "rus");//русификация консоли int *p;

p = new int; /* Выделение памяти для целого. Далее выполняется проверка, удачно ли произошло выделение памяти, если нет – выход из программы с кодом завершения 1: */ if(!p) { cout << "\nНедостаточно памяти\n";

return 1;

} *p = 1000;

cout << "По адресу p="<

delete p; // освобождение памяти return 0;

} Пример. Использование операторов new и delete #include using namespace std;

int main() { double *px = new double;

*px = 10.102;

int *pn = new int;

*pn = 100000;

char *pc = new char;

*pc = 'A';

cout << *px << '\t' << *pn << '\t' << *pc;

cout << '\n';

delete px;

delete pn;

delete pc;

return 0;

} Возможность выделения памяти с помощью оператора new появилась в C++, в языке C для этой цели используется функция malloc():

указатель = malloc(количество байт);

Поскольку указатель типизированный, т.е. ссылается на блок памяти, занятой данными определенного типа, требуется выполнить явное приведение типа значения функции. Кроме того, функция sizeof() поможет правильно определить необходимое количество байт.

указатель = (Тип *) malloc(sizeof(Тип));

Пример. Выделение памяти функцией malloc().

setlocale(LC_CTYPE, "rus");//русификация консоли int * p;

p = (int *) malloc(sizeof(int)); /* Выделение памяти для целого. */ if(!p) /* Неудача при выделении памяти */ { printf("\nНедостаточно памяти\n");

return 1;

} *p = 1000;

printf("По адресу p=%p записано: %d \n",p,*p);

free(p);

Замечание. Для вывода значений указателей в функции printf() можно использовать спецификатор формата %р, который отображает адреса в формате, используемом компилятором.

Как уже было отмечено, для обозначения переменной–указателя используется звздочка *. Пробелы между символом *, типом и именем переменной не имеют значения.

int *ptr;

int* ptr;

int * ptr;

Приведенные формы объявления указателя равносильны, предпочтения субъективные. При использовании первой формы объявления подчркивается, что *ptr имеет значение int. Во втором случае отмечается, что int* – это тип указатель на int.



Следует учитывать особенности использования инструкции, (запятая) при объявлении указателей. Так, объявление int * p1, p2;

создат один указатель p1 и переменную p2 типа int. Объявление int * p1, * p2;

создат два указателя p1 и p2.

Пример. Пример инициализации динамической переменной.

Значение, используеммое для инициализации, указано в круглых скобках оператора new.

#include using namespace std;

int main() { setlocale(LC_CTYPE, "rus");//русификация консоли int *p;

p = new int(5); // начальное значение равно if(!p) { cout << "\nНедостаточно памяти\n ";

return 1;

} cout<<"\n По адресу p="<

delete p; // освобождение памяти return 0;

} Для динамически размещаемого одномерного массива используется следующая форма оператора new:

p=new type [size] Для удаления динамически размещаемого одномерного массива используется оператор delete [] p;

Пример. Размещение массива из 5 целых чисел.

#include using namespace std;

int main() { setlocale(LC_CTYPE, "rus");//русификация консоли int *p;

int i;

p = new int [5]; // выделение памяти для 5 целых // Проверим, что память выделена if(!p) { cout <<"\nНедостаточно памяти\n";

return 1;

} for(i=0; i<5; i++) p[i] = i;

for(i=0; i<5; i++) { cout<<"Это целое, на которое указывает (p+"<

cout << p[i] << "\n";

} delete [] p; // освобождение памяти return 0;

} Арифметика указателей В C/C++ разрешены несколько арифметических операций с участием переменных-указателей. К указателям можно прибавлять и вычитать целые числа, выполнять операции инкремента и декремента, а также вычитать два указателя.

Увеличение и уменьшение указателя на целое число Увеличение указателя на 1, означает, что указатель будет ссылаться на следующий блок памяти, занятый переменной того же типа. Увеличение же указателя на целое число n, передвигает указатель на n блоков в сторону увеличения адресов.

Уменьшение указателя на целое число n, передвигает указатель на n блоков в сторону уменьшения адресов.

В примере Размещение массива из 5 целых чисел выражение p[i] используется для обращения к i-му элементу массива. Компилятор преобразует это выражение к виду *(p+i). Это означает, что к адресу p будет добавлено количество байт, занятых i элементами данного типа (в примере – тип int).

Вычитание указателей Можно вычитать два указателя одного и того же типа. Результат этой операции – количество данных, уместившихся между адресами, являющихся значениями этих указателей.

Пример. Выделяется блок для размещения 50 целых чисел.

Указателю ps присвоено значение p+10, т.е. этот указатель ссылается на блок данных, а значения адресов отличаются на число 40 (28 в шестнадцатеричной системе счисления). Указатель pf ссылается на 40 блок данных. Из одного указателя вычитается другой.

int *p, *ps, *pf;

p = new int [50];

for (int i=0;i<50;i++) *(p+i) = i * 2;

ps=p+10; pf=p+40;

cout<<"\n *ps="<<*ps<<" *pf="<<*pf;

cout<<"\n p="<

Пример. Указателю b присвоено значение указателя a. Однако, операция присваивания a=p будет воспринята компилятором как ошибка, поскольку, в отличие от b указатель a является именем массива.

const int N=5;

int *b;

b = new int [N];

int a[N]={10,20,30,40,50};

for(int i=0; i

cout<<"\n a: ";

for(int i=0; icout<<"\n b: ";

for(int i=0; i

b=a; // так можно cout<<"\n *(b+2)="<

/* a=p; // в так нельзя */ Указатели и многомерные массивы В многомерных массивах имя массива также указывает на первый элемент массива. Обращение к элементу массива, указанием его индексов, является сокращенной формой выражения с указателями. Пусть a – двумерный массив размера n*m, где n, m – заданные константы, тогда выражение a[i][j] преобразуется компилятором в операцию с указателями *(*(a+i)+j). Выражение a[i] является указателем на первый элемент строки с индексом i.

Пример.

const int N=3;

const int M=5;

setlocale(LC_CTYPE, "rus");//русификация консоли int a[N][M]={{0,1,2,3,4},{1,2,3,4,5},{2,3,4,5,6}};

cout<<"\n Первый элемент= "<<*(*a);

cout<<"\n a[2][3]="<<*(*(a+2)+3);

int *p;

p=a[2];// адрес первого элемента строки cout<<"\n p[3]="<<*(p+3);

Пример. Многоуровневая адресация. Обращение к одним и тем же данным с помощью массива и указателя на указатель. Указатели a и b имеют разные значения, но адреса строк a[i] и b[i] одинаковые, как следствие, обращения a[i][j] и b[i][j] дают одинаковый результат.

const int N=3;

const int M=5;

int a[N][M]={{0,1,2,3,4},{1,2,3,4,5},{2,3,4,5,6}};

int **b;

b= new int*[N];

for(int i=0; i

cout<<"\n b: \n";

for(int i=0; i

cout<<"\n";

} cout<<"\n a="<

cout<<"\n b="<

cout<<"\n a[0]="<

cout<<"\n b[0]="<

Динамические массивы Выделение памяти для массива в процессе компиляции называется статическим связыванием. Память под массив выделяется на этапе компиляции. С помощью оператора new можем создавать массив во время выполнения программы, размер массива также определяется на этапе выполнения программы. Такой массив называется динамическим, а процесс его создания – динамическим связыванием.

Пример. Размер массива устанавливается во время выполнения.

#include "stdafx.h" #include using namespace std;

int main(int argc, _TCHAR* argv[]) { int i,size;

cout<<"Size=";

cin>>size;

int * pz= new int[size];

for(i=0;i

delete [] pz; // освобождаем память return 0;

} Пример. Тот же пример, но память выделяется с помощью функции malloc().

#include "stdafx.h" #include #include using namespace std;

int main(int argc, _TCHAR* argv[]) { int i,size;

printf("\n Size=");

scanf("%d",&size);

int * pz= (int *) malloc(size * sizeof(int));

for(i=0;i

} int sum=0;

for(i=0;i

printf("summa=%d\n",sum);

free(pz); // освобождаем память return 0;

} Двумерные динамические массивы Пример. Размер матрицы вводится с клавиатуры во время выполнения программы. Память для размещения данных выделяется с помощью оператора new.

// Двумерный динамический массив n*m double **a;

int n, m;

setlocale(LC_CTYPE, "rus");//русификация консоли cout<<"\n Число строк=";

cin>>n;

cout<<"\n Число столбцов=";

cin>>m;

// Память для размещения данных:

a=new double* [n];

for (int i=0;i

// Заполняем случайными числами:

for (int i=0;i

// Печатаем:

for(int i=0; i cout<<"\n";

} Пример. Размер матрицы вводится с клавиатуры во время выполнения программы. Память для размещения данных выделяется с помощью функции malloc().

// Двумерный динамический массив n*m double **a;

int n, m;

int i,j;

setlocale(LC_CTYPE, "rus");

printf("\n Число строк=");

scanf("%d",&n);

printf("\n Число столбцов=");

scanf("%d",&m);

// Память для размещения данных:

a=(double **) malloc(n * sizeof(double *));

for (i=0;i

// Заполняем случайными числами for (i=0;i

// печатаем for(i=0; i

printf("\n");

} Структуры Данные различных типов можно объединить под одним именем с помощью структур.

Пример. Создается тип данных для хранения почтового адреса.

struct Address { char *name;

int num; // номер дома char *street; // улица char *city; // город int zip; // индекс };

Address drug;

Address *p=new Address;

Address gruppa[10];

drug.street ="Mushtary"; drug.city="Kazan";

Pages:     | 1 |   ...   | 4 | 5 || 7 | 8 |   ...   | 11 |










© 2011 www.dissers.ru - «Бесплатная электронная библиотека»

Материалы этого сайта размещены для ознакомления, все права принадлежат их авторам.
Если Вы не согласны с тем, что Ваш материал размещён на этом сайте, пожалуйста, напишите нам, мы в течении 1-2 рабочих дней удалим его.