Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Сделать поиск в классе книга  (Прочитано 9465 раз)
0 Пользователей и 1 Гость смотрят эту тему.
mihansk
Гость
« : 22-11-2009 09:00 » 

Надо сделать что-то типа библиотеки в виде списка. Классы я создал и список тоже, но с поиском элементов проблема:
kniga* knigalist::vzat(int t)
{kniga* cur;
int colvo;


for (cur=START;cur->getNEXT()!=NULL;cur=cur->getNEXT())
{if(nomer==t)
   {colvo=kolvo;
   colvo--;
   kolvo=colvo;
   return cur;
      printf("kniga vzata\n");

      }

   else {printf("nety\n");
   
   }}
Работает некорректно, помогите найти ошибку.
« Последнее редактирование: 22-11-2009 11:57 от Sel » Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 22-11-2009 09:17 » 

А как вообще работает? не вижу объявления переменных kolvo и nomer - оно что, член класса? Тогда зачем оно?
В любом случае, код
Код:
colvo=kolvo;
colvo--;
kolvo=colvo;
делает что-то странное и непонятное. Что ты пытаешься этим сделать?

Ну и printf после return уже бесполезен - он никогда не будет выполнен. Кроме того, непонятно, почему "nety" должно выводиться каждый раз в цикле при несовпадении номера, хотя поиск ещё не завершён.
« Последнее редактирование: 22-11-2009 09:19 от Вад » Записан
mihansk
Гость
« Ответ #2 : 22-11-2009 09:28 » 

kolvo nomer члены класса
colvo=kolvo;
colvo--;
kolvo=colvo;
с этим я, конечно, намудрил что-то, тут можно сделать напрямую kolvo--?

Тут надо сделать поиск, чтобы при взятии каждой книги вводился номер, и программа уменьшает количество книг на 1, или выдает сообщение об отсутствии книги, или о том, что она кем-то уже взята.
« Последнее редактирование: 22-11-2009 11:59 от Sel » Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 22-11-2009 10:55 » 

Ну хорошо, а зачем kolvo и nomer - вообще члены класса knigalist? В них хранится что-то значимое между вызовами метода vzat? Тогда почему в этом методе kolvo меняется, а новое значение nomer возникает совершенно ниоткуда?

Кстати, ещё один вопрос: что такое t? Это порядковый номер (положение в списке), или какой-то другой произвольный идентификатор, которым обладает книга?
То есть, что нужно найти - книгу, находящуюся в списке на месте t, или книгу, у которой есть внутреннее значение nomer, равное t?
Записан
mihansk
Гость
« Ответ #4 : 22-11-2009 11:07 » new

kolvo и nomer членв класса kniga а knigalist наследованный класс от kniga
t - это как бы параметр, по которому ищется номер книги. Надо найти книгу, у которой есть внутреннее значение nomer, равное t и вычесть из количества этих книг 1.

Исправьте, пожалуйста, если неправиьно сделано.


« Последнее редактирование: 22-11-2009 12:00 от Sel » Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 22-11-2009 11:47 » 

не понимаю, зачем наследовать knigalist от kniga. Номер там всё равно будет свой собственный, а не номер конкретной книги в списке. Поэтому будет работать неправильно.

Я бы разложил иерархию так:
1. Класс kniga. Он вообще ничего не знает про списки книг. Поскольку я не знаю, какие у книги там ещё должны быть поля и в каком формате (название, автор, ...?), пусть для простоты у неё есть только поле number - номер:
Код:
class kniga
{
private:
    int number;
public:
    int getNumber() const { return number; }
};
- я пока не касаюсь вопроса, как устанавливается этот number. Возможно, в конструкторе, или методом setNumber. Для списка это неважно.

Теперь переходим к списку. Очевидно, что нам нужен хотя бы односвязный список, чтобы мы могли пройти по всем книгам. Однако книга ни про какие другие не знает.
Тут есть две идеи, как это сделать:
1. knigalist - это рекурсивная структура, содержащая "голову"-книгу и "хвост"-список.
2. knigalist лишь управляет связным списком, то есть, содержит его.

Первый подход более "функциональный", что ли. Второй - наверное, более свойственный для языков типа С++, где управление памятью выполняется вручную или почти вручную. Схематически покажу оба:
1. Рекурсивная структура
Код:
class knigalist
{
private:
    kniga*      head_; // первый элемент - по-моему, аналог твоего START
    knigalist* tail_;     // остальные элементы
public:
    knigalist(kniga* head,  knigalist* tail) : kniga_(kniga), tail_(tail) {}

    // метод add добавляет книгу в указанную позицию, возвращая новый список, с добавленной книгой
    knigalist* add(kniga* item, int pos); // реализация такого метода - отдельный любопытный вопрос

    // метод getByNumber возвращает книгу, имеющую заданный number
    kniga* getByNumber(int number){
        if (head_.getNumber() == number){
            return head_;
        }
        else if (tail_ != NULL){
            return tail_.getByNumber(number);
        }
        else return NULL;
    }
};

2. управление рекурсивной структурой. Всё, что нам нужно - это прицепить к книге указатель на следующую. Для этого не надо ничего наследовать: обычная композиция является более слабой связью, и её тут достаточно (если интересно, могу отдельно пояснить, что имею в виду под более слабой связью)
Код:
class knigalist{
private:
    // внутреннее представление для элемента списка. Последний элемент содержит null в качестве next
    struct list_item {
            kniga*       book;
            list_item*  next;
    };

    list_item* start_;
    int count_; // мало ли, понадобится хранить размер списка
public:
    // наш метод получения книги из списка по номеру
    kniga* getByNumber(int number)
    {
        list_item* cur = start_;
        for ( ; cur != null; cur = cur->next) {
             if (cur->book->getNumber() == number){
                // прерываем поиск
                break;
             }
        }
        if (cur != null)
            return cur->book;
        else
            return null; // ничего не нашли.
    }
};
второй случай более близок к тому, как подобные вещи обычно в C++ реализуются. Скажем, поиск в контейнерах типа std::list реализован похожим образом.

В общем, это всё - информация к размышлению. Я не привожу здесь полных решений Улыбаюсь И уж тем более, не настаиваю на каком-то конкретном. Просто задачу можно решить множеством интересных способов. И в каждом случае какие-то из способов будут более удобны или эффективны.
« Последнее редактирование: 22-11-2009 11:53 от Вад » Записан
mihansk
Гость
« Ответ #6 : 22-11-2009 12:09 » 

Cпасибо, сейчас в этом попробую разобраться.
« Последнее редактирование: 22-11-2009 12:12 от Sel » Записан
Sel
Злобный
Администратор

ru
Offline Offline

« Ответ #7 : 22-11-2009 12:13 » 

mihansk, а заодно и в русском языке разберись. Вечно править твой олбанизм я не буду, скоро просто удалять посты начну.
Записан

Слово не воробей. Всё не воробей, кроме воробья.
mihansk
Гость
« Ответ #8 : 22-11-2009 12:39 » 

У меня еще один вопрос.

kniga* cur;
for (cur=START;cur->getNEXT()!=NULL;cur=cur->getNEXT())
Этот цикл проходит (n-1) элемент, то есть, если я ввожу 3 элемента, то он просматривает только 2((
B чем ошибка не знаю.
« Последнее редактирование: 22-11-2009 12:42 от Sel » Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 22-11-2009 16:52 » 

У тебя ошибка в условии выхода из цикла.
Пусть есть 3 элемента. Для первого и второго getNext даст следующий элемент. А на третьем витке цикла, когда мы должны проверять cur, являющийся 3м элементом, выражение cur->getNEXT() != NULL имеет значение false, потому что больше элементов нет. Соответственно, выходим из цикла, так и не выполнив третью итерацию.

В общем, тут целых 2 возможных проблемы: первая - что один последний элемент не будет просмотрен. А вторая - если ты подашь пустой список (то есть, START == NULL), то код упадёт при попытке вычислить cur->getNEXT().

А ответ на эти две проблемы один: нужно проверять на NULL не следующий элемент, а текущий:
Код:
for (cur = START; cur != NULL; cur = cur->getNEXT())
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines