Теперь вам придется много практиковаться, чтобы закрепить знания и до конца разобраться. Решим несколько задач для начала.
1. Задачка элементарная, но требует хорошего понимания что такое указатели. Дан указатель: double**p=0; Выполните следующие задания (решения можно оформлять внутри функции main): * создайте конструкцию, изображенную на рисунке; * выведите число, указанное в квадратике, на экран; * после этого удалите все динамические объекты.
Опять же – ищем самое короткое решение. Автор: Olej
Посмотреть код
Задача 1: Указатели в С++
C++
1
2
3
4
5
6
7
8
9
10
#include <iostream>
usingnamespacestd;
intmain(void){
double**p=0;
*(*(p=newdouble*)=newdouble)=2;
cout<<**p<<endl;
delete*p;
deletep;
}
2. Объявите указатель на массив типа double и предложите пользователю выбрать его размер. Далее напишите четыре функции: первая должна выделить память для массива, вторая – заполнить ячейки данными, третья – показать данные на экран, четвертая – освободить занимаемую память. Программа должна предлагать пользователю продолжать работу (создавать новые динамические массивы ) или выйти из программы.
Остановимся на функции, которая выделяет память под массив, размер которого задает пользователь. Это функция giveMemoryToArr(). Определение находится в строках 34 – 38. Как видно – в результате она возвращает указатель типа double. Смотрите – если бы функция имела тип void, как бы она работала? В нее передался бы указатель и заданный размер. Далее для этого указателя выделяется участок памяти – строка 36. И все – при выходе их функции копия указателя уничтожается и адрес этого участка памяти нигде не сохранен. Поэтому функция должна вернуть адрес (указатель) в результате работы. То есть адрес выделенного участка памяти нам надо будет записать в указатель, который объявлен в main() в строке 13.
Результат:
3. Объявите указатель на массив типа int и выделите память память для 12-ти элементов. Необходимо написать функцию, которая поменяет значения четных и нечетных ячеек массива. Например есть массив из 4-х элементов:
Определение функции, которая меняет данные местами, находится в строках 40 – 52. В ней объявляется временная переменная bufferVar. Она будет выполнять роль буфера для значений, которые необходимо будет записать в другую ячейку. Цикл for будет перебирать все ячейки массива. Если индекс – четное число (если остаток от деления на 2 равен 0), то записываем значение этой ячейки в переменную bufferVar. В саму четную ячейку записывается значение следующей (нечетной): ptrArr[i]=ptrArr[i+1]; И далее уже в нечетную копируем значение из bufferVar: ptrArr[i+1]=bufferVar; Потом цикл и блок if перейдут к проверке следующей ячейки.
Результат работы:
4. Объявить и заполнить двумерный динамический массив случайными числами от 10 до 50. Показать его на экран. Для заполнения и показа на экран написать отдельные функции. (подсказка: функции должны принимать три параметра – указатель на динамический массив, количество строк, количество столбцов). Количество строк и столбцов выбирает пользователь.
Посмотреть код
Задача 4: Указатели в С++, Двумерный динамический массив
Первое на что надо обратить внимание – это объявление динамического двумерного массива, выделение памяти для него и её освобождение. Когда мы рассматривали тему Двумерные массивы в С++ мы затрагивали тот вопрос, что двумерный массив – это массив массивов. Например если объявлен двумерный массив int ArrForChange [3][3], то значит он содержит в себе три массива по три элемента каждый. Объявляется двумерный динамический массив с применением операции ** (двойная звездочка). Это указатель на указатель. Он содержит в себе адрес массива указателей, каждый элемент которого хранит адрес какой-то строки двумерного массива. Визуально это можно показать так:
Сначала надо выделить память под массив, который будет содержать адреса строк двумерного массива:
выделение памяти для двумерного динамического массива
C++
22
int**ArrayForChange=newint*[stringAmount];
Вы видите, что память выделяется не для данных типа int, а именно для указателей на данные типа int.
Далее выделяется память для каждого указателя. В этой памяти уже будут находиться данные типа int:
выделение памяти для двумерного динамического массива
C++
23
24
25
26
for(inti=0;i<stringAmount;i++)
{
ArrayForChange[i]=newint[columnAmount];
}
Освобождая память, занимаемую двумерным массивом, надо быть внимательным. Освободить её надо обратным способом: сначала память в которой содержатся данные:
освобождение памяти двумерного динамического массива
C++
32
33
34
35
for(inti=0;i<stringAmount;i++)
{
delete[]ArrayForChange[i];
}
Потом память массива указателей:
освобождение памяти двумерного динамического массива
C++
36
delete[]ArrayForChange;
Если пропустить первый шаг – произойдет утечка памяти. Так как ячейки занимаемые данными, будут отмечены как зарезервированная память и не смогут использоваться в программе повторно.
Передавая двумерный массив в функцию, нам необходимо передать указатель на указатель.
void show2Arr (int** ArrForChange, int strAmount, int colAmount);
void fill2Array (int** ArrForChange, int strAmount, int colAmount);
Когда функция получает этот указатель на указатель, она далее может с ним работать, как с обычным двумерным массивом. Например используя вложенные циклы, отображать данные на экран, как показано в строках 44 – 52. Или внести данные в ячейки массива – строки 58 – 64.
Результат работы программы:
4.7
41
40 thoughts on “Задачи и решения: Указатели C++”
Не понял решения первого задания Либо я плохо читал и смотрел видос, либо я просто что-то забыл, но как я понял, этот указатель – указатель на указатель, верно? То есть, одной строчкой кода мы создаем два указателя, один из которых указывает на другой указатель, который в свою очередь указывает на 2. Послушать так бред у меня много вопросов, Как указатель указывает просто на двойку? Или там еще и переменная создается? почему сначала, там нужно поставить * а потом нет? *(*(p = new double*) = new double) = 2; И что вообще происходит в этой строке я так и не разобрался Кто в этом разбирается помогите пожалуйста, ничего не понимаю
Указателю p присваивается адрес динамически выделенной памяти в которой хранится указатель на double, далее мы разадресуем p и получаем указатель на тип double и динамически выделяем ему память, разадресацией получаем значение этой ячейки памяти (с double) и присваиваем ему значение 2.Можно записать по другому: p = new double*; *p=new double; **p=2;
Прочитал уроки и посмотрел видео до этого момента, со скрипом пытаюсь понять: по 2 задаче, //double* pArrForFill = 0;// как мы таким образом указатель на массив сделали? типо адресс первой ячейки? Еще, почему так: //double* giveMemoryToArr(double* ptrArr, int sizeOfArr) { ptrArr = new double[sizeOfArr];// а не вот так? //double* giveMemoryToArr(double* ptrArr, int sizeOfArr) { double* ptrArr = new double[sizeOfArr];//
double* pArrForFill = 0 мы создаем указатель но он просто пустой //double* giveMemoryToArr(double* ptrArr, int sizeOfArr) { double* ptrArr = new double[sizeOfArr];// таким образом мы заново создаем указатель а зачем нам это делать когда он у нас уже есть и мы его передаем в функцию?
Задача №3 я вижу решение такое, более простое как мне кажется void fuu(int* pmas) { for (int i = 0; i < 12; i++) { pmas[i] = i + 1; cout << " | " << pmas[i]; } cout << "\n\n============================================\n\n"; for (int ix = 0; ix 0) pmas[ix] = pmas[ix] + 1; else pmas[ix] = pmas[ix] – 1; }
} void main() { setlocale(LC_ALL, “rus”); int* mas = new int[12]; fuu(mas); for (int i = 0; i < 12; i++) { cout << " | " << mas[i]; } }
Не понял решения первого задания
Либо я плохо читал и смотрел видос, либо я просто что-то забыл, но как я понял, этот указатель – указатель на указатель, верно?
То есть, одной строчкой кода мы создаем два указателя, один из которых указывает на другой указатель, который в свою очередь указывает на 2.
Послушать так бред
у меня много вопросов,
Как указатель указывает просто на двойку? Или там еще и переменная создается?
почему сначала, там нужно поставить * а потом нет?
*(*(p = new double*) = new double) = 2;
И что вообще происходит в этой строке я так и не разобрался
Кто в этом разбирается помогите пожалуйста, ничего не понимаю
Указателю p присваивается адрес динамически выделенной памяти в которой хранится указатель на double, далее мы разадресуем p и получаем указатель на тип double и динамически выделяем ему память, разадресацией получаем значение этой ячейки памяти (с double) и присваиваем ему значение 2.Можно записать по другому:
p = new double*;
*p=new double;
**p=2;
Спасибо, впринципе я примерно так и думал, только у меня в голове это казалось намного сложнее
По 4 заданию можете подсказать из-за чего возникает эта ошибка
“вызвал срабатывание точки останова”
не каждый раз .
Прочитал уроки и посмотрел видео до этого момента, со скрипом пытаюсь понять:
по 2 задаче, //double* pArrForFill = 0;// как мы таким образом указатель на массив сделали? типо адресс первой ячейки?
Еще, почему так:
//double* giveMemoryToArr(double* ptrArr, int sizeOfArr)
{
ptrArr = new double[sizeOfArr];//
а не вот так?
//double* giveMemoryToArr(double* ptrArr, int sizeOfArr)
{
double* ptrArr = new double[sizeOfArr];//
double* pArrForFill = 0
мы создаем указатель но он просто пустой
//double* giveMemoryToArr(double* ptrArr, int sizeOfArr)
{
double* ptrArr = new double[sizeOfArr];//
таким образом мы заново создаем указатель а зачем нам это делать когда он у нас уже есть и мы его передаем в функцию?
3 задача:
#include
using namespace std;
void fillArr(int* parr);
int main()
{
setlocale(LC_ALL, “rus”);
int arr[12]{};
cout << "Массив до функции:\n";
cout << "___________________________\n";
for (int i = 0; i < 12; i++)
{
arr[i] = i + 1;
cout << arr[i] <<"|";
}
fillArr(arr);
cout << "\n___________________________\n";
cout << "\nМассив после функции: \n";
cout << "___________________________\n";
for (int i = 0; i < 12; i++)
{
cout << arr[i] << "|";
}
cout << "\n___________________________\n";
return 0;
}
void fillArr(int* parr)
{
for (int i = 1; i < 12; i += 2)
{
int j = parr[i – 1];
parr[i – 1] = parr[i];
parr[i] = j;
}
}
Задача № 3
#include
using namespace std;
void FillArray(int* arr, int size)
{
for (int i = 0; i < size; i++)
{
arr[i] = rand() % 100;
}
}
void OutputArray(int* arr, int size)
{
for (int i = 0; i < size; i++)
{
cout << i+1 << ": " << arr[i] << "\t";
}
cout << endl;
}
int main()
{
int size = 12;
int* arr = new int[size];
FillArray(arr, size);
OutputArray(arr, size);
for (int i = 0; i < size; i++)
{
if ((i+1) % 2 == 0)
{
arr[i] = arr[i] + arr[i – 1];
arr[i – 1] = arr[i] – arr[i – 1];
arr[i] = arr [i] – arr[i – 1];
}
}
OutputArray(arr, size);
return 0;
}
Задача №3
я вижу решение такое, более простое как мне кажется
void fuu(int* pmas)
{
for (int i = 0; i < 12; i++)
{
pmas[i] = i + 1;
cout << " | " << pmas[i];
}
cout << "\n\n============================================\n\n";
for (int ix = 0; ix 0)
pmas[ix] = pmas[ix] + 1;
else
pmas[ix] = pmas[ix] – 1;
}
}
void main()
{
setlocale(LC_ALL, “rus”);
int* mas = new int[12];
fuu(mas);
for (int i = 0; i < 12; i++)
{
cout << " | " << mas[i];
}
}
А не проще ли сделать решение 3 задачи так?:
//librayes
#include
//std
using namespace std;
void swapOddAndShow(int* &p, int size) {
for (int i = 0; i < size; i++) {
if (p[i] % 2 == 0) {
p[i – 1] = p[i];
p[i] = p[i – 1] – 1;
}
}
for (int i = 0; i < size; i++) { //after
cout << p[i] << endl;
}
}
int main()
{
const int size = 12;
int* pArr = new int[size];
for (int i = 0; i < size; i++) { //before
pArr[i] = i + 1;
cout << pArr[i] << endl;
}
cout << "=======================" << endl;
swapOddAndShow(pArr, size);
delete[] pArr;
}
Вообще-то у меня опыта немного, поэтому я могу ошибаться.
Можете написать программу с++ “Частотный словарь слов “