Главная

Популярная публикация

Научная публикация

Случайная публикация

Обратная связь

ТОР 5 статей:

Методические подходы к анализу финансового состояния предприятия

Проблема периодизации русской литературы ХХ века. Краткая характеристика второй половины ХХ века

Ценовые и неценовые факторы

Характеристика шлифовальных кругов и ее маркировка

Служебные части речи. Предлог. Союз. Частицы

КАТЕГОРИИ:






Реалізація вказівників у програмах . Розадресація та розіменування . Застосування вказівників у масивах .

ЗВІТ

З навчальної практики

«Основи програмування та алгоритмічні мови»

 

 

Виконав студент групи 230ПР

Підпис _____ Дубовий В.

«___» _______ 2012р.

Перевірила:

_______ Проскура

Світлана Леонідівна

«___» _______ 2012р.

 

 


Зміст:

  1. Організація динамічної пам’яті Принцип організаціїї розподілу динамічної пам’яті. Команди new i delete. Пошук, сортування та впорядковування елементів динамічних одновимірних масивів.................................................. 2
  2. Реалізація вказівників у програмах. Розадресація та розіменування. Застосування вказівників у масивах..................................................... 4
  3. Практичне завдання № 1.................................................. 6
  4. Створити текстовий файл, що містить літери латинського алфавіту. Підрахувати кількість рядків, що починаються і закінчуються однієї і тією же літерою................ 7

 


Організація динамічної пам’яті Принцип організаціїї розподілу динамічної пам’яті. Команди new i delete. Пошук, сортування та впорядковування елементів динамічних одновимірних масивів

В С++ объекты могут быть размещены либо статически – во время компиляции, либо динамически – во время выполнения программы, путем вызова функций из стандартной библиотеки. Основная разница в использовании этих методов – в их эффективности и гибкости. Статическое размещение более эффективно, так как выделение памяти происходит до выполнения программы, однако оно гораздо менее гибко, потому что мы должны заранее знать тип и размер размещаемого объекта. К примеру, совсем не просто разместить содержимое некоторого текстового файла в статическом массиве строк: нам нужно заранее знать его размер. Задачи, в которых нужно хранить и обрабатывать заранее неизвестное число элементов, обычно требуют динамического выделения памяти.
До сих пор во всех наших примерах использовалось статическое выделение памяти. Скажем, определение переменной ival

int ival = 1024;

заставляет компилятор выделить в памяти область, достаточную для хранения переменной типа int, связать с этой областью имя ival и поместить туда значение 1024. Все это делается на этапе компиляции, до выполнения программы.
С объектом ival ассоциируются две величины: собственно значение переменной, 1024 в данном случае, и адрес той области памяти, где хранится это значение. Мы можем обращаться к любой из этих двух величин. Когда мы пишем:

int ival2 = ival + 1;

то обращаемся к значению, содержащемуся в переменной ival: прибавляем к нему 1 и инициализируем переменную ival2 этим новым значением, 1025. Каким же образом обратиться к адресу, по которому размещена переменная?
С++ имеет встроенный тип “указатель”, который используется для хранения адресов объектов. Чтобы объявить указатель, содержащий адрес переменной ival, мы должны написать:

int *pint; // указатель на объект типа int

Существует также специальная операция взятия адреса, обозначаемая символом &. Ее результатом является адрес объекта. Следующий оператор присваивает указателю pint адрес переменной ival:

int *pint;

pint = &ival; // pint получает значение адреса ival

Мы можем обратиться к тому объекту, адрес которого содержит pint (ival в нашем случае), используя операцию разыменования, называемую также косвенной адресацией. Эта операция обозначается символом *. Вот как можно косвенно прибавить единицу к ival, используя ее адрес:

*pint = *pint + 1; // неявно увеличивает ival

Это выражение производит в точности те же действия, что и

ival = ival + 1; // явно увеличивает ival

В этом примере нет никакого реального смысла: использование указателя для косвенной манипуляции переменной ival менее эффективно и менее наглядно. Мы привели этот пример только для того, чтобы дать самое начальное представление об указателях. В реальности указатели используют чаще всего для манипуляций с динамически размещенными объектами.
Основные отличия между статическим и динамическим выделением памяти таковы:

  • статические объекты обозначаются именованными переменными, и действия над этими объектами производятся напрямую, с использованием их имен. Динамические объекты не имеют собственных имен, и действия над ними производятся косвенно, с помощью указателей;
  • выделение и освобождение памяти под статические объекты производится компилятором автоматически. Программисту не нужно самому заботиться об этом. Выделение и освобождение памяти под динамические объекты целиком и полностью возлагается на программиста. Это достаточно сложная задача, при решении которой легко наделать ошибок. Для манипуляции динамически выделяемой памятью служат операторы new и delete.

Оператор new имеет две формы. Первая форма выделяет память под единичный объект определенного типа:

int *pint = new int(1024);

Здесь оператор new выделяет память под безымянный объект типа int, инициализирует его значением 1024 и возвращает адрес созданного объекта. Этот адрес используется для инициализации указателя pint. Все действия над таким безымянным объектом производятся путем разыменовывания данного указателя, т.к. явно манипулировать динамическим объектом невозможно.
Вторая форма оператора new выделяет память под массив заданного размера, состоящий из элементов определенного типа:

int *pia = new int[4];

В этом примере память выделяется под массив из четырех элементов типа int. К сожалению, данная форма оператора new не позволяет инициализировать элементы массива.
Некоторую путаницу вносит то, что обе формы оператора new возвращают одинаковый указатель, в нашем примере это указатель на целое. И pint, и pia объявлены совершенно одинаково, однако pint указывает на единственный объект типа int, а pia – на первый элемент массива из четырех объектов типа int.
Когда динамический объект больше не нужен, мы должны явным образом освободить отведенную под него память. Это делается с помощью оператора delete, имеющего, как и new, две формы – для единичного объекта и для массива:

// освобождение единичного объекта

delete pint;

// освобождение массива

delete[] pia;

Что случится, если мы забудем освободить выделенную память? Память будет расходоваться впустую, она окажется неиспользуемой, однако возвратить ее системе нельзя, поскольку у нас нет указателя на нее. Такое явление получило специальное название утечка памяти. В конце концов программа аварийно завершится из-за нехватки памяти (если, конечно, она будет работать достаточно долго). Небольшая утечка трудно поддается обнаружению, но существуют утилиты, помогающие это сделать.

Реалізація вказівників у програмах. Розадресація та розіменування. Застосування вказівників у масивах.

В самом простом случае оператор определения объекта состоит из спецификатора типа и имени объекта и заканчивается точкой с запятой. Например:

double salary;

double wage;

int month;

int day;

int year;

unsigned long distance;

В одном операторе можно определить несколько объектов одного типа. В этом случае их имена перечисляются через запятую:

double salary, wage;

int month,

day, year;

unsigned long distance;

Простое определение переменной не задает ее начального значения. Если объект определен как глобальный, спецификация С++ гарантирует, что он будет инициализирован нулевым значением. Если же переменная локальная либо динамически размещаемая (с помощью оператора new), ее начальное значение не определено, то есть она может содержать некоторое случайное значение.
Использование подобных переменных – очень распространенная ошибка, которую к тому же трудно обнаружить. Рекомендуется явно указывать начальное значение объекта, по крайней мере в тех случаях, когда неизвестно, может ли объект инициализировать сам себя. Механизм классов вводит понятие конструктора по умолчанию, который служит для присвоения значений по умолчанию.

int main() {

// неинициализированный локальный объект

int ival;


// объект типа string инициализирован
// конструктором по умолчанию
string project;


//...
}

Начальное значение может быть задано прямо в операторе определения переменной. В С++ допустимы две формы инициализации переменной – явная, с использованием оператора присваивания:

int ival = 1024;

string project = "Fantasia 2000";

и неявная, с заданием начального значения в скобках:

int ival(1024);

string project("Fantasia 2000");

Оба варианта эквивалентны и задают начальные значения для целой переменной ival как 1024 и для строки project как "Fantasia 2000".
Явную инициализацию можно применять и при определении переменных списком:

double salary = 9999.99, wage = salary + 0.01;

int month = 08;

day = 07, year = 1955;

Переменная становится видимой (и допустимой в программе) сразу после ее определения, поэтому мы могли проинициализировать переменную wage суммой только что определенной переменной salary с некоторой константой. Таким образом, определение:

// корректно, но бессмысленно

int bizarre = bizarre;

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

// ival получает значение 0, а dval - 0.0

int ival = int();

double dval = double();

В следующем определении:

// int() применяется к каждому из 10 элементов

vector< int > ivec(10);

к каждому из десяти элементов вектора применяется инициализация с помощью int().
Переменная может быть инициализирована выражением любой сложности, включая вызовы функций. Например:

#include <cmath>

#include <string>


double price = 109.99, discount = 0.16;
double sale_price(price * discount);

 

string pet("wrinkles");

extern int get_value();

int val = get_value();


unsigned abs_val = abs(val);

abs() – стандартная функция, возвращающая абсолютное значение параметра.
get_value()– некоторая пользовательская функция, возвращающая целое значение.

 

 

Пример №1:

Задана статична матриця B(N,N). Впорядкувати її рядки за спаданням сум елементів кожного рядка. Застосувати функцію.Передачу параметрів у функцію виконати за допомогою вказівників.

 

#include <iostream>

using namespace std;

 

void Init(int **mas, int N);

void Sort(int **mas, int N);

 

void main()

{

setlocale(LC_ALL, "RUS");

 

int N = 10;

int **B = new int*[N];

for(int i = 0; i < N; i++)

{

B[i] = new int[N];

}

 

Init(B, N);

cout<<"\n";

Sort(B, N);

 

for(int i = 0; i < N; i++)

{

for(int j = 0; j < N; j++)

{

cout<<B[i][j]<<" ";

}

cout<<"\n";

}

 

for(int i = 0; i < N; i++)

{

delete []B[i];

}

 

delete []B;

}

 

void Init(int **mas, int N)

{

for(int i = 0; i < N; i++)

{

for(int j = 0; j < N; j++)

{

mas[i][j] = rand() % 100;

cout<<mas[i][j]<<" ";

}

cout<<endl;

}

}

 

void Sort(int **mas, int N)

{

int a, b, c, v;

 

for(int i = 0; i < N; i++)

{

a = 0;

b = i;

 

for(int j = 0; j < N; j++)

{

a += mas[i][j];

}

 

for(int j = i; j < N; j++)

{

c = 0;

for(int q = 0; q < N; q++)

{

c += mas[j][q];

}

 

if(a < c)

{

a = c;

b = j;

}

}

 

for(int j = 0; j < N; j++)

{

v = mas[i][j];

mas[i][j] = mas[b][j];

mas[b][j] = v;

}

}

}

 

 

Пример № 2:

<== предыдущая лекция | следующая лекция ==>
Meet George Bronson | 


Не нашли, что искали? Воспользуйтесь поиском:

vikidalka.ru - 2015-2024 год. Все права принадлежат их авторам! Нарушение авторских прав | Нарушение персональных данных