0 / 0 / 0
Регистрация: 06.01.2016
Сообщений: 8
1

Логика программы

22.07.2016, 13:05. Показов 616. Ответов 11
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всем доброго времени суток! Помогите, пожалуйста, понять логику программы (код дан целиком) по теме связанные списки типа очередь. Код взят из книги Шилдта "Самоучитель C++" стр. 319. Суть вопроса в следующем: не могу понять, как связующий элемент tail->next связывает список? tail->next принадлежит *this, адрес *this не меняется. В динамических элементах (при отладке) вижу только их адрес и num, и не вижу связь с предыдущим элементом списка. Я, наверно, упустил какое-то уникальное свойство или правило и поэтому не могу понять ... Наверно, точнее смогу объяснить своё непонимание в процессе обсуждения ...

И ещё, когда программа входит в строку где p->store(2); и tail->next = item; то head->next автоматом тоже получает адрес item. Почему?

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include <iostream>
using namespace std;
 
class list {
public:
    list *head;
    list *tail;
    list *next;
    int num;
 
    list() { head = tail = next = NULL; num = 0; }
    virtual ~list() {}
    virtual void store(int i) = 0;
    virtual int retrieve() = 0;
};
 
class queue : public list {
public:
    virtual ~queue() {}
    virtual void store(int i);
    virtual int retrieve();
};
 
void queue::store(int i)
{
    list *item;
    item = new queue;
 
    if (!item) {
        cout << "Ошибка выделения памяти.\n";
        exit(1);
    }
 
    item->num = i;
 
    if (tail) 
        tail->next = item; // где сохраняется и как сцепляет?
                           // если бы tail->next "двигался" как item было бы понятно
    tail = item;
 
    item->next = NULL; // не понял зачем эта строка? item->next всегда NULL
 
    if (!head) // эти две строки понятны
        head = tail;
}
 
int queue::retrieve()
{
    int i;
    list *p;
 
    if (!head) {
        cout << "Список пуст.\n";
 
        return 0;
    }
 
    i = head->num;
    p = head;
    head = head->next;
    delete p;
    p = NULL;
 
    return i;
}
 
int main()
{
    setlocale(LC_ALL, "rus"); // для Visual Studio
 
    list *p;
    queue q_ob;
    p = &q_ob;
 
    p->store(1);
    p->store(2);
    p->store(3);
 
    cout << "Очередь: ";
    cout << p->retrieve();
    cout << p->retrieve();
    cout << p->retrieve();
 
    cout << '\n';
 
    return 0;
}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
22.07.2016, 13:05
Ответы с готовыми решениями:

Логика программы для доступа к БД
Есть потребность получить доступ к базе данных MS Access на удаленной машине и передавать часть...

Нужна логика программы,общие понятия ,переменные
Нужна программа учет оценок студентов на с++ Должно быть Окно в нем поля допустим: Реферат 90...

Условия и логика
Доброго времени суток! Подскажите , почему на выводе 1 ? Желательно поподробнее! Заранее благодарен...

Логика выражения
Изучать С начал недавно, изучение изучением, а вопрос текущий назрел и в литературе когда появится...

11
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
22.07.2016, 13:16 2
Цитата Сообщение от class Alex Посмотреть сообщение
C++
1
2
3
if (tail) 
    tail->next = item; // где сохраняется и как сцепляет?
                  // если бы tail->next "двигался" как item было бы понятно
так он и "двигается" строчкой ниже.
вот здесь:
Цитата Сообщение от class Alex Посмотреть сообщение
C++
1
tail = item;
0
0 / 0 / 0
Регистрация: 06.01.2016
Сообщений: 8
22.07.2016, 15:24  [ТС] 3
Адрес this == p == &q_ob
tail и tail->next "принадлежат структуре данных" this или нет (?). Может к каждому новому динамическому объекту копия this создаётся? Судя по всему я что-то упускаю из фундаментальных знаний о свойстве языка. Когда строится список-стэк там всё просто и понятно. Динамический объект "помечается" адресом от предыдущего объекта через какой-то статический объект и "помечает" его своим адресом для следующего. Так происходит сцепка. А здесь непонятно.
0
Хитрая блондиночка $)
1472 / 988 / 399
Регистрация: 21.12.2015
Сообщений: 3,785
22.07.2016, 15:32 4
Цитата Сообщение от class Alex Посмотреть сообщение
Может к каждому новому динамическому объекту копия this создаётся?
this это всего лишь указание работать с объектом, метод которого сейчас выполняется.
tail->next = item - создается новый объект item. который цепляется к next. В методах, которые содержит этот объект item инструкция this будет равна тому, чему было присвоено в tail->next предидущего созданного объекта.
Ты на this не зацикливайся, это всего лишь удобное указание с какой переменной методу работать.
0
0 / 0 / 0
Регистрация: 06.01.2016
Сообщений: 8
22.07.2016, 15:55  [ТС] 5
Цитата Сообщение от Hikari Посмотреть сообщение
this это всего лишь указание работать с объектом, метод которого сейчас выполняется.
Это я понимаю. Выражаюсь коряво ...

tail->next = item - создается новый объект item. который цепляется к next. В методах, которые содержит этот объект item инструкция this будет равна тому, чему было присвоено в tail->next предидущего созданного объекта.
Точнее, сначала создаётся объект item, а потом tail->next и tail получают адрес этого динамического объекта. Но где они потом зацепляются? По логике получается, что должны создаваться копии этих указателей. И почему вдруг после инструкции: tail->next = item; адрес head->next == tail->next? Ведь явного получения адреса head->next = item не было.

Ты на this не зацикливайся, это всего лишь удобное указание с какой переменной методу работать.
В отладке открывая this видны tail->next и tail - поэтому.
0
Хитрая блондиночка $)
1472 / 988 / 399
Регистрация: 21.12.2015
Сообщений: 3,785
22.07.2016, 16:49 6
Цитата Сообщение от class Alex Посмотреть сообщение
Но где они потом зацепляются?
Ты сам на свой вопрос ответил:
Цитата Сообщение от class Alex Посмотреть сообщение
сначала создаётся объект item, а потом tail->next и tail получают адрес этого динамического объекта.
именно поле next и является сцепкой.
0
0 / 0 / 0
Регистрация: 06.01.2016
Сообщений: 8
22.07.2016, 17:17  [ТС] 7
Цитата Сообщение от Hikari Посмотреть сообщение
Ты сам на свой вопрос ответил:
Да, ничего я не ответил. Номинальный ответ я тоже знаю, но постольку-поскольку так написал Шилдт и компилятор, ну и вы конечно (!). Но в отладке я не вижу связи. У меня нет понимания этого метода, а значит я не смогу применить его в другой ситуации. Посмотрите в отладке и объясните мне "на пальцах" где связь? Очередь строится из динамических "объектов" так? Думаю, что так. Они должны друг за друга цепляться. Эту сцепку они получают от "статического объекта". Этот объект их помечает. Но на деле я не вижу этого.

именно поле next и является сцепкой.
Потому что next ("следующий") ? Хотя, правильнее было-бы предыдущий потому-что текущий получает адрес предыдущего, а не следующего. Хотя, как смотреть: вагон движется или вокзал
0
18822 / 9826 / 2401
Регистрация: 30.01.2014
Сообщений: 17,260
22.07.2016, 17:44 8
class Alex, вот представь себе ситуацию. У тебя есть деревянный ящик, в нем лежит бумажка. На бумажке написано где лежит следующий ящик. Еще у тебя есть две персональные бумажки. На одной (1) написано где лежит первый ящик, на второй(2) написано где лежит последний ящик.
В самом начале у тебя нет ящиков. И вот, тебе принесли один, ты его положил на место. В ящик положил бумажку, но на ней ничего не написал, т.к. больше ящиков у тебя пока нет. На персональную бумажку(1) записал где лежит этот ящик. На персональную бумажку (2), записал где лежит последний ящик. Т.к. ящик один, то местоположения на бумажках пока одинаковые. Теперь тебе принесли второй ящик. Тебе надо добавить его к первому. Ты берешь персональную бумажку(2), находишь на ней местоположение последнего ящика. Достаешь ящик, вынимаешь оттуда бумажку и кладешь другую, на которой написано местоположение только что прибывшего ящика. На персональную бумажку (2) ты записываешь местоположение вновь прибывшего ящика. В только что прибывший ящик, кладешь бумажку, на которой ничего не написано, т.к. больше ящиков пока нет.

Достаточно "на пальцах"?
0
47 / 47 / 31
Регистрация: 02.04.2016
Сообщений: 312
22.07.2016, 18:00 9
Цитата Сообщение от class Alex Посмотреть сообщение
C++
1
2
3
if (tail) 
    tail->next = item; // где сохраняется и как сцепляет?
                  // если бы tail->next "двигался" как item было бы понятно
тут тебе правильно сказали - item - указатель, память для которого выделяется в 27 строке,
Цитата Сообщение от class Alex Посмотреть сообщение
C++
1
item->next = NULL; // не понял зачем эта строка? item->next всегда NULL
тут вы не правы - item->next ссылается на неопределенную область памяти(допустим была переменная по адресу 001, в ней было число 10, потом переменная стала не нужна программе(даже не обязательно, что это ваша программа), и программа дала сигнал системе "мне этот участок памяти больше не нужен" а число 10 из участка памяти никуда не делось, оно там осталось, просто никому не нужно, этот участок память выделяется Вашей программе под указатель, и получается что указывает он на ячейку памяти под номером 10) <- это все конечно примитивно и не учитываются размеры переменных указателей и адресов, но смысл похожий, так вот строчкой item->next = NULL вы "заземляете" указатель, чтобы случайно не изменить участок памяти, который не следует.
0
0 / 0 / 0
Регистрация: 06.01.2016
Сообщений: 8
22.07.2016, 18:22  [ТС] 10
Цитата Сообщение от Stitch Igorek Посмотреть сообщение
тут тебе правильно сказали - item - указатель, память для которого выделяется в 27 строке,
тут вы не правы - item->next ссылается на неопределенную область памяти(допустим была переменная по адресу 001, в ней было число 10, потом переменная стала не нужна программе(даже не обязательно, что это ваша программа), и программа дала сигнал системе "мне этот участок памяти больше не нужен" а число 10 из участка памяти никуда не делось, оно там осталось, просто никому не нужно, этот участок память выделяется Вашей программе под указатель, и получается что указывает он на ячейку памяти под номером 10) <- это все конечно примитивно и не учитываются размеры переменных указателей и адресов, но смысл похожий, так вот строчкой item->next = NULL вы "заземляете" указатель, чтобы случайно не изменить участок памяти, который не следует.
item->next == NULL ещё при инициализации через базовый класс и прямо в программе он не используется. Но зная, что автор этой программы очень крут у меня возник вопрос: для чего? Хотя, закоментировав потом эту инструкцию результат не изменился - NULL от начала до конца программы.

Добавлено через 6 минут
Цитата Сообщение от DrOffset Посмотреть сообщение
... вот представь себе ситуацию. У тебя есть деревянный ящик, в нем лежит бумажка. На бумажке написано где лежит следующий ящик. ...
Это уже похоже на рекурсию

Достаточно "на пальцах"?
Ваши "пальцы" сложнее моего вопроса ... к пониманию

Я понимаю, что у всех, особенно у опытных программистов много дел, но если у вас или других форумчан-программистов есть немного времени, сделайте доброе дело - объясните мне доходчиво. Список-стэк я понял. Там всё наглядно (на простых примерах). Но в построении очереди нет наглядности и часть логики скрыта за свойствами языка, которые я не улавливаю. Давайте, например, хотя-бы с явного: почему в инструкции p->store(2); функц main(), после выполнения инструкции tail->next = item; y head->next то же значение адреса? Какая между ними связь? Это свойство данных в связанной структуре? Я вижу, но не понимаю.
0
18822 / 9826 / 2401
Регистрация: 30.01.2014
Сообщений: 17,260
22.07.2016, 18:39 11
Цитата Сообщение от class Alex Посмотреть сообщение
C++
1
item->next = NULL; // не понял зачем эта строка? item->next всегда NUL
Эта строка и правда не нужна.
Конструктор queue (сгенерированный компилятором) вызывает конструктор list, в котором next устанавливается в NULL.

Добавлено через 11 минут
Цитата Сообщение от class Alex Посмотреть сообщение
функц main(), после выполнения инструкции tail->next = item; y head->next то же значение адреса?
Зря ты внимательно не прочитал что я написал. Вот смотри:
Цитата Сообщение от DrOffset Посмотреть сообщение
Т.к. ящик один, то местоположения на бумажках пока одинаковые.
Т.е. после выполнения store(1) у тебя tail и head указывают на один и тот же объект (пока единственный).
На момент выполнения store(2) в инструкции tail->next = item мы берем первый объект в очереди (он же пока последний) через указатель tail и выставляем у него next в значение указателя нового объекта. Т.к. head и tail на данном этапе ссылаются на один и тот же объект, то возникает описанный тобой эффект "неявной" смены значения head->next). После выполнения tail = item, мы помечаем, что последний элемент - это только что добавленный.

Добавлено через 3 минуты
Если ты посмотришь дальше, на store(3), то убедишься, что head->next больше не меняется.
1
0 / 0 / 0
Регистрация: 06.01.2016
Сообщений: 8
22.07.2016, 18:50  [ТС] 12
Цитата Сообщение от DrOffset Посмотреть сообщение
...
Зря ты внимательно не прочитал что я написал. Вот смотри:
...
Иду спать. У меня уже ночь ... Ваш "код" проанализирую завтра. Думаю в нём начало решения моего непонимания ...
0
22.07.2016, 18:50
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
22.07.2016, 18:50
Помогаю со студенческими работами здесь

C++ мат. логика
НАПИШИТЕ прогу pleas (желательно самый оптимальный вариант): дани число n и а=1, а можно умножать...

CTL логика
Подскажите где искать литературу, у меня курсовая на тему : &quot;Написать библиотеку классов функций...

Логика switch
Программа должна расчитывать количество проданного товара, суть проблемы, кода вместо численных...

Нечеткая логика
Здравствуйте. Помогите пожалуйста с програмкой.


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

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru