Главная страница

Программирование C++. Пензенский государственный университет введение в программирование на языке с лабораторный практикум пенза 2010 г 2


Скачать 1.47 Mb.
НазваниеПензенский государственный университет введение в программирование на языке с лабораторный практикум пенза 2010 г 2
Дата06.10.2022
Размер1.47 Mb.
Формат файлаpdf
Имя файлаПрограммирование C++.pdf
ТипПрактикум
#718990
страница5 из 10
1   2   3   4   5   6   7   8   9   10
using
std::cout;
using
std::endl;
int
main()
{
int
i =10, j =20;
int
& rfc = i; cout<
int
* ptr = &i; cout<<*ptr<
//10
ptr = &j; cout<<*ptr<
//20, изменилось значение указателя
cout<< i <
//10, значение i не изменилось
rfc = j; cout<
//20, изменилось значение данных
cout<< i <
//20, значение i изменилось, так как rfc по-прежнему ссылается на i;
system(
"pause"
);
return
0;
} Указатели и массивы Имя массива – это указатель- константана начало массива. Таким образом доступ к элементу массива можно записать через смещение от начала массива. Например для массива
b
, операция разыменования
*(b+3)
– это тоже, что и операция индексирования
b[3] взгляните еще раз например первой программы во введении. Для элемента двумерного массива
data[row][col]
операция индексирования переводится компилятором в операцию разыменования указателей
*( *(data+row)+col). Описание
int (*data1)[20] определяет указатель нам асс ив из целых значений. Описание
int *data1[20] определяет массив из указателей на целые значения. Начальный адрес массива определяется компилятором в момент описания массива, и такой адрес немо же т быть переопределен. Это делает невозможным копирование массивов с помощью простого оператора присваивания (как в языке
Pascal
).
Наример:
const
int
ArraySize=5;
int
a[ArraySize] = {12, 3, 42, 5, 34};
int
b[ArraySize];
b=a;
// ОШИБКА Попытка изменить константный указатель
b,
// сообщение компилятора C++ Microsoft Visual Studio:
//
«error C2106: '=' : left operand must be l-value»,
// те. b должно быть изменяемой величиной
Динамическое размещение массива Указатели используются для размещения массива в динамическойобласти оперативной памяти – куче. Для выделения памяти применяется оператор –
new
тип[размер массива , для освобождения

delete
[]. Например
int
* ptrArray1 =
new
int
[5];
//
ptrArray1
– начальный адрес массива из 5 элементов
. . .
//
использование массива
ptrArray1
delete
[] ptrArray1; освобождение памяти с начальным адресом
ptrArray1

37 Пример Указатели и массивы

using
std::cout;
using
std::endl;
int
main()
{
int
Array[5] = {10, 20, 30, 40, 50}; статический массив – память резервируется при компиляции
int
* ptrArray1 =
new
int
[5];
// динамические массивы – память резервируется
int
* ptrArray2 =
new
int
[5];
// в куче при выполнении программы Размер массива. В случае динамического массива получаем размер указателя
cout<<
"SizeofArray "
<<
sizeof
(Array) <
cout<<
"SizeofPtrArray "
<<
sizeof
(ptrArray1)<
for
(
int
i=0; i<5; ++i){ копируем значения изв используя для доступа к значениям
cout<<*(ptrArray1+i)<
// массивов разыменование указателя
}
for
(
int
i=0; i<5; i++) { копируем значения изв используя для доступа к значениям
cout<
// массивов имя массива и номер элемента
}
delete
[] ptrArray1; освобождаем память,
delete
[] ptrArray2; выделенную для ptrArray1 и ptrArray2
system(
"pause"
);
return
0;
} Пример Указатели и массивы символов
using
std::cout;
using
std::endl;
int
main()
{
char
string1[10], *string2 =
"Hello"
,
string3[10], *string4 =
"GoodBye"
,
*tmp; копирование string2 в string1, используя обозначение массива
for
(
int
i=0; (string1[i]= string2[i]) !=
'\0'
; ++i) ;
cout<<
"string1:"
<
tmp=string3; используем tmp, т.к. нельзя string3++
for
( ; (*tmp = *string4) !=
'\0'
; tmp++, string4++) ;
cout<<
"string3:"
<
system(
"pause"
);
return
0;
}

38 Пример Указатели и массивы символов

#include

#include

using
std::endl;
using
std::cout;
int
main()
{
// использование функции strtok для определения слов в предложении
// разделитель слов - пробел
char
str[] = Это предложение из 5 слов
char
*tkPtr; указатель на слово
tkPtr = strtok(str,
" "
);
while
(tkPtr != NULL) {
cout<
tkPtr=strtok(NULL,
" "
);
}
system(
"pause"
);
return
0; Указатели и ссылки как параметры Передача параметров по адресу Указатели и ссылки используются для передачи параметров по адресу. Схема обмена информацией вызывающей программы и функции с использованием передачи параметра по адресу приведена на рисунке 3.1. В этом случае формальный параметр обрабатывается в функции как переменная, адрес которой есть адрес соответствующего фактического параметра. Рисунок 3.1 – Передача параметра по адресу В операторе вызова фактическим параметром может быть только переменная. Любое изменение формального параметра есть изменение соответствующего ему фактического параметра. После завершения работы функции f значение равно, так как в функции выполнен оператора Пример 3_5_1. Перестановка значений
Вариант 1
#include

using
std::cout;
using
std::endl;
void
swap_values(
int
* a,
int
* b)
// формальный параметр - указатель
int
temp=*a;
// требуется разыменование указателей
*b=temp;
}
int
main()
{
int
x=10, y=20;
swap_values(&x, &y);
// требуется операция
&
, так как
// параметры передаются по адресу
cout<
" "
<
// результат 20 10
system(
"pause"
);
return
0;
} Вариант 2
#include

using
std::cout;
using
std::endl;
void
swap_values(
int
& a,
int
& b)
// формальный параметр - ссылка
int
temp=a;
// НЕ требуется разыменование указателей
b=temp;
}
int
main()
{
int
x=10, y=20;
swap_values(x, y);
// НЕ требуется операция
&
cout<
" "
<
// результат 20 10
system(
"pause"
);
return
0;
} Передача массивов в качестве параметров Во многих случаях передавать значения в функции выгоднее по адресу, а не по значению. Особенно эффективна передача по адресу, если передаваемые данные имеют большой размер, например массивы данных. Однако, при этом досаточно частот ре буе т с яз а щит и т ь передаваемые данные от изменения. Для этого в прототипе функции используется не константный указатель на константные данные Пример 3_6_1. Передача массива в качестве параметра
using
std::endl;
using
std::cout;
int
summa(
const
int
* x,
const
int
n);
// массив всегда передается по адресу необходимо передать и размер массива main()
{
const
int
ArraySize=5;
// размер массива
int
a[ArraySize] = {1, 3, 4, 5, 2};
// инициализация массива
for
(
int
i=0; i
// вывод значений элементов
cout<
// массива
cout << Сумма элементов массива "
<
system(
"pause"
);
return
0;
}
int
summa(
const
int
* x,
const
int
n)
// можно итак сумма значений элементов массива
for
(
int
i=0; i
// цикл вычисления суммы
total+=x[i];
return
total;
} Структуры Структура – это тип данных, состоящий из фиксированного числа компонентов разного типа. Компоненты записи называют полями, и соответственно имена компонентов являются именами полей. Основной операцией над структурами является выбор компонентов. Эта операция подобна выбору элементов из массива, нос одним существенным отличием индекс здесь всегда является именем компонента и никогда не может быть вычисляемым значением. Синтаксически операция выбора компонента структуры представляет собой имя структуры, за которым следует имя компонента. Пример Тип Комплексное число
#include

using
std::endl;
using
std::cout;
struct
Complex{
//
struct
– структура,
Complex
– имя структуры r, поле
r
– действительная часть
i; поле
i
– мнимая часть
};
int
main()
{
Complex c2, *pc, c1={1,2}; инициализация с c1.r=1, c1.i=2
// операция выбора поля структуры
c2.r = c1.r;
// имя_структуры . имя_поля
c2.i = c1.i;
// например, c2.i : c2 – имя структуры, i – имя поля
cout<<
"r="
<
" i="
<
pc =
new
Complex;
// определение указателя на структуру
pc->r = -10;
// операция выбора поля структуры

41
pc->i = 5;
// имя_структуры -> имя_поля
cout<<
"r="
<
r<<

" i="
<
i<
delete
pc;
system(
"pause"
);
return
0;
} Как видите, выбор полей структуры с помощью операции
.
или операции
->
зависит от переменной типа
struct
и не имеет отношения к полям самой структуры. Раз уж мы заговорили об этом, правильные названия этих операторов (
. и
->
) – селекторы полей структуры. Как сказано водной умной книге по С (автор Дж.
Элджер), если вы назовете их точкой или стрелкой на семинаре с коктейлями, наступит гробовая тишина, все повернутся и презрительно посмотрят на вас, а в дальнем углу кто-нибудь выронит свой бокал. Заметим также, что синтаксис описания структуры позволяет объявить переменные сразу в самом описании. Для рассмотренного примера переменные с, си указатель
pc
можно объявить такс, с Примеры программ

3.8.1 Стек как одномерный статический массив Стек

– структура для хранения данных с дисциплиной обслуживания последним пришел, первым ушел (Last In First Out). Стек широко используется как на аппаратном, таки на программном уровне копьютера.
О снов н ы е функции работы со стеком следующие
push
– помещает значение в стек
pop
– извлекает значение и удаляет его из стека
full
– возвращает значение истина, если стек заполнен
empty
– возвращает значение истина, если стек пуст. Реализуем стек как структуру (
struct
), которая для хранения данных использует символьный (в данном примере) массив длиной
max_len рисунок 3.2). Рисунок 3.2 – Стек

42 Пример Стек символов Файл Stack_1.h определение стека и его операций _STACK1_H предотвращение многократного

#define
_STACK1_H включения заголовочного файла
//Данные
const
int
Max_len = 100;
enum
{EMPTY = -1, FULL = Max_len -1};
struct
ch_stack {
char
s[Max_len]; массив символов top; значение номера верхушки стека Операции со стеком
void
reset(ch_stack* stk) { очистка стека = EMPTY;
}
void
push(ch_stack* stk,
char
c) {
stk->s[++stk->top] = c; приоритет stk->top, ++, [ ], =
}
char
pop(ch_stack* stk) {
return
(stk->s[stk->top--]); приоритет stk->top, [ ], stk->top --
}
bool
empty(
const
ch_stack* stk) {
return
(stk->top == EMPTY);
}
bool
full(
const
ch_stack* stk) {
return
(stk->top == FULL);
}
#endif
_STACK1_H Файл Stack_1.cpp
// использование стека включение описания стека
#include

using
std::endl;
using
std::cout;
int
main()
{
ch_stack st;
// st - стек
char
str[]=
"12345"
;
// str - строка, символы которой помещаются в стек
int
i=0;
cout<
// вывод str
reset(&st);
// очистка стека
while
(str[i] && !full(&st))
// пока символ не '\0' истек не заполнен
push(&st, str[i++]);
// поместить символ в стек
while
(!empty(&st))
// пока стек не пуст
cout<
// выбрать символ из стека и вывести на экран
cout<
system(
"pause"
);
return
0;
} Результат работы

43 3.8.2 Динамический двумерный массив В основе реализации динамического двумерного массива лежит следующая структура данных (рисунок 3.3) Рисунок 3.3 – Динамический двумерный массив Указатель
base содержит начальный адрес массива указателей, каждый элемент которого является начальным адресом массива данных. При этом указатель
base
является указателем на указатель на тип данных.
N
– число строк в двумерном массиве.
M
– число столбцов в двумерном массиве. Пример Двумерный динамический массив

Файл определение динамического массива и его операций Н предотвращение многократного
#define
Н включения заголовочного файла
#include

using
std::endl;
using
std::cout;
using
std::cin; Данные
struct
array2d {
int
** base; базовый адрес массива – двойной указатель
int
N, M; количество строки столбцов
}; Операции с массивом создание массива размерность
r

c
void
allocate(
const
int
r,
const
int
c, array2d& x){
x.base =
new
int
*[r]; выделить память для массива указателей на int
for
(
int
i=0; i
x.base[i]=
new
int
[c]; выделить память для массива целых чисел
x.N = r; x.M = c;
} удаление массива
void
deallocate(array2d& x){
for
(
int
i=0; i
delete
[] x.base[i];
delete
[] x.base; x.base=0;
x.N = 0; x.M = 0;
}

44 вывод значений элементов массива по строкам

void
print(
const
array2d& x){
for
(
int
i=0; i
for
(
int
j=0; j
cout<<
" "
<
cout<
}
} ввод значений элементов массива по строкам
void
input(
const
array2d& x){
for
(
int
i=0; i
for
(
int
j=0; j
cin>>x.base[i][j];
cout<
} поиск максимального значения массива
int
find_max(
const
array2d& x){
int
i, j, max=x.base[0][0];
1   2   3   4   5   6   7   8   9   10


написать администратору сайта