С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.77/13: Рейтинг темы: голосов - 13, средняя оценка - 4.77
Модератор
Эксперт CЭксперт С++
 Аватар для sourcerer
5288 / 2376 / 342
Регистрация: 20.02.2013
Сообщений: 5,773
Записей в блоге: 20

Стивен Прата (гл. 8, упр. 4) - структура с методами и использование new

28.02.2015, 17:03. Показов 2555. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Вопрос. Имеется упражнение. Собственно, вот оно:

Ниже представлена общая структура программы:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <cstring>   // для strlen(), strcpy()
 
struct stringy
{
    char * str;     // указывает на строку
    int ct;         // длина строки (не считая символа '\0')
};
 
// Здесь размещаются прототипы функций set() и show()
 
int main()
{
    stringy beany;
    char testing[] = "Reality is not what it used to be.";
    set(beany, testing);    // Первым аргументом является ссылка.
    // Выделяет пространство для хранения копии testing,
    // использует элемент типа str структуры beany как указатель
    // на новый блок, копирует testing в новый блок и
    // создает элемент ct структуры beany
 
    show(beany);        // выводит строковый член структуры один раз
    show(beany, 2);     // выводит строковый член структуры два раза
    testing[0] = 'D';
    testing[1] = 'u';
    show(testing);      // выводит сроку testing один раз
    show(testing, 3);   // выводит строку testing три раза
    show("Done");
    
    return 0;
}
Завершите программу, создав соответствующие функции и прототипы. Обратите
внимание, что в программе должны быть две функции show(), и каждая из
них использует аргументы по умолчанию. Где необходимо, используйте const.
Функция set() должна использовать операцию new для выделения
достаточного пространства памяти под хранение заданной строки. Используемые здесь
методы аналогичны методам, применяемым при проектировании и реализации
классов. (В зависимости от используемого компилятора, может понадобиться
изменить имена заголовочных файлов и удалить директиву using.)
Начал делать. То есть, сделал:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
#include <cstring>  // для strlen(), strcpy()
 
struct stringy
{
    char * str;     // указывает на строку
    int ct;         // длина строки (не считая символа '\0')
};
 
void show(const char * str, int times = 1);
void show(const stringy & some, int times = 1);
void set(stringy & some, const char * cstr);
 
int main()
{
    stringy beany;
    char testing[] = "Reality is not what it used to be.";
    set(beany, testing);    // первым аргументом является ссылка,
    // Выделяет пространство для хранения копии testing,
    // использует элемент типа str структуры beany как указатель
    // на новый блок, копирует testing в новый блок и
    // создает элемент ct структуры beany
 
    show(beany);        // выводит строковый член структуры один раз
    show(beany, 2);     // выводит строковый член структуры два раза
    testing[0] = 'D';
    testing[1] = 'u';
    show(testing);      // выводит сроку testing один раз
    show(testing, 3);   // выводит строку testing три раза
    show("Done");
    
    return 0;
}
 
void show(const char * str, int times)
{
    for (int i = 0; i < times; ++i)
        std::cout << str << std::endl;
}
 
void show(const stringy & some, int times)
{
    for (int i = 0; i < times; ++i)
        std::cout << some.str << std::endl;    
}
 
void set(stringy & some, const char * cstr)
{
    some.ct = std::strlen(cstr);
    some.str = new char[some.ct+1];
    std::strcpy(some.str, cstr);
}
Но задумался, а как будет освобождаться память?
В упражнении об этом ни слова. С классами - понятно, там деструкторы есть.
А здесь как? Отдельный метод написать? Типа
C++
1
2
3
4
void del(stringy & some)
{
    delete [] some.str;
}
Или просто в конце мэйна добавить
что-то вроде
C++
1
delete [] beany.str;
?

Или в саму структуру зафигачить конструктор с деструктором? Но по логике автора обучающийся ещё такого не знает. Это, типа, плавный переход от структур к понимаю классов. Как вот в таком случае правильно "плавно перейти"?
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
28.02.2015, 17:03
Ответы с готовыми решениями:

Стивен Прата (гл. 6, упр. 6) - массив структур
Что-то упускаю, не могу понять, что именно. Не выводит список имён. Кто подскажет, почему? // sp_Ch6_Pg301_Ex06 /// Занятия по...

9 Задача 4 главы Стивен Прата
Выполните упражнение 6, но вместо объявления массива из трех структур CandyBar используйте операцию new для динамического размещения...

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

10
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
28.02.2015, 18:11
Может так
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <iostream>
#include <cstring>  // для strlen(), strcpy()
 
struct stringy
{
    char * str;     // указывает на строку
    int ct;         // длина строки (не считая символа '\0')
};
 
void show(const char * str, int times = 1);
void show(const stringy & some, int times = 1);
char * set(stringy & some, const char * cstr);
 
int main()
{
    stringy beany;
    char testing[] = "Reality is not what it used to be.";
    char *ch=NULL;
    ch=set(beany, testing);    // первым аргументом является ссылка,
    // Выделяет пространство для хранения копии testing,
    // использует элемент типа str структуры beany как указатель
    // на новый блок, копирует testing в новый блок и
    // создает элемент ct структуры beany
 
    show(beany);        // выводит строковый член структуры один раз
    show(beany, 2);     // выводит строковый член структуры два раза
    testing[0] = 'D';
    testing[1] = 'u';
    show(testing);      // выводит сроку testing один раз
    show(testing, 3);   // выводит строку testing три раза
    show("Done");
 
    delete []ch;  //Перед каждым вызовом Set и по окончанию необходимости.
    return 0;
}
 
void show(const char * str, int times)
{
    for (int i = 0; i < times; ++i)
        std::cout << str << std::endl;
}
 
void show(const stringy & some, int times)
{
    for (int i = 0; i < times; ++i)
        std::cout << some.str << std::endl;
}
 
char * set(stringy & some, const char * cstr)
{
    some.ct = std::strlen(cstr);
    some.str = new char[some.ct+1];
    std::strcpy(some.str, cstr);
    return some.str;
}
1
Модератор
Эксперт CЭксперт С++
 Аватар для sourcerer
5288 / 2376 / 342
Регистрация: 20.02.2013
Сообщений: 5,773
Записей в блоге: 20
28.02.2015, 18:18  [ТС]
daslex, set() не должна возвращать никакого значения, из условия это ясно видно. Кроме того, в условии сказано, что
Функция set() должна использовать операцию new для выделения
достаточного пространства памяти под хранение заданной строки.
То есть, выделение памяти должно происходить именно внутри метода set()
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
28.02.2015, 18:26
Цитата Сообщение от gru74ik Посмотреть сообщение
Как вот в таком случае правильно "плавно перейти"?
Вариант a: не использовать ручное выделение памяти, а использовать std::string в качестве члена структуры.
Мотивация: В современном С++ не принято ручное управление памятью без веской необходимости.
_____
Вариант б: написать конструктор копирования, оператор присваивания(реализующие глубокое копирование, либо какой-то способ передачи владения), и деструктор для структуры.
Мотивация: Если стоит задача научиться пользоваться классами, то конструкторы и деструкторы - это неотъемлемая их часть.

Остальные способы выглядят сомнительно.
1
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
28.02.2015, 18:32
Только или если возвращать значение или добавлять еще 1 параметр. Или деструктор с конструктором, о котором читатель якобы еще не знает.
Потому что этот указатель на который выделяется память - это локальная переменная. А во всех учебниках говорят, что локальные переменные уничтожаются после завершения работы функции. Если адрес не зарезервирован, а мы к нему обращаемся, пытаясь почистить, то к чему все это ведет, ни к чему хорошему.

Если не так как у меня, то единственное конструктор с деструктором.

Добавлено через 5 минут

Не по теме:

Цитата Сообщение от gru74ik Посмотреть сообщение
Функция set() должна использовать операцию new для выделения
достаточного пространства памяти под хранение заданной строки.
То есть, выделение памяти должно происходить именно внутри метода set()
у меня ваш код, где именно так и происходит. поэтому непосредственно это замечание мне не понятно.

1
Модератор
Эксперт CЭксперт С++
 Аватар для sourcerer
5288 / 2376 / 342
Регистрация: 20.02.2013
Сообщений: 5,773
Записей в блоге: 20
28.02.2015, 18:34  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Вариант a: не использовать ручное выделение памяти, а использовать std::string в качестве члена структуры.
Мотивация: в современном С++ не принято ручное управление памятью без веской необходимости.
Увы, в задаче определённо строка в стиле Си.

Цитата Сообщение от DrOffset Посмотреть сообщение
Вариант б: написать конструктор копирования, оператор присваивания(реализующие глубокое копирование, либо какой-то способ передачи владения), и деструктор для структуры.
Мотивация: Если стоит задача научиться пользоваться классами, то конструкторы и деструкторы - это неотъемлемая их часть.
DrOffset, это всё логично и понятно. Я бы и сам так сделал. Но предполагается, что обучающийся про такие штуки не знает на стадии выполнения этого упражнения (8 глава). Работа с классами начнётся только с 10 главы. А тема "Динамическая память и классы" и вовсе рассматривается только в 12 главе.

Цитата Сообщение от DrOffset Посмотреть сообщение
Остальные способы выглядят сомнительно.
Я тоже так подумал, почему и тему на форуме создал. Не смог понять, чего же хотел автор учебника?

Добавлено через 2 минуты
Цитата Сообщение от daslex Посмотреть сообщение
у меня ваш код, где именно так и происходит. поэтому непосредственно это замечание мне не понятно.
daslex, мой код вот:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
//  sp_Ch8_Pg427_Ex04
/// Занятия по книге Стивена Праты "Язык программирования С++" (2013, 6-е изд.).
/// Упражнения по программированию. Глава 8, страница 427, упражнение 4.
/*
Завершите программу, создав соответствующие функции и прототипы. Обратите
внимание, что в программе должны быть две функции show(), и каждая из
них использует аргументы по умолчанию. Где необходимо, используйте const.
Функция set() должна использовать операцию new для выделения достаточного
пространства памяти под хранение заданной строки. Используемые здесь
методы аналогичны методам, применяемым при проектировании и реализации
классов. (В зависимости от используемого компилятора, может понадобиться
изменить имена заголовочных файлов и удалить директиву using.)
*/
#include <iostream>
#include <cstring>  // для strlen(), strcpy()
 
struct stringy
{
    char * str;     // указывает на строку
    int ct;         // длина строки (не считая символа '\0')
};
 
void show(const char * str, int times = 1);
void show(const stringy & some, int times = 1);
void set(stringy & some, const char * cstr);
void del(stringy & some);
 
int main()
{
    stringy beany;
    char testing[] = "Reality is not what it used to be.";
    set(beany, testing);    // первым аргументом является ссылка,
    // Выделяет пространство для хранения копии testing,
    // использует элемент типа str структуры beany как указатель
    // на новый блок, копирует testing в новый блок и
    // создает элемент ct структуры beany
 
    show(beany);        // выводит строковый член структуры один раз
    show(beany, 2);     // выводит строковый член структуры два раза
    del(beany);
    testing[0] = 'D';
    testing[1] = 'u';
    show(testing);      // выводит сроку testing один раз
    show(testing, 3);   // выводит строку testing три раза
    show("Done");
 
    return 0;
}
 
void show(const char * str, int times)
{
    for (int i = 0; i < times; ++i)
        std::cout << str << std::endl;
}
 
void show(const stringy & some, int times)
{
    for (int i = 0; i < times; ++i)
        std::cout << some.str << std::endl;
}
 
void set(stringy & some, const char * cstr)
{
    some.ct = std::strlen(cstr);
    some.str = new char[some.ct+1];
    std::strcpy(some.str, cstr);
}
 
void del(stringy & some)
{
    delete [] some.str;
}
1
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
28.02.2015, 18:34
Лучший ответ Сообщение было отмечено gru74ik как решение

Решение

Цитата Сообщение от gru74ik Посмотреть сообщение
Не смог понять, чего же хотел автор учебника?
Скорее всего на этом этапе автор считает вопрос освобождения памяти несущественным. Поэтому полностью пропустил этот момент и акцентирует внимания на других вещах.
1
Модератор
Эксперт CЭксперт С++
 Аватар для sourcerer
5288 / 2376 / 342
Регистрация: 20.02.2013
Сообщений: 5,773
Записей в блоге: 20
28.02.2015, 18:39  [ТС]
daslex, в задании в учебнике весь код мэйна уже написан. Надо написать только определения методов:
Завершите программу, создав соответствующие функции и прототипы.
0
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
28.02.2015, 19:47

Не по теме:

Все верно. Код не ваш. Невнимательность моя, однако.



Добавлено через 26 минут

Не по теме:

Цитата Сообщение от gru74ik Посмотреть сообщение
delete [] beany.str;
Лучший из трех вариантов предполагаемых вначале. Ибо мало писанины.

И я выше погорячился. По ссылке же, значит речь о локальной копии некорректна.

1
Модератор
Эксперт CЭксперт С++
 Аватар для sourcerer
5288 / 2376 / 342
Регистрация: 20.02.2013
Сообщений: 5,773
Записей в блоге: 20
28.02.2015, 20:52  [ТС]
Цитата Сообщение от daslex Посмотреть сообщение
Лучший из трех вариантов предполагаемых вначале. Ибо мало писанины.
Перечитал 8-ю главу у Праты. Судя по всему, Вы правы. Автор учебника так же делает в своих примерах. Давно читал, сейчас только упражнения выполняю, поскольку большая часть информации уже понятна и мне известна. Просто хочется прорешать всё подряд, что бы уж наверняка ничего не упустить. Системный подход, так сказать. Но иногда и перечитывать приходится. Ладно, повторение - мать учения.

Добавлено через 2 минуты
Цитата Сообщение от daslex Посмотреть сообщение
И я выше погорячился. По ссылке же, значит речь о локальной копии некорректна.
Погорячились. Но, как мне кажется, дело не в ссылке. Смотрим, к примеру, листинг 8.9. из того же учебника:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// left.cpp -- string function with a default argument
#include <iostream>
const int ArSize = 80;
char * left(const char * str, int n = 1);
int main()
{
    using namespace std;
    char sample[ArSize];
    cout << "Enter a string:\n";
    cin.get(sample,ArSize);
    char *ps = left(sample, 4);
    cout << ps << endl;
    delete [] ps;       // free old string
    ps = left(sample);
    cout << ps << endl;
    delete [] ps;       // free new string
    // cin.get();
    // cin.get();
    return 0;
}
 
// This function returns a pointer to a new string
// consisting of the first n characters in the str string.
char * left(const char * str, int n)
{
    if(n < 0)
        n = 0;
    char * p = new char[n+1];
    int i;
    for (i = 0; i < n && str[i]; i++)
        p[i] = str[i];  // copy characters
    while (i <= n)
        p[i++] = '\0';  // set rest of string to '\0'
    return p; 
}
Добавлено через 6 минут
Хотя тут return есть... Да, похоже, и правда, дело в ссылке.
1
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
28.02.2015, 21:42
Ну нет. Этот пример больно напоминает мне мой первый ответ в эту ветку.
..............
Здорово бы было если автор акцентировал свое внимание, что обязательно нужен адрес ячейки памяти для корректного высвобождения памяти. Что этот адрес должен быть именно, что правильным адресом, а не фейковым. И что именно для этого там вон в примере нужен параметр-ссылка, а тут в примере коли уж ссылки нету, то надо ее насильно ретурном вытягивать, причем в обязательном порядке. Но что эту ссылку на адрес нам кровь из носа надо знать. Подозреваю, что на это нет акцента.


прототипы
C++
1
2
3
const inline void show(const char *, const int times = 1);
const inline void show(const stringy &, const int times = 1);
const inline void set(stringy &, const char *);
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
28.02.2015, 21:42
Помогаю со студенческими работами здесь

Шилдт или Стивен Прата: что выбрать?
Недавно закончил вводный курс от Яндекс по C++. Хотел бы дальше продолжить изучать язык. В интернете нарыл, что хвалят учебник Шилда...

Стивен Прата - про decltype (гл. 8, стр. 422)
Прочитал раз десять. Сверился с оригиналом: Я что-то упустил или тип функции long? Соответственно, и m должна быть long? С какого...

Стивен Прата Кто Читал его ? - Нужен Совет
Нужна книжка по изучению C++ ,так сказать &quot;С НУЛЯ&quot;,чтоб всё разжевывалось. Остановился На авторе Стивен Прата ,книга - Язык...

книга стивен прата как справиться с задачей стр 342 листинг 7.12
стивен прата 6 издание. стр 343 листинг 7.12 strctfun переписал код, код полностью работает и проблем в этом нет, но при вводе данных по...

Стивен Прата Язык программирования C++ лекции и упражнения (6-е издание). Листинг 6.8 - странная штука
Извиняюсь заранее, если было уже где-то - я не нашел( Штудирую Прату 6-е издание. Полностью перекопировал Листинг 6.8.: #include...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути
Programma_Boinc 01.01.2026
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути Сочетание глобально распределённой вычислительной мощности и инновационных. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru