1

Тема: Звільннея памяті для вказівника типу *char

Задача: Створити рядок у динамічній пам’яті. Замінити у рядку всі великі букви на малі і навпаки.
При обробці рядка використати вказівник.

Реалізувала так:

Прихований текст
#include <iostream>
#include <cstring>

using namespace std;

int main()
{
    const int STRING_LENGTH = 100;
    char *text = new char[STRING_LENGTH];
    cout << "Enter the string: \n";
    cin.getline(text, STRING_LENGTH);
    system("cls");
    cout << "Your text: " << text << "\n";
    cin.ignore(STRING_LENGTH, '\n');
    char *p = text;
    while (p < text + STRING_LENGTH && *p != '\0')
    {
        if (isupper(*p))
            *p = tolower(*p);
        else 
            *p = toupper(*p);
        p++;
    }
    
    cout << "\nYour changed text: " << text << "\n";
    delete[]text;
 
    return 0;
}

Запитання: чи потрібно при виділенні динамічної пам'яті для рядків і видаляти. Теоретично - так, але як це робиться на практиці - нам про це нічого не сказали. І в прикладах, які показував викладач, видалення пам'яті не відбувається. То як правильно?

2

Re: Звільннея памяті для вказівника типу *char

На кожен new має бути свій delete. Обов'язково. Конкретно в цій ситуації можна було б і не видаляти, оскільки одразу іде вихід, але ви не можете знати, як ваш код використають в майбутньому - може, перейменують функцію з main на laba_3 і використовуватимуть повторно.
І якщо вже мова йде за конкретно тут, то можна було б і без new обійтися. Або ж std::string-ом.

Подякували: pika19891

3

Re: Звільннея памяті для вказівника типу *char

Користуючись нагодою хочу запитати cin.ignore() відноситься до бібліотеки cstring?

4 Востаннє редагувалося koala (14.10.2015 20:58:15)

Re: Звільннея памяті для вказівника типу *char

shonrens написав:

Користуючись нагодою хочу запитати cin.ignore() відноситься до бібліотеки cstring?

std::cin::ignore відноситься, очевидно, до std::cin. std::istream cin описаний в iostream.

Подякували: shonrens1

5

Re: Звільннея памяті для вказівника типу *char

Принагідно хочу зауважити, що замість new можна використовувати розумні вказівники.

// Створити unique_ptr на масив з STRING_LENGTH символів.
std::unique_ptr<char[]> text = std::make_unique<char[]>(STRING_LENGTH);

Коли завершиться область видимості для змінної text десруктор unique_ptr автоматично звільнить пам'ять. Так ви уникнете витоку пам"яті у випадку виняткової ситуації. Звісно, як вказав koala

koala написав:

На кожен new має бути свій delete. Обов'язково. Конкретно в цій ситуації можна було б і не видаляти, оскільки одразу іде вихід, але ви не можете знати, як ваш код використають в майбутньому - може, перейменують функцію з main на laba_3 і використовуватимуть повторно.

Такий підхід, звільнення пам'яті і не тільки у дестркуторі, називається RAII.

6

Re: Звільннея памяті для вказівника типу *char

koala написав:

Конкретно в цій ситуації можна було б і не видаляти, оскільки одразу іде вихід, але ви не можете знати, як ваш код використають в майбутньому - може, перейменують функцію з main на laba_3 і використовуватимуть повторно.

Мається на увазі саме вихід з програми, а не з функції.

Yola написав:

Такий підхід, звільнення пам'яті і не тільки у дестркуторі, називається RAII.

RAII тут і не пахне.

7

Re: Звільннея памяті для вказівника типу *char

Arete написав:
Yola написав:

Такий підхід, звільнення пам'яті і не тільки у дестркуторі, називається RAII.

RAII тут і не пахне.

Будь ласка, аргументуйте.

8 Востаннє редагувалося koala (16.10.2015 10:53:16)

Re: Звільннея памяті для вказівника типу *char

RAII - це прив'язка ресурсу до об'єкту: створюємо об'єкт - отримуємо ресурс, знищуємо об'єкт - звільняємо ресурс. Не має бути об'єктів без ресурсів і ресурсів без об'єктів. Єдині RAII-об'єкти тут - це cin і cout.

Подякували: Arete1

9

Re: Звільннея памяті для вказівника типу *char

Також прив'язка ресурсу до об'єкту дозволяє коректно звільняти ресурс у випадку кидання Exception-а. Бо коли в функції кидається Exception, то функція, перед тим як кинути його вище, викликає деструктори всіх об’єктів, створених локально.
В даному прикладі якщо Exception виникне між

char *text = new char[STRING_LENGTH];

та

delete[]text;

ресурс не звільниться.

10

Re: Звільннея памяті для вказівника типу *char

У мене запитання конкретно до користувача Arete, який на мою адресу сказав "RAII тут і не пахне", - про що саме я сказав, що там є РАІІ, а його там немає. Звісно, якщо "не пахне" означає "немає". Дякую.

11

Re: Звільннея памяті для вказівника типу *char

Я вже пояснив.

12

Re: Звільннея памяті для вказівника типу *char

koala написав:

Я вже пояснив.

Прочитайте уважно моє запитання. Там все дуже просто.

Про що саме я сказав, що там є РАІІ, а його там немає.

13

Re: Звільннея памяті для вказівника типу *char

Ви написали, що

Yola написав:

Такий підхід, звільнення пам'яті і не тільки у дестркуторі, називається RAII.

Я ж казав про те, що виділене за допомогою new має знищуватися delete. Це не RAII - RAII це прив'язка ресурсів до об'єктів, причому не тільки ресурсів пам'яті. А RAII стосується виключно конструктора і деструктора. Тут RAII і не пахне - ані в коді, ані в моєму коментарі.

14

Re: Звільннея памяті для вказівника типу *char

koala написав:

Ви написали, що

Yola написав:

Такий підхід, звільнення пам'яті і не тільки у дестркуторі, називається RAII.

Це було про unique_ptr, він вивілюнює пам'ять у деструкторі.

koala написав:

Тут RAII і не пахне - ані в коді, ані в моєму коментарі.

Ну, так. Я цього ніде не заперечував. Фрагмент вашого коментаря я навів для того, щоб ще раз наголосити, що це має значення лише якщо це функція десь у глибині програми, а не кінець програми.

Наступні мої повідомлення, досить прискіпливі, викликані оцим

RAII тут і не пахне

Вважаю це нечемною відмашкою. Тому і зажадав пояснень.

15

Re: Звільннея памяті для вказівника типу *char

en.wikipedia.org написав:

Володіння динамічно розташованими об'єктами (пам'ять виділена за допомогою new у C++) також можна контролювати через RAII, так що об'єкт вивільняється коли RAII (стековий) об'єкт знищується. Для цього у C++11 визначені розумні вказівники std::unique_ptr для одиноприналежних об'єктів і std::shared_ptr для об'єктів з розділеним володінням.

16

Re: Звільннея памяті для вказівника типу *char

Ок, непорозумілися.

17

Re: Звільннея памяті для вказівника типу *char

Yola

Вважаю це нечемною відмашкою. Тому і зажадав пояснень.

Прошу вибачення за різкість, нікого не хотів образити, тільки хотів спонукати розібратися в цьому питанні :)

18 Востаннє редагувалося shonrens (22.10.2015 22:11:53)

Re: Звільннея памяті для вказівника типу *char

Можливо хтось дасть відповідь на запитання, хочу створити динамічний масив і відразу заповнити його алфавітом як це можна реалізувати?
простий виходить
char message[] ="A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q R r S s T t U u V v W w X x Y y Z z";
а от як динамічний зробити не розумію і потрібно через char .

19

Re: Звільннея памяті для вказівника типу *char

strcpy і п. 3.6 Правил форуму допоможуть вам.

Подякували: shonrens1

20

Re: Звільннея памяті для вказівника типу *char

shonrens написав:

Можливо хтось дасть відповідь на запитання, хочу створити динамічний масив і відразу заповнити його алфавітом як це можна реалізувати?
простий виходить
char message[] ="A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q R r S s T t U u V v W w X x Y y Z z";
а от як динамічний зробити не розумію і потрібно через char .

Після того, як виділили блок пам'яті потрібного розміру, можна заповнити його алфавітом програмно. Символи (char) в Сі можна обробляти як цілі числа: додавати, віднімати, порівнювати і т.п. Далі, якщо подивитись таблицю кодів ASCII, можна побачити, що коди латинських літер у ній ідуть в алфавітному порядку: від a до z й від A до Z. Тобто, треба написати цикл, який генеруватиме коди символів у цьому діапазоні й записуватиме їх у потрібне місце динамічно створеного символьного масиву.