Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Двухсвязный линейный список на C, пишу программу, нужна помощь 
:(
    Опции темы
lesha_od
Дата 3.12.2006, 15:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 3.12.2006

Репутация: нет
Всего: нет



В университете дали задание сделать двухсвязный линейный список, над которым можно было бы выполнять определенные действия.
Но при этом я не понимаю, что представляет этот тип списка. И что именно должны делать те или иные операции, куда добавлять элементы и т.п.
Преподавателя увы сложно выловить. Вот само задание:
-------
Задание
Реализовать линейный двухсвязный список для хранения следующих данных:
- фамилия,
- год поступления,
-средний балл.
Обеспечить выполнение операций:
- добавление элемента в неупорядоченный список,
- удаление  элемента с заданным полем «фамилия» в неупорядоченном списке,
- сортировка списка по полю «фамилия»,
- добавление и удаление заданного элемента из упорядоченного списка  с поиском «слева» и «справа»,
- распечатка содержимого списка.
-------
То есть должен быть список, его элементы, и связи между элементами. А вот какие связи - это мне неизвестно.
Вот так я начинал делать программу (но это неправильно - нужен другой тип списка).

Код

#include <iostream>
#include <conio.h>
#include <windows.h>
using namespace std;

struct Elem 
{
    char surname[30];
    int year;
    double avg;
    Elem * next;
    Elem * prev;
    Elem(char * sn,int y, double a)
    {
        strcpy(surname,sn);
        year = y;
        avg = a;
        next=NULL;
        prev=NULL;
    }
    Elem()
    {
        year = 0;
        avg=0;
        strcpy(surname,"");
        next=NULL;
        prev=NULL;
    }
};

class List
{
    Elem *head;
    Elem *tail;
public:
    List():head(NULL),tail(NULL){}
    void Print()const;
    void AddToHead(const Elem &value);
};



void List::Print()
{
    Elem * ptr = head;
    if (head==NULL)
        cout<<endl<<" List is Empty"<<endl;
    cout<<endl;
    while(ptr)
    {
        cout<<ptr->surname<<endl;
        cout<<ptr->year<<endl;
        cout<<ptr->avg<<endl;
        ptr = ptr->next;
    }

}

void List::AddToHead(const Elem & value)
{
    Elem * newvalue = new Elem;
    strcpy(newvalue->surname,
        value.surname);
    newvalue->year = value.year;
    newvalue->avg = value.avg;
    if (NULL == head)
    {
        head = tail = newvalue;
    }
    else{
        newvalue->next = head;
        head = newvalue;
        newvalue->next->prev = head;
    }
}

void main() {
List l1;
Elem e1;
strcpy(e1.surname,"aaa");
e1.year=1997;
e1.avg=15;
l1.AddToHead(e1);
Elem e2;
strcpy(e2.surname,"bbb");
e2.year=1953;
e2.avg=16;
l1.AddToHead(e2);
l1.Print();
}


Поясните, пожалуйста, что от меня хотят. Либо если не сложно, как это реализовать.
PM MAIL   Вверх
DFooz
Дата 3.12.2006, 16:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 81
Регистрация: 3.9.2006

Репутация: нет
Всего: нет



Вот пример двунаправленного списка
Код

#include <iostream>
#include <cstdlib> //for exit
#include <iomanip>
using namespace std;

struct card {
                            char *author;
                            char *title;
                            char *firm;
                            int edition;
                            int year;
                        };
//--------------------
void printbook(card & car) //printing of record
{
    static int count = 0;
    cout << "\n" << ++count << ". " << car.author;
    cout << " - " << car.title << ", " << car.firm;
    cout << ", " << car.edition << ", " << car.year;
}
//--------------------                        
struct record {
                                card book;
                                record *prior;
                                record *next;
                            };                        
//--------------------
card books[] = {
    {"Wiener", "Turbo C++", "Mir", 3, 1991},
    {"Stroustrup", "C++", "DiaSoft", 2, 1991},
    {"Turbo C++", "Programming", "INTKV", 1, 1993},
    {"Lippman", "C++ for beginners", "GELION", 1, 1994}
};
//--------------------
int main(void)
{
    record *begin = NULL,    //begin list pointer
                 *current = NULL,    //current record pointer
                 *list; // record pointer
    
    int n = sizeof(books)/sizeof(books[0]);
    for (int i = 0; i < n; i++)
        {    //
            current = new(record);
            //
            (*current).book.author = books[i].author;
            (*current).book.title = books[i].title;
            current->book.firm = books[i].firm;
            current->book.edition =  books[i].edition;
            current->book.year = books[i].year;
            
            if (begin == NULL)
                {
                    current->prior = NULL;
                    current->next = NULL;
                    begin = current;
                    list = begin;
                }
            else
                {
                    current->next = NULL;
                    current->prior = list;
                    list->next = current;
                    list = list->next;
                    
                }
      }

    list = begin;
    while (list)
        {
            printbook(list->book);
            list = list->next;
        }
            
    
  cin.get();
  return 0;
}


PM MAIL   Вверх
lesha_od
Дата 3.12.2006, 23:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 3.12.2006

Репутация: нет
Всего: нет



Спасибо за ответ.
Двунаправленный - это линейный двухсвязный или другой?
PM MAIL   Вверх
Anikmar
Дата 3.12.2006, 23:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 9
Всего: 59



Насколько я помню - двунаправленный список, это список, в котором каждый элемент имеет ссылку как на предыдущий так и на следующий элемент, соответственно можно двигаться по списку как в пряммом так и в обратном направлении...

Если воспользуетесь поиском - недавно аналогичная тема достаточно подробно разбиралась с кучей примеров... (правда не помню в этом конкретном форуме или нет), но тема настолько избитая, что поиск должен выдать огромную массу информации.
PM MAIL ICQ   Вверх
lesha_od
Дата 4.12.2006, 11:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 3.12.2006

Репутация: нет
Всего: нет



Я такое и сделал вначале. А мне сказали, что надо по-другому.
Может, кто-нибудь знает наверняка?

p.s. В поиске нашел многое, но не то...
PM MAIL   Вверх
Anikmar
Дата 4.12.2006, 12:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 9
Всего: 59



Цитата(lesha_od @ 4.12.2006,  11:51)
Я такое и сделал вначале. А мне сказали, что надо по-другому.

Может тот, кто сказал по-другому и скажет как? Или хотя бы что не так?
Многие преподаватели несколько по-разному подходят к таким вопросам.


PM MAIL ICQ   Вверх
Mayk
Дата 4.12.2006, 12:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: 45
Всего: 134



Цитата(Anikmar @  4.12.2006,  16:09 Найти цитируемый пост)

Многие преподаватели несколько по-разному подходят к таким вопросам.

Ну не имели же они в виду двунаправленную очередь. 

Их можно отправить читать Кормена и др.
Цитата(Cormen et al)

Как показано на рис 10 3 каждый элемент дважды связанного списка(doubly linked list) L - это объект с одним полем key и двумя полями-указателями: next(следующий) и prev(предыдущий)

И двухсвязный список сложно понять как-то по иному  smile 


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
Anikmar
Дата 4.12.2006, 12:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 9
Всего: 59



Цитата(Mayk @ 4.12.2006,  12:11)
И двухсвязный список сложно понять как-то по иному  smile

Лично я нет, но иногда такие задания в форумах выплювывают, что я уже ничему не удивляюсь. Иных преподавтелей не мешало бы самих немного подучить.

Недавно лично видел, как бедолага студент делал свою минисубд в курсовике по теме "Динамическое распределение памяти".

Ну на фига в такой теме заставлять свою СУБД писать?! Человек больше провозился с файловыми операциями чем с заданием по теме...
PM MAIL ICQ   Вверх
lesha_od
Дата 4.12.2006, 15:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 3.12.2006

Репутация: нет
Всего: нет



Ок, чем отличается линейный двухсвязный от простого двухсвязного?
И в задании говорится:

- добавление элемента в неупорядоченный список,
.....
- добавление и удаление заданного элемента из упорядоченного списка  с поиском «слева» и «справа»,

То есть возможно указатели next и prev указывают не так что 1 <-> 2 <-> 3 а по-другому?
1 -> 2 -> 3 -> 4
2 <- 4 <- 1 <- 3
PM MAIL   Вверх
Anikmar
Дата 4.12.2006, 15:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 9
Всего: 59



Кто-то писал так:
Цитата

Список называется линейным, если входящие в него элементы линейно-упорядочены, то есть элементы могут быть выстроены в логическую линию. Упорядоченность может задаваться с помощью ссылок (указателей), располагаемых в элементах и дающих возможность для каждого элемента определить его предшественника и последователя. Такой список называется связным. Наиболее простой способ объединить некоторое множество элементов - это "вытянуть их в линию ", то есть организовать линейный связный список. В линейном односвязном списке каждый элемент состоит из двух различных по назначению видов полей: содержательные поля или информационные и поля структурного (или логического) указателя. Поле логического указателя хранит адрес в памяти следующего элемента списка. Пользуясь указателем, можно получить доступ к элементу списка, а от него к следующему и т. д.
Линейный двусвязный список дает возможность двигаться в одном из двух направлений. Он отличается от односвязного тем, что каждый его элемент содержит два логических указателя, один из которых (прямой указатель) адресует следующий элемент, а другой указатель (обратный) адресует предыдущий элемент списка. Кольцевой двусвязный список отличается от линейного двусвязного списка тем, что у него нет конечных элементов. Первому предшествует последний, а следующий за последним - первый.


Отсюда вывод: двусвязный список является частным случаем линейного...
Ромб, он же параллелограмм...

Хотя быть может я и не прав  smile 
PM MAIL ICQ   Вверх
lesha_od
Дата 4.12.2006, 15:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 3.12.2006

Репутация: нет
Всего: нет



Спасибо, понял. То есть код  который я написал в 1 сообщении этой темы, правильно описывает нужный тип списка?
PM MAIL   Вверх
Anikmar
Дата 4.12.2006, 15:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 9
Всего: 59



Описывает да, на счет реализации - не смотрел, если честно.
PM MAIL ICQ   Вверх
Arks
Дата 4.12.2006, 16:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 197
Регистрация: 7.5.2006
Где: Барнаул

Репутация: нет
Всего: нет



Lesh_od
Неплохо бы проверять длину строки sn в конструкторе прежде, чем копировать иначе можешь память попортить.
Вместо strcpy(surname,"") не проще ли написать surname[0] = '\0' ?
В AddToHead нужно ещё: newvalue->prev=NULL сделать.
Также у тебя там описан неупорядоченный список, т.к. всегда добавляется к голове. В упорядоченном списке тебе следует проходить список вперёд или назад и искать ту позицию в которую нужно добавить элемент.
Кроме того, у тебя не написан деструктор к классу List!
И ещё удаления отдельного элемента из класса List у тебя нет   smile 

Добавлено @ 16:25 
Подписался

Это сообщение отредактировал(а) Arks - 4.12.2006, 16:58
PM MAIL ICQ Skype MSN   Вверх
lesha_od
Дата 6.12.2006, 00:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 3.12.2006

Репутация: нет
Всего: нет



Arks, Спасибо. Да, я знаю, что над программой надо работать и работать. Сейчас займусь этим, и напишу о результатах.
PM MAIL   Вверх
lesha_od
Дата 6.12.2006, 01:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 3.12.2006

Репутация: нет
Всего: нет



Взял за основу программу человека из другого варианта, и изменил под свой вариант. Все вроде бы ничего, учитывая, что в C++ я ничего не понимаю в указателях. Но почему-то при выполнении выдается ошибка.

Код

#include <iostream>
#include <conio.h>
#include <windows.h>
using namespace std;

struct Elem 
{
    char surname[30];
    int year;
    double avg;
    Elem * next;
    Elem * prev;
    Elem(char * sn,int y, double a)
    {
        strcpy(surname,sn);
        year = y;
        avg = a;
        next=NULL;
        prev=NULL;
    }
    Elem()
    {
        year = 0;
        avg=0;
        strcpy(surname,"");
        next=NULL;
        prev=NULL;
    }
};

class List
{
    Elem *head;
    Elem *tail;
public:
    List():head(NULL),tail(NULL){}
    /*virtual ~List()
    {
        ClearAll();
    }*/
    void Print()const;
    void AddToHead(const Elem &value);
    int DelSurname(const char *name);
    int HowMany();
    void DelNum(const int & position);
    void DeleteFromHead();
    void DeleteFromTail();
};



void List::Print()const
{
    Elem * ptr = head;
    if (head==NULL)
        cout<<endl<<" List is Empty"<<endl;
    cout<<endl;
    while(ptr)
    {
        cout<<ptr->surname<<endl;
        cout<<ptr->year<<endl;
        cout<<ptr->avg<<endl;
        ptr = ptr->next;
    }

}

void List::AddToHead(const Elem & value)
{
    Elem * newvalue = new Elem;
    strcpy(newvalue->surname,
        value.surname);
    newvalue->year = value.year;
    newvalue->avg = value.avg;
    if (head == NULL)
    {
        head = tail = newvalue;
    }
    else{
        newvalue->next = head;
        head = newvalue;
        newvalue->next->prev = head;
    }
}

int List::DelSurname(const char *name)
{
    Elem * ptr=head;
    int i=0;
    int count=0;
    while(ptr)
    {
        if (!strcmp(ptr->surname,name))
        {    
            ptr=ptr->next;
            this->DelNum(i);            
            count++;            
        }
        else
        {
            ptr=ptr->next;
            i++;
        }
    } ;
    return count;
}

int List::HowMany()
{
    Elem * ptr = head;
    int counter = 0;
    while (ptr)
    {
        ptr = ptr->next;
        counter++;
    }
    return counter;
}

void List::DeleteFromHead()
{
    if(NULL==head)
    {
        cout<<endl<<"\tList Is Empty !!!!!"<<endl;
        return;
    }
    Elem * ptr = head; 
    head = head->next; 
    if(head)
        head->prev = NULL;  
    delete ptr;
}

void List::DeleteFromTail()
{
    if(NULL==tail)
    {
        cout<<endl<<"\tList  Is Empty !!!!! \t\t\t"<<endl;
        return;
    }
    Elem * ptr = tail; 
    tail = tail->prev; 
    if(tail)
        tail->next = NULL;  
    delete ptr;
}

void List::DelNum(const int & position)
{
    int temp = HowMany();
    if (position>=0 && position<=temp-1)
    {
        if (0==position)
            DeleteFromHead();
        else if (HowMany()-1==position)
            DeleteFromTail();
        else
        {
            int count=0;
            Elem * ptr=head;
            while (position-1!=count)
            {
                ptr=ptr->next;
                count++;
            }
            Elem * temp=ptr->next;
            ptr->next=ptr->next->next;
            ptr->next->next->prev=temp;
            delete temp;
            return;
        }
    }else
    {
        cout<<endl<<"\t Wrong index !!!!! \t\t\t"<<endl;    
        return;
    }
    
}

void main() {
List l1;
Elem e1;
strcpy(e1.surname,"aaa");
e1.year=1997;
e1.avg=15;
l1.AddToHead(e1);
Elem e2;
strcpy(e2.surname,"bbb");
e2.year=1953;
e2.avg=16;
l1.AddToHead(e2);
Elem e3;
strcpy(e3.surname,"ccc");
e3.year=1964;
e3.avg=16;
l1.AddToHead(e3);
Elem e4;
strcpy(e4.surname,"ddd");
e4.year=1955;
e4.avg=16;
l1.AddToHead(e4);
l1.Print();
l1.DelNum(2);
l1.Print();
l1.DelSurname("bbb");
l1.Print();
}

PM MAIL   Вверх
Arks
Дата 6.12.2006, 07:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 197
Регистрация: 7.5.2006
Где: Барнаул

Репутация: нет
Всего: нет



Для начала поправь то, на что я тебе в предыдущем посте указал. Особенно в AddToHead - это ведь ведёт к будущим ошибкам.
Касательно, нового кода в проге, могу сказать, что функцию List::DelNum лучше спрятать подальше от глаз людских и никогда не использовать  smile 
Она во-первых, жутко медленная - список от начала и до нужного элемента проходится аж ТРИ РАЗА! Во-вторых, я так понял она должна бы удалять элемент в i-ой позиции, а похоже удаляет в i+1 -ой. Отсюда может и быть ошибка. Чтобы точно узнать, оттрасируй.
В любом случае, эту функцию следует переписать, т.к. ты сейчас работаешь со списком, будто он односвязный. У двусвязного списка перед односвязным преимущество в том, что нам не требуется проходить его когда нужно добавить (если мы знаем после/перед каким эл-м добавлять) или удалить элемент, где-то в середине. Нам достаточно знать адрес элемента для этого.
Т.е. вместо удаления по номеру, нужно написать удаление по адресу:
Код
void List::DelElem(Elem *ptr)
{
 if(!ptr)
   return;
 if(ptr->prev)
   ptr->prev->next = ptr->next;
 if(ptr->next)
   ptr->next->prev = ptr->prev;
 if(ptr==head)
   head = ptr->next;
 if(ptr==tail)
   tail = ptr->prev;
 delete ptr;
}

И ещё, когда работаешь со списками, рисуй наброски на бумаге - здорово поможет избагать ошибок.

Это сообщение отредактировал(а) Arks - 6.12.2006, 07:22
PM MAIL ICQ Skype MSN   Вверх
lesha_od
Дата 6.12.2006, 08:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 3.12.2006

Репутация: нет
Всего: нет



До того, как я прочитал последнее сообщение, я наладил ту программу, которая была. Потом добавил деструктор List и заменил удаление на показанное тобой. Сейчас она выглядит так:

Код

 #include <iostream>
#include <conio.h>
#include <windows.h>
using namespace std;

struct Elem 
{
    char surname[30];
    int year;
    double avg;
    Elem * next;
    Elem * prev;
    Elem(char * sn,int y, double a)
    {
        strcpy(surname,sn);
        year = y;
        avg = a;
        next=NULL;
        prev=NULL;
    }
    Elem()
    {
        year = 0;
        avg=0;
        strcpy(surname,"");
        next=NULL;
        prev=NULL;
    }
};

class List
{
    Elem *head;
    Elem *tail;
public:
    List():head(NULL),tail(NULL){}
    virtual ~List()
    {
        ClearAll();
    }
    void Print();
    void AddToHead(Elem &value);
    void DelSurname(const char *name);
    int HowMany();
    void DelNum(const int & position);
    void DeleteFromHead();
    void ClearAll();
    void DeleteFromTail();
    void DelElem(Elem *ptr);
};

void List::ClearAll()
{
    int size = HowMany();
    for (int i = 0;i<size;i++)
    {
        DeleteFromHead();
    }
}


void List::Print()
{
    Elem * ptr = head;
    if (head==NULL)
        cout<<endl<<" List is Empty"<<endl;
    cout<<endl;
    while(ptr)
    {
        cout<<ptr->surname<<endl;
        cout<<ptr->year<<endl;
        cout<<ptr->avg<<endl;
        if (ptr->next !=NULL) cout<<"Next El: "<<ptr->next->surname<<endl;
        if (ptr->prev !=NULL) cout<<"Prev El: "<<ptr->prev->surname<<endl;
        ptr = ptr->next;
    }

}

void List::AddToHead(Elem & value)
{
    Elem * newvalue = new Elem;
    strcpy(newvalue->surname,
        value.surname);
    newvalue->year = value.year;
    newvalue->avg = value.avg;
    if (head == NULL)
    {
        head = tail = newvalue;
    }
    else{
        newvalue->next = head;
        head = newvalue;
        newvalue->next->prev = head;
    }
}

void List::DelElem(Elem *ptr)
{
 if(!ptr)
   return;
 if(ptr->prev)
   ptr->prev->next = ptr->next;
 if(ptr->next)
   ptr->next->prev = ptr->prev;
 if(ptr==head)
   head = ptr->next;
 if(ptr==tail)
   tail = ptr->prev;
 delete ptr;
}

void List::DelSurname(const char *name)
{
    Elem * ptr=head;
    int i=0;
    for (int k=0; k<this->HowMany();k++)
    {
        if (!strcmp(ptr->surname,name))
        {    
            cout<<"Equals: "<<name<<" and "<<ptr->surname<<"\n";
            DelElem(ptr);
            break;
        }
        else
        {
            ptr=ptr->next;
        }
    }

};

int List::HowMany()
{
    Elem * ptr = head;
    int counter = 0;
    while (ptr)
    {
        ptr = ptr->next;
        counter++;
    }
    return counter;
}

void List::DeleteFromHead()
{
    if(NULL==head)
    {
        cout<<endl<<"\tList Is Empty !!!!!"<<endl;
        return;
    }
    Elem * ptr = head; 
    head = head->next; 
    if(head)
        head->prev = NULL;  
    delete ptr;
}

void List::DeleteFromTail()
{
    if(NULL==tail)
    {
        cout<<endl<<"\tList  Is Empty !!!!! \t\t\t"<<endl;
        return;
    }
    Elem * ptr = tail; 
    tail = tail->prev; 
    if(tail)
        tail->next = NULL;  
    delete ptr;
}

/*void List::DelNum(const int & position)
{
    int temp = HowMany();
    if (position>=0 && position<=temp-1)
    {
        if (0==position)
            DeleteFromHead();
        else if (HowMany()-1==position)
            DeleteFromTail();
        else
        {
            int count=0;
            Elem * ptr=head;
            while (position-1!=count)
            {
                ptr=ptr->next;
                count++;
            }
            Elem * temp=ptr->next;
            ptr->next=ptr->next->next;
            if (ptr->next->next != NULL) ptr->next->next->prev=ptr;
            else ptr->next->prev=ptr;
            delete temp;
            return;
        }
    }else
    {
        cout<<endl<<"\t Wrong index !!!!! \t\t\t"<<endl;    
        return;
    }
    
}*/

void main() {
List l1;
Elem e1;
strcpy(e1.surname,"aaa");
e1.year=1997;
e1.avg=15;
l1.AddToHead(e1);
Elem e2;
strcpy(e2.surname,"bbb");
e2.year=1953;
e2.avg=16;
l1.AddToHead(e2);
Elem e3;
strcpy(e3.surname,"ccc");
e3.year=1964;
e3.avg=16;
l1.AddToHead(e3);
Elem e4;
strcpy(e4.surname,"ddd");
e4.year=1955;
e4.avg=16;
l1.AddToHead(e4);
Elem e5;
strcpy(e5.surname,"eee");
e5.year=1955;
e5.avg=16;
l1.AddToHead(e5);
Elem e6;
strcpy(e6.surname,"fff");
e6.year=1955;
e6.avg=16;
l1.AddToHead(e6);
l1.Print();
cout<<"\n"<<l1.HowMany()<<"\n";
l1.DelSurname("aaa");
l1.Print();

}


Если все это соответствует заданию, то мне сейчас осталось:
1)- сортировка списка по полю «фамилия»,
2)- добавление и удаление заданного элемента из упорядоченного списка  с поиском «слева» и «справа»

Для сортировки, наверное, имеет смысл выбрать самую простую (пузырьковую) и написать функцию Change (Elem *one, Elem *two).
А что значит 2-ое, то есть работа с упорядоченным списком?

Добавлено @ 08:34 
Нашел в форуме такую сортировку:

Код

void swapitem(item*&a,item*&b)
{
    item c;
    c.element=b->element;
    b->element=a->element;
    a->element=c.element;
}
void bublesortlist(void)
{
   item *p,*q,*end=NULL;
   q=list->next;
   while( q->next!=end)
   {
       for(p=q;p->next!=end;p=p->next)
       {
           if(p->element>p->next->element)
           {
               swapitem(p,p->next);
           }
       }
       end=p;
   }
}

PM MAIL   Вверх
lesha_od
Дата 6.12.2006, 09:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 3.12.2006

Репутация: нет
Всего: нет



Я попытался сделать хотя бы смену элементов, но она не работает. Почему- пока не разобрался, наверное я меняю копии объектов. Вот так это выглядит:

Код

    void swapitem(Elem *a,Elem *b);
    void bublesortlist();

Код

void List::swapitem(Elem *a,Elem *b)
{
    cout<<"changing elements "<<a->surname<<" and "<<b->surname<<"\n";
        Elem c;
    strcpy(c.surname,b->surname);
    c.avg=b->avg;
    c.year=b->year;
    strcpy(b->surname,a->surname);
    b->avg=a->avg;
    b->year=a->year;
    strcpy(a->surname,c.surname);
    a->avg=c.avg;
    a->year=c.year;
}

Код

void List::bublesortlist()
{
   Elem *p,*q,*end=NULL;
   q=head;
   while( q->next!=end)
   {
       for(p=q;p->next!=end;p=p->next)
       {
           if(p->surname>p->next->surname)
           {
               swapitem(p,p->next);
           }
       }
       end=p;
   }
}



Код

l1.swapitem(&e1,&e2);


Убирал указатели (то есть swapitem(Elem a,Elem b)) - ничего не дало.

Полный текст программы:
Код

 #include <iostream>
#include <conio.h>
#include <windows.h>
using namespace std;

struct Elem 
{
    char surname[30];
    int year;
    double avg;
    Elem * next;
    Elem * prev;
    Elem(char * sn,int y, double a)
    {
        strcpy(surname,sn);
        year = y;
        avg = a;
        next=NULL;
        prev=NULL;
    }
    Elem()
    {
        year = 0;
        avg=0;
        strcpy(surname,"");
        next=NULL;
        prev=NULL;
    }
};

class List
{
    Elem *head;
    Elem *tail;
public:
    List():head(NULL),tail(NULL){}
    virtual ~List()
    {
        ClearAll();
    }
    void Print();
    void AddToHead(Elem &value);
    void DelSurname(const char *name);
    int HowMany();
    void DelNum(const int & position);
    void DeleteFromHead();
    void ClearAll();
    void DeleteFromTail();
    void DelElem(Elem *ptr);
    void swapitem(Elem *a,Elem *b);
    void bublesortlist();
};

void List::ClearAll()
{
    int size = HowMany();
    for (int i = 0;i<size;i++)
    {
        DeleteFromHead();
    }
}


void List::Print()
{
    Elem * ptr = head;
    if (head==NULL)
        cout<<endl<<" List is Empty"<<endl;
    cout<<endl;
    while(ptr)
    {
        cout<<ptr->surname<<endl;
        cout<<ptr->year<<endl;
        cout<<ptr->avg<<endl;
        if (ptr->next !=NULL) cout<<"Next El: "<<ptr->next->surname<<endl;
        if (ptr->prev !=NULL) cout<<"Prev El: "<<ptr->prev->surname<<endl;
        ptr = ptr->next;
        cout<<endl;
    }

}

void List::AddToHead(Elem & value)
{
    Elem * newvalue = new Elem;
    strcpy(newvalue->surname,
        value.surname);
    newvalue->year = value.year;
    newvalue->avg = value.avg;
    if (head == NULL)
    {
        head = tail = newvalue;
    }
    else{
        newvalue->next = head;
        head = newvalue;
        newvalue->next->prev = head;
    }
}

void List::DelElem(Elem *ptr)
{
 if(!ptr)
   return;
 if(ptr->prev)
   ptr->prev->next = ptr->next;
 if(ptr->next)
   ptr->next->prev = ptr->prev;
 if(ptr==head)
   head = ptr->next;
 if(ptr==tail)
   tail = ptr->prev;
 delete ptr;
}

void List::DelSurname(const char *name)
{
    Elem * ptr=head;
    int i=0;
    for (int k=0; k<this->HowMany();k++)
    {
        if (!strcmp(ptr->surname,name))
        {    
            cout<<"Equals: "<<name<<" and "<<ptr->surname<<"\n";
            DelElem(ptr);
            break;
        }
        else
        {
            ptr=ptr->next;
        }
    }

};

int List::HowMany()
{
    Elem * ptr = head;
    int counter = 0;
    while (ptr)
    {
        ptr = ptr->next;
        counter++;
    }
    return counter;
}

void List::DeleteFromHead()
{
    if(NULL==head)
    {
        cout<<endl<<"\tList Is Empty !!!!!"<<endl;
        return;
    }
    Elem * ptr = head; 
    head = head->next; 
    if(head)
        head->prev = NULL;  
    delete ptr;
}

void List::DeleteFromTail()
{
    if(NULL==tail)
    {
        cout<<endl<<"\tList  Is Empty !!!!! \t\t\t"<<endl;
        return;
    }
    Elem * ptr = tail; 
    tail = tail->prev; 
    if(tail)
        tail->next = NULL;  
    delete ptr;
}

/*void List::DelNum(const int & position)
{
    int temp = HowMany();
    if (position>=0 && position<=temp-1)
    {
        if (0==position)
            DeleteFromHead();
        else if (HowMany()-1==position)
            DeleteFromTail();
        else
        {
            int count=0;
            Elem * ptr=head;
            while (position-1!=count)
            {
                ptr=ptr->next;
                count++;
            }
            Elem * temp=ptr->next;
            ptr->next=ptr->next->next;
            if (ptr->next->next != NULL) ptr->next->next->prev=ptr;
            else ptr->next->prev=ptr;
            delete temp;
            return;
        }
    }else
    {
        cout<<endl<<"\t Wrong index !!!!! \t\t\t"<<endl;    
        return;
    }
    
}*/


void List::swapitem(Elem *a,Elem *b)
{
    cout<<"changing elements "<<a->surname<<" and "<<b->surname<<"\n";
    Elem c;
    strcpy(c.surname,b->surname);
    c.avg=b->avg;
    c.year=b->year;
    strcpy(b->surname,a->surname);
    b->avg=a->avg;
    b->year=a->year;
    strcpy(a->surname,c.surname);
    a->avg=c.avg;
    a->year=c.year;
}

void List::bublesortlist()
{
   Elem *p,*q,*end=NULL;
   q=head;
   while( q->next!=end)
   {
       for(p=q;p->next!=end;p=p->next)
       {
           if(p->surname>p->next->surname)
           {
               swapitem(p,p->next);
           }
       }
       end=p;
   }
}

void main() {
List l1;
Elem e1;
strcpy(e1.surname,"aaa");
e1.year=1997;
e1.avg=15;
l1.AddToHead(e1);
Elem e2;
strcpy(e2.surname,"bbb");
e2.year=1953;
e2.avg=16;
l1.AddToHead(e2);
Elem e3;
strcpy(e3.surname,"ccc");
e3.year=1964;
e3.avg=16;
l1.AddToHead(e3);
Elem e4;
strcpy(e4.surname,"ddd");
e4.year=1955;
e4.avg=16;
l1.AddToHead(e4);
Elem e5;
strcpy(e5.surname,"eee");
e5.year=1955;
e5.avg=16;
l1.AddToHead(e5);
Elem e6;
strcpy(e6.surname,"fff");
e6.year=1955;
e6.avg=16;
l1.AddToHead(e6);
l1.Print();
cout<<"\n"<<l1.HowMany()<<"\n";
l1.swapitem(&e1,&e2);
//l1.DelSurname("aaa");
l1.Print();

}


Это сообщение отредактировал(а) lesha_od - 6.12.2006, 09:24
PM MAIL   Вверх
Annihilator
Дата 6.12.2006, 09:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


bytegrinder
**


Профиль
Группа: Участник
Сообщений: 493
Регистрация: 21.11.2006
Где: Омск

Репутация: 1
Всего: 3



Цитата(lesha_od @  6.12.2006,  01:35 Найти цитируемый пост)
в C++ я ничего не понимаю в указателях

А вот это оччччень зря, друг! Обязательно разберись! Без них какой смысл??


--------------------
Если вы не можете сделать хоpошyю пpогpаммy, сделайте, чтобы она по кpайней меpе выглядела хоpошо
PM ICQ   Вверх
Arks
Дата 6.12.2006, 11:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 197
Регистрация: 7.5.2006
Где: Барнаул

Репутация: нет
Всего: нет



Для начала советую подумать, что случится с указателем ptr после его удаления. Понял? Так вот, а ты его после этого используешь! Если не понял о чём, я можешь глянуть листинг ниже. Там новая правильная версия функции DelElem.

Когда же ты обмениваешь элементы списка между собой в сортировке, то вовсе ненужно физически их содержимое обменивать местами, достаточно просто поменять соответсвующие связи. Разбираться, что у тебя там не так с сортировкой не охото, сам немного подумай ;)
Единственное скажу, что это не лучший метод. Для не очень длинных списков (<20) эффективно будет применять сортировку вставками (InsertSort), а для длинных списков сорт. слияниями (MergeSort).
Код

Elem* List::DelElem(Elem *ptr)
{
 if(!ptr)
   return;
 if(ptr->prev)
   ptr->prev->next = ptr->next;
 if(ptr->next)
   ptr->next->prev = ptr->prev;
 if(ptr==head)
   head = ptr->next;
 if(ptr==tail)
   tail = ptr->prev;
 Elem *resptr = prt->next;
 delete ptr;
 return resptr;
}

П.С.: Почитай про указатели. Да же на этом форуме (в этом разделе) кое-что есть.
PM MAIL ICQ Skype MSN   Вверх
lesha_od
Дата 6.12.2006, 13:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 3.12.2006

Репутация: нет
Всего: нет



Про указатели я знаю в общих чертах. Когда долго программируешь на Java, совсем не охота запутываться с ссылками\указателями на C.

Я пробовал и ссылки поменять на элементы. Но по неизвестной мне причине они не меняются местами, хоть убей. Сортировку-то я сделаю, любым способом.

Код

void swapitem(Elem *a,Elem *b);

void List::swapitem(Elem *a,Elem *b)
{
Elem * c;
c=a;
a=b;
b=c;
}

Должно работать?
PM MAIL   Вверх
Arks
Дата 6.12.2006, 21:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 197
Регистрация: 7.5.2006
Где: Барнаул

Репутация: нет
Всего: нет



Неа, не должно. smile  Ты обмениваешь значения указателей, а не тех элементов на которые они указывают.
Тоже самое, что и в ссылках Java, там таким присваиванием ты обменяешь ссылки, а не сами объекты.
Указатели Си и ссылки Java по сути одно и тоже (попровте меня кто-нибудь, если ошибаюсь), по-крайней мере я не вижу между ними никакой разницы, кроме синтаксиса.
Т.е. тебе нужно так:
Код
void List::swapitem(Elem *a,Elem *b)
{
 Elem c=*a;
 *a = *b;
 *b = c;
}

В Java ты бы делал это через клонирование.

Но это не эффективно. То что я предлагал, это изменения соответсвующих указателей a->next; a->prev; b->next; b->prev.
Итак, берёшь бумагу. Рисуешь прямоугольники-кирпичи, которые будут обозначать элементы. Рисуешь связи, и смотришь как надо изменить (рисуя эти изменения на бумаге) эти связи. Вперёд и с песней  smile 
PM MAIL ICQ Skype MSN   Вверх
lesha_od
Дата 7.12.2006, 09:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 3.12.2006

Репутация: нет
Всего: нет



Arks,
твой код меняет сами элементы, но не меняет указатели на них соседних элементов... то есть функция Print() выдает то же самое и до, и после обмена.

Тогда я попробовал с указателями.... вроде бы связи правильные, но не работает из-за синтаксиса.

Код

void List::swapitem(Elem *a,Elem *b)
{
 a->next=b->next;
 b->next=b->prev;
 b->prev=a->prev;
 a->prev=b;
}


user posted image

и плюс в эту функцию нужно добавить 
Код

 if (a->prev!=NULL) a->prev->next=b;
 else head=b;
 if (b->next!=NULL) b->next->prev=a;
 else tail=a;


(связи с предыдущими элементами)

Но не работает.

Это сообщение отредактировал(а) lesha_od - 7.12.2006, 09:36
PM MAIL   Вверх
Arks
Дата 7.12.2006, 11:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 197
Регистрация: 7.5.2006
Где: Барнаул

Репутация: нет
Всего: нет



Проверил все рассмотренные варианты.

1) У тебя swapitem, кстати, был совершенно корректно написан ещё в этом посте.
Если ты запустишь сортировку, она должна отработать верно, если ещё где-нибудь не закосячил.
Просто, когда меняешь местами e1 и e2, ты меняешь местами именно их, а не то, что содержится в списке. Посмотри адреса в указателях, они разные. Причина в том, что ты копируешь элементы при добавлении. Если их не копировать, то всё ок:
Код
void List::AddToHead(Elem & value)
{
    if (head == NULL)
    {
        head = tail = &value;
    }
    else{
        value.next = head;
        head = &value;
        value.next->prev = head;
        value.prev = NULL;
    }
}

Правда в этом случае, придётся немного изменить ф-цию main, чтобы не вылетало ошибок (ведь список удаляет свои элементы):
Код
void main() {
List l1;
Elem *e1 = new Elem;
strcpy(e1->surname,"aaa");
e1->year=1997;
e1->avg=15;
l1.AddToHead(*e1);
Elem *e2 = new Elem;
strcpy(e2->surname,"bbb");
e2->year=1953;
e2->avg=16;
l1.AddToHead(*e2);
Elem *e3 = new Elem;
strcpy(e3->surname,"ccc");
e3->year=1964;
e3->avg=16;
l1.AddToHead(*e3);
Elem *e4 = new Elem;
strcpy(e4->surname,"ddd");
e4->year=1955;
e4->avg=16;
l1.AddToHead(*e4);
Elem *e5 = new Elem;
strcpy(e5->surname,"eee");
e5->year=1955;
e5->avg=16;
l1.AddToHead(*e5);
Elem *e6 = new Elem;
strcpy(e6->surname,"fff");
e6->year=1955;
e6->avg=16;
l1.AddToHead(*e6);
l1.Print();
cout<<"\n"<<l1.HowMany()<<"\n";
l1.swapitem(e2,e1);
//l1.DelSurname("aaa");
l1.Print();
getch();
}


2)Твой вариант, как я и сказал не работает. Вот этот:
Код
void List::swapitem(Elem *a,Elem *b)
{
Elem * c;
c=a;
a=b;
b=c;
}


3) Мой вариант тоже не катит  smile 
Связи портятся.

4)Вариант и изменением ссылок - самый замутный, но и самый эффективный, особенно если собираешься расширять кол-во информационных полей в будущем.
Ты в принципе понял, что я имел ввиду, но закосячил реализвацию. Вот так верно:
Код
    a->next=b->next;
    b->next=a;
    b->prev=a->prev;
    a->prev=b;
    if(a->next)
        a->next->prev=a;
    else
        tail = a;
    if(b->prev)
        b->prev->next=b;
    else
        head = b;

Ещё элементы должны следовать в правильном порядке, т.е. чтобы работало должно быть так:
Код
...
l1.swapitem(e2,e1);
...

PM MAIL ICQ Skype MSN   Вверх
lesha_od
Дата 7.12.2006, 14:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 3.12.2006

Репутация: нет
Всего: нет



Спасибо за такой подробный ответ! Я уже начинаю понимать, как эти указатели работаютsmile
Программа работает, выполняет требуемое от нее. Единственное, что не работает - если вручную запустить смену элементов, и до или после нее попытаться удалить "хвостовой" элемент с фамилией "ааа", то выдается ошибка.

Update: оказалось, сравнение строк не работает по знаку ">". Видимо, надо сравнивать по-другому.

Вот код работающей программы:

Код

#include <iostream>
#include <conio.h>
#include <windows.h>
using namespace std;
struct Elem 
{
    char surname[30];
    int year;
    double avg;
    Elem * next;
    Elem * prev;
    Elem(char * sn,int y, double a)
    {
        strcpy(surname,sn);
        year = y;
        avg = a;
        next=NULL;
        prev=NULL;
    }
    Elem()
    {
        year = 0;
        avg=0;
        strcpy(surname,"");
        next=NULL;
        prev=NULL;
    }
};
class List
{
    Elem *head;
    Elem *tail;
public:
    List():head(NULL),tail(NULL){}
    virtual ~List()
    {
        ClearAll();
    }
    void Print();
    void AddToHead(Elem &value);
    void DelSurname(const char *name);
    int HowMany();
    void DelNum(const int & position);
    void DeleteFromHead();
    void ClearAll();
    void DeleteFromTail();
    void DelElem(Elem *ptr);
    void swapitem(Elem* a,Elem* b);
    void bublesortlist();
};
void List::ClearAll()
{
    int size = HowMany();
    for (int i = 0;i<size;i++)
    {
        DeleteFromHead();
    }
}
void List::Print()
{
    Elem * ptr = head;
    if (head==NULL)
        cout<<endl<<" List is Empty"<<endl;
    cout<<endl;
    while(ptr)
    {
        cout<<ptr->surname<<endl;
        cout<<ptr->year<<endl;
        cout<<ptr->avg<<endl;
        if (ptr->next !=NULL) cout<<"Next El: "<<ptr->next->surname<<endl;
        if (ptr->prev !=NULL) cout<<"Prev El: "<<ptr->prev->surname<<endl;
        ptr = ptr->next;
        cout<<endl;
    }
}


void List::AddToHead(Elem & value)
{
    if (head == NULL)
    {
        head = tail = &value;
    }
    else{
        value.next = head;
        head = &value;
        value.next->prev = head;
        value.prev = NULL;
    }
}

void List::DelElem(Elem *ptr)
{
 if(!ptr)
   return;
 if(ptr->prev)
   ptr->prev->next = ptr->next;
 if(ptr->next)
   ptr->next->prev = ptr->prev;
 if(ptr==head)
   head = ptr->next;
 if(ptr==tail)
   tail = ptr->prev;
 delete ptr;
}

void List::DelSurname(const char *name)
{
    Elem * ptr=head;
    int i=0;
    for (int k=0; k<this->HowMany();k++)
    {
        if (!strcmp(ptr->surname,name))
        {    
            cout<<"Equals: "<<name<<" and "<<ptr->surname<<"\n";
            DelElem(ptr);
            break;
        }
        else
        {
            ptr=ptr->next;
        }
    }
};

int List::HowMany()
{
    Elem * ptr = head;
    int counter = 0;
    while (ptr)
    {
        ptr = ptr->next;
        counter++;
    }
    return counter;
}
void List::DeleteFromHead()
{
    if(NULL==head)
    {
        cout<<endl<<"\tList Is Empty !!!!!"<<endl;
        return;
    }
    Elem * ptr = head; 
    head = head->next; 
    if(head)
        head->prev = NULL;  
    delete ptr;
}
void List::DeleteFromTail()
{
    if(NULL==tail)
    {
        cout<<endl<<"\tList  Is Empty !!!!! \t\t\t"<<endl;
        return;
    }
    Elem * ptr = tail; 
    tail = tail->prev; 
    if(tail)
        tail->next = NULL;  
    delete ptr;
}

void List::swapitem(Elem* a,Elem* b)
{
    a->next=b->next;
    b->next=a;
    b->prev=a->prev;
    a->prev=b;
    if(a->next)
        a->next->prev=a;
    else
        tail = a;
    if(b->prev)
        b->prev->next=b;
    else
        head = b;
}

void List::bublesortlist()
{
   Elem *p,*q,*end=NULL;
   q=head;
   while( q->next!=end)
   {
       for(p=q;p->next!=end;p=p->next)
       {
           if(p->surname>p->next->surname)
           {
               swapitem(p,p->next);
           }
       }
       end=p;
   }
}

void main() {
List l1;
Elem *e1 = new Elem;
strcpy(e1->surname,"aaa");
e1->year=1997;
e1->avg=15;
l1.AddToHead(*e1);
Elem *e2 = new Elem;
strcpy(e2->surname,"bbb");
e2->year=1953;
e2->avg=16;
l1.AddToHead(*e2);
Elem *e3 = new Elem;
strcpy(e3->surname,"ccc");
e3->year=1964;
e3->avg=16;
l1.AddToHead(*e3);
Elem *e4 = new Elem;
strcpy(e4->surname,"ddd");
e4->year=1955;
e4->avg=16;
l1.AddToHead(*e4);
Elem *e5 = new Elem;
strcpy(e5->surname,"eee");
e5->year=1955;
e5->avg=16;
l1.AddToHead(*e5);
Elem *e6 = new Elem;
strcpy(e6->surname,"fff");
e6->year=1955;
e6->avg=16;
l1.AddToHead(*e6);
l1.Print();
cout<<"\n"<<l1.HowMany()<<"\n";
l1.DelSurname("aaa");
l1.Print();
l1.bublesortlist();
l1.Print();
getch();
}

а вот строчки, которые в любом порядке убивают программу:
Код

cout<<"\n"<<l1.HowMany()<<"\n"; //эта строка просто показывает, где начинается код
l1.DelSurname("aaa");
l1.swapitem(e3,e2);

Попробую сейчас разобраться, почему ошибка. Наверно какой-то указатель мы таки забыли поставить на место.
P.S. А в принципе, это неважно. Программа же должна быть инкаспулированной, и работать с (e3,e2) необязательно. А в остальных случаях она работает, что отлично.

Это сообщение отредактировал(а) lesha_od - 7.12.2006, 14:36
PM MAIL   Вверх
lesha_od
Дата 11.12.2006, 07:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 3.12.2006

Репутация: нет
Всего: нет



Я начал делать интерфейс ввода данных самим пользователем, и натолкнулся на ошибку. Когда делаю так:
Код

Elem *e1 = new Elem;
strcpy(e1->surname,"aaa");
e1->year=1997;
e1->avg=15;
l1.AddToHead(*e1);
Elem *e5 = new Elem;
strcpy(e5->surname,"bbb");
e5->year=1945;
e5->avg=1;
l1.AddToHead(*e5);
l1.Print();

то все работает нормально.
А как добавить созданный пользователем элемент? Когда я делаю так:
Код

char sname[20];
   int y;
double avg;
     cout<<"Surname: "; 
              cin>>sname;
               cout<<endl<<"Year: ";
               cin>>y;
cout<<endl<<"Average score: ";
              cin>>avg;
 l1.AddToHead(Elem(sname,y,avg));

то программа зависает при распечатке, либо при удалении - в общм, что-то с копиями и объектами не так smile
PM MAIL   Вверх
Arks
Дата 11.12.2006, 18:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 197
Регистрация: 7.5.2006
Где: Барнаул

Репутация: нет
Всего: нет



1) Разве p->surname - строка? Это всего лишь указатель на неё. Для строк есть свои функции. В том числе и для сравнения. Ты сравниваешь указатели. Кстати в DelSurname ты ведь нужную ф-цию используешь, а здесь забыл!

2)Ты память портишь, т.к. не создаёшь таким образом новый объект. Надо:
Код
l1.AddToHead(new Elem(sname,y,avg));

только AddToHead надо перекроить, т.к. сейчас ей параметр передаётся по ссылке, а нам надо по указателю:
Код
void List::AddToHead(Elem *value) {...};

Можно и не перекраивать, но имо, так даже правильнее будет.

3)
Код
cout<<"\n"<<l1.HowMany()<<"\n"; //эта строка просто показывает, где начинается код
l1.DelSurname("aaa");
l1.swapitem(e3,e2);

Таже рожа толька в профиль: смотри про правильный порядок  smile 
А ещё лучше посмотри, что со связями творится в этой функции, после её вызова в отсортированном списке.
Не хочешь париться с порядком. Проверяй в его в функции.
PM MAIL ICQ Skype MSN   Вверх
lesha_od
Дата 12.12.2006, 15:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 3.12.2006

Репутация: нет
Всего: нет



Все отлично заработало, кроме сортировки... я к сожалению не умею нормально отлаживать. Надеюсь, преподаватель сможет помочь с ошибкой.

Как называется функция, проверяющая, является ли введенное значение числом? Скажем я пишу

Код

int i;
cin>>i;


И мне надо точно знать, что это число. А если не число, то выдать сообщение пользователю.
PM MAIL   Вверх
JackYF
Дата 12.12.2006, 15:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 18
Всего: 162



lesha_od,

i в данном случае всегда будет целым числом со знаком.
А проверять придется флаги у cin.


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
Arks
Дата 12.12.2006, 16:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 197
Регистрация: 7.5.2006
Где: Барнаул

Репутация: нет
Всего: нет



Цитата
И мне надо точно знать, что это число. А если не число, то выдать сообщение пользователю. 

Вот так:
Код
int i;
 if(!(cin >> i))
  cout << "not a number";

Я это кстати, где то на этом форуме нашёл.  smile 
PM MAIL ICQ Skype MSN   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1260 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.