Теперь вам придется много практиковаться, чтобы закрепить знания и до конца разобраться. Решим несколько задач для начала.
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: Указатели в С++, Двумерный динамический массив
Первое на что надо обратить внимание – это объявление динамического двумерного массива, виділення пам'яті для нього і її звільнення. Коли ми розглядали тему Двумерные массивы в С мы затрагивали тот вопрос, что двумерный массив – це масив масивів. Например если объявлен двумерный массив ІНТ 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;
Если пропустить первый шаг – произойдет утечка памяти. Так как ячейки занимаемые данными, будут отмечены как зарезервированная память и не смогут использоваться в программе повторно.
Передавая двумерный массив в функцию, нам необходимо передать указатель на указатель.
Когда функция получает этот указатель на указатель, она далее может с ним работать, как с обычным двумерным массивом. Например используя вложенные циклы, отображать данные на экран, как показано в строках 44 – 52. Або внести дані в осередку масиву– строки 58 – 64.
Результат работы программы:
4.7
41
40 думки про "Задачі та рішення: Указатели C ”
В цілому придатно. Чи не вчитувався, подивився по діагоналі. картинки красиві.
Функції типу giveMemoryToArr я б не писав (хоча, на смак і колір…). Якщо вже їх залишати, то ІМХО подвійний * FreeMemory(double* ptrArr) повинна повертати void. Навіщо вона повертає у вас завжди нуль?
Приклад б який-небудь ще (більш об'ємний)… Шашки (людина проти людини) чи що…
Адміну величезне спасибі, за то, що дає не тільки завдання, а й рішення з докладними коментарями до коду. Я читала уроки по C ++ на декількох сайтах. На вашому – мені подобається найбільше. Зручне зміст головної сторінки, завдання з рішеннями на окремій сторінці. При чому завдання згруповані за темами, а не всі скопом і упереміш. Не зупиняйтесь! Пишіть ще! :)
Так-то напевно можна задачу 3 і без буферів вирішити: недійсний mixmass(ІНТ С.З., int *arr) { for (int i = 1; i < С.З.; i ) { if (arr[i] % 2 == 0) arr[i] = Я-1; } } ————————————————————– for (int i = 0; i < С.З.; i ) { маса [i] = + 1; std::cout << маса [i] << std::кінці; };
У першій задачі купа незрозумілих конструкцій, в попередніх уроках не було пояснено, по них, так навіщо ж вирішувати задачу способом, який не зрозумілий учням?
У 1-й задачі взагалі немає ніяких “конструкцій” – потрібно тільки добре розуміти те, що: a). покажчик містить адрес того, на що він вказує, б). а операція разіменованія покажчика (префиксная операція *) означає: “взяти значение того, на що вказує покажчик”.
Це я знаю, це було в уроке.Но 4 строку, де в дужках стоїть void, взагалі не можу зрозуміти, в уроках ніколи в дужках нічого не було; Строка 6, де взагалі нічого не зрозуміло, таких конструкцій в уроках не було. Завдання повинні бути такими, що прочитавши всі попередні статті їх можна було легко зрозуміти. Але перше завдання зовсім не така.
3 задача
#include using namespace std;
int main() { setlocale(LC_ALL, “rus”); system(“колір E0”);
INT * масив = новий INT[12]; for (int i = 0; i < 12; i ) { array[i] = i + 1; cout << array[i] << " "; }
cout << endl;
INT B = 0; int j = 1; ІНТ зберегти = 0; for (int i = 0; i < 6; i ) { зберегти = масив[b]; array[b] = масив[j]; array[j] = зберегти;
B = B + 2; J = J + 2; }
for (int i = 0; i < 12; i ) { cout << array[i] << " "; }
хлопці, если не сложно допоможіть з задачкою: Дано матриці А і В розміру k × m і m × l відповідно. Знайти твір АВ. Перемноження матриць реалізувати у вигляді функції.
Сама завдання множення матриць – “якщо не важко” (і навіть елементарно – 2 вкладених циклу). Але: 1. Є різні варіанти представлення 2-мірних матриць (як 2-х мірних масивів, як масивів покажчиків, як STL контейнерів – вектор векторів і т.д. … до 10 різних способів або більше). Залежно від обраного способу обчислення будуть записуватися зовсім по-різному. 2. Набагато більше за обсягом, ніж саме множення, займе у вас а). введення вихідних матриць + б). висновок результату + в). тестова задача main() яка буде наочно демонструвати процес і результат.
Так що завдання дуже проста, але писати все для неї обрамлення – зовсім не просто, там механічної роботи багато.
народ, а якщо я хочу написати функція виділення пам'яті під двомірний масив, як це виглядає.
INT * givemmry (INT ** бовдура, INT size1, внутр size2) { **бовдура = новий INT * [size1]; for (int i = 0; i < size1; i ) { бовдур[i] = new int[size2]; } повернутися ** бовдура; }
int** givemmry( int size1, int size2 ) { int **boob = new int* [ size1 ]; for( int i = 0; i < size1; i++ ) boob[ i ] = new int[ size2 ]; return boob; }
або простіше: int** givemmry( int size1, int size2 ) { return (int**)new int* [ size1 * size2 ]; }
В цілому придатно. Чи не вчитувався, подивився по діагоналі. картинки красиві.
Функції типу giveMemoryToArr я б не писав (хоча, на смак і колір…).
Якщо вже їх залишати, то ІМХО подвійний * FreeMemory(double* ptrArr) повинна повертати void. Навіщо вона повертає у вас завжди нуль?
Приклад б який-небудь ще (більш об'ємний)… Шашки (людина проти людини) чи що…
В цілому, молодець. Пиши ще :)
Адміну величезне спасибі, за то, що дає не тільки завдання, а й рішення з докладними коментарями до коду. Я читала уроки по C ++ на декількох сайтах. На вашому – мені подобається найбільше. Зручне зміст головної сторінки, завдання з рішеннями на окремій сторінці. При чому завдання згруповані за темами, а не всі скопом і упереміш.
Не зупиняйтесь! Пишіть ще! :)
Так-то напевно можна задачу 3 і без буферів вирішити:
недійсний mixmass(ІНТ С.З., int *arr)
{
for (int i = 1; i < С.З.; i )
{
if (arr[i] % 2 == 0)
arr[i] = Я-1;
}
}
————————————————————–
for (int i = 0; i < С.З.; i )
{
маса [i] = + 1;
std::cout << маса [i] << std::кінці;
};
mixmass(С.З., маса);
Але у мене не доходить..
У першій задачі купа незрозумілих конструкцій, в попередніх уроках не було пояснено, по них, так навіщо ж вирішувати задачу способом, який не зрозумілий учням?
У 1-й задачі взагалі немає ніяких “конструкцій” – потрібно тільки добре розуміти те, що:
a). покажчик містить адрес того, на що він вказує,
б). а операція разіменованія покажчика (префиксная операція *) означає: “взяти значение того, на що вказує покажчик”.
Це я знаю, це було в уроке.Но 4 строку, де в дужках стоїть void, взагалі не можу зрозуміти, в уроках ніколи в дужках нічого не було;
Строка 6, де взагалі нічого не зрозуміло, таких конструкцій в уроках не було. Завдання повинні бути такими, що прочитавши всі попередні статті їх можна було легко зрозуміти. Але перше завдання зовсім не така.
3 задача
#include
using namespace std;
int main()
{
setlocale(LC_ALL, “rus”);
system(“колір E0”);
INT * масив = новий INT[12];
for (int i = 0; i < 12; i )
{
array[i] = i + 1;
cout << array[i] << " ";
}
cout << endl;
INT B = 0;
int j = 1;
ІНТ зберегти = 0;
for (int i = 0; i < 6; i )
{
зберегти = масив[b];
array[b] = масив[j];
array[j] = зберегти;
B = B + 2;
J = J + 2;
}
for (int i = 0; i < 12; i )
{
cout << array[i] << " ";
}
хлопці, если не сложно допоможіть з задачкою: Дано матриці А і В розміру k × m і m × l відповідно. Знайти твір АВ. Перемноження матриць реалізувати у вигляді функції.
Сама завдання множення матриць – “якщо не важко” (і навіть елементарно – 2 вкладених циклу).
Але:
1. Є різні варіанти представлення 2-мірних матриць (як 2-х мірних масивів, як масивів покажчиків, як STL контейнерів – вектор векторів і т.д. … до 10 різних способів або більше). Залежно від обраного способу обчислення будуть записуватися зовсім по-різному.
2. Набагато більше за обсягом, ніж саме множення, займе у вас а). введення вихідних матриць + б). висновок результату + в). тестова задача main() яка буде наочно демонструвати процес і результат.
Так що завдання дуже проста, але писати все для неї обрамлення – зовсім не просто, там механічної роботи багато.
народ, а якщо я хочу написати функція виділення пам'яті під двомірний масив, як це виглядає.
INT * givemmry (INT ** бовдура, INT size1, внутр size2)
{
**бовдура = новий INT * [size1];
for (int i = 0; i < size1; i )
{
бовдур[i] = new int[size2];
}
повернутися ** бовдура;
}
так він видає помилку
int** givemmry( int size1, int size2 ) {
int **boob = new int* [ size1 ];
for( int i = 0; i < size1; i++ )
boob[ i ] = new int[ size2 ];
return boob;
}
або простіше:
int** givemmry( int size1, int size2 ) {
return (int**)new int* [ size1 * size2 ];
}
У 2-му рішенні копіюванням вкралася помилка, должо бути, естественно:
int** givemmry( int size1, int size2 ) {
return (int**)new int [ size1 * size2 ];
}
Спасибо! як я зрозумів, не обов'язково вказувати тип і індекс масиву (бовдур) аргументи функцій, ми просто повертаємо значення?
Тут параметр виявляється просто зайвий – ви його значення все-одно затрёте після new, а тип його (і елементів масиву) змінити все-одно не можете.