Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Кольцевой односвязный список


Автор: ALI46 3.5.2008, 19:55
Разработайте класс, реализующий кольцевой односвязный список. Методы класса: добавление элемента в список, просмотр списка, удаление произвольного элемента из списка. Поля записей: участники, количество забегов, в которых они принимали участие, сумма сделанных на них ставок, количество побед.
я написал вот так:
Код
#include <stdio.h>
#include <conio.h>
#include <iostream.h>
#include <stdlib.h>
class group
{
    private:
        struct runner
        {
            char name[20];
            int zabeg;
            int stavk;
            int pobed;
            runner *next;
        } *begin, *end, *rex;
    public:
        group(); 
        ~group();
        void add(void);
        void del(void);
        void show(void);
        void menu(void);
} g;
void main(void)
{
    g.menu();
}
group :: group()
{
    begin = end = rex = NULL;
}
group :: ~group()
{
    while(begin!=NULL)
    {
        rex = begin;
        begin = begin->next;
        delete rex;
    }
}
void group :: add(void)
{
    //clrscr();
    system("cls");
    rex = new runner;
    cout << "Name:\t";        cin >> rex->name;
    cout << "Zabeg:\t";    cin >> rex->zabeg;
    cout << "Stavka:\t";    cin >> rex->stavk;
    cout << "Kol-vo pobed:\t";    cin >> rex->pobed;
    if(begin == NULL && end == NULL)
        begin = rex;
    else  end -> next = rex;
    end = rex;
    end->next = NULL;
}
void group :: del(void)
{
    //clrscr();
    system("cls");
    if(begin == NULL && end == NULL)
    {
        cout << "The is no runners!!!" << endl << "Press any key..." << endl;
        getch();
        return;
    }
    rex = begin;
    begin = begin->next;
    delete rex;
    if(begin == NULL)
        end = NULL;
}
void group :: show(void)
{
//    clrscr();
    system("cls");
    int i = 1;
    rex = begin;
    if(rex == NULL)
    {
        cout << "The group is empty!!!" << endl;
        getch();
        return;
    }
    while(rex != NULL)
    {
        cout << i <<". Name:\t" << rex->name
                << "\tZabeg: " << rex->zabeg
                << "\tStavka: " << rex->stavk
                << "\tKol-vo pobed: " << rex->pobed<< endl;
        rex = rex->next;
        i++;
    }
    cout << "Press any key..." << endl; getch();
}
void group :: menu(void)
{
    int key = 0;
    do
    {
//        clrscr();
        system("cls");
        cout << "1 - add runner" << endl << "2 - delete runner" <<endl
                << "3 - show runners" << endl << "Esc - exit" << endl << "Press any key..." << endl;
        key = getch();
        switch(key)
        {
            case 49: add(); break;
            case 50: del(); break;
            case 51: show();
        }
    }while(key!=27);
}


Подскажите пожалуйста - как реализовать ввод/вывод списка в один и тот же бинарный файл, как сделать удаление произвольного элемента(у меня удаляет первый в списке) и как сделать данный список кольцевым односвязным(у меня линейный односвязный)?

Автор: Annihilator 4.5.2008, 16:27
Цитата(ALI46 @  3.5.2008,  23:55 Найти цитируемый пост)
как реализовать ввод/вывод списка в один и тот же бинарный файл

ты собираешься считывать и записывать в один файл? Может лучше 2 сделать - один для чтения другой для записис, чтобы путанницы не возникло

Цитата(ALI46 @  3.5.2008,  23:55 Найти цитируемый пост)
как сделать удаление произвольного элемента(у меня удаляет первый в списке)

во-первых заведи счетчик номера элемента. Ты считываешь данные элемента, пихая указатель начала списка в функцию. Так вот как только считал этот элемент, а следовательно и его поля, рекурсивно пихни указатель на следующий элемент, содержащийся в поле только что прочтенного и делай это столько раз пока у тебя счетчик, который при каждом заходе в функцию будет инкрементироваться (не сам конечно, а пропиши это), не станет равен номеру элемента, который надо удалить

Цитата(ALI46 @  3.5.2008,  23:55 Найти цитируемый пост)
как сделать данный список кольцевым односвязным

у последнего элемента присвой указателю на следующий элемент адрес первого элемента

Автор: ALI46 4.5.2008, 16:43
Цитата(Annihilator @  4.5.2008,  16:27 Найти цитируемый пост)
ты собираешься считывать и записывать в один файл? Может лучше 2 сделать - один для чтения другой для записис, чтобы путанницы не возникло

мне в задании сказано что ввод/вывод должен осуществляться в один бинарный файл, как это сделать?
Цитата(Annihilator @  4.5.2008,  16:27 Найти цитируемый пост)
у последнего элемента присвой указателю на следующий элемент адрес первого элемента

а в каком именно месте? smile 

Автор: Annihilator 4.5.2008, 19:18
Цитата(ALI46 @  4.5.2008,  20:43 Найти цитируемый пост)
каком именно месте

в поле УКАЗАТЕЛЬ НА СЛЕДУЮЩИЙ ЭЛЕМЕНТ, там ведь связь как раз осуществляется между элементами с помощью этого поля!

Автор: ALI46 7.5.2008, 21:01
удаление произвольного элемента я так реализовал

Код

//
в структуре runner я добавил указатель *num
//

void group :: del(void)
{
    //clrscr();
    system("cls");
    int n,i;
    
    if(begin == NULL && end == NULL)
    {
        cout << "The group is empty!!!" << endl << "Press any key..." << endl;
        getch();
        return;
    }
    
    cout << "Enter number to delete:" << endl;
    cin >> n;
    
    if (n>1&&end!=NULL)
    {
        rex = begin;
        num = rex->next;
        for (i=1;i<n-1;i++) {num = num->next; rex = rex->next;}
        rex->next=num->next;
        delete num; 
    }
    if (n==1)
    {
        rex = begin;
        begin = begin->next;
        delete rex;    
    }
    if(begin == NULL) end = NULL;
}


но как ввести/вывести в один файл и сделать список кольцевым без зацикленного вывода не знаю...

Автор: Annihilator 7.5.2008, 21:16
Цитата(ALI46 @  8.5.2008,  01:01 Найти цитируемый пост)
сделать список кольцевым без зацикленного вывода 

запомни где-нибудь адрес первого элемента. Далее бежишь по списку и как только у тебя rex->next будет равен адресу первого элемента, выводи rex и завершай вывод

Автор: ALI46 7.5.2008, 22:23
в методе add я вместо
Код

end->next = NULL; //следующий после последнего элемента - NULL

прописал
Код

end->next = begin; //следующий после последнего элемента - первый элемент


а в методе show вместо
Код

 while(rex != NULL)

написал
Код

 while(rex != begin)


в итоге ничо не выводит

Автор: ALI46 12.5.2008, 19:25
список так и остался линейным, ноя добавил чтение-запись в файл...
Код

#include <stdio.h>
#include <conio.h>
#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>
#define N 20
class group
{
    private:
        struct runner
        {
            char name[N];
            int zabeg;
            int stavk;
            int pobed;
            runner *next;
        } *begin, *end, *rex, *num;
    public:
        group(); 
        ~group();
        void add(void);
        void del(void);
        void show(void);
        void menu(void);
        void FileAdd ();
        void FileRead () ;
        int CheckEmpty() const;
} g;
void main(void)
{
    
    g.FileRead();
//    clrscr();
    g.menu();
    g.FileAdd ();
}
group :: group()
{
    begin = end = rex = NULL;
}
group :: ~group()
{
    while(begin!=NULL)
    {
        rex = begin;
        begin = begin->next;
        //end = begin;
        delete rex;
    }
}
void group :: add(void)
{
    //clrscr();
    system("cls");
    rex = new runner;
    cout << "Name:\t";        cin >> rex->name;
    cout << "Zabeg:\t";    cin >> rex->zabeg;
    cout << "Stavka:\t";    cin >> rex->stavk;
    cout << "Kol-vo pobed:\t";    cin >> rex->pobed;
    if(begin == NULL && end == NULL)
        begin = rex;
    else  end->next = rex;
    end = rex;
    end->next = NULL;
}
void group :: del(void)
{
    //clrscr();
    system("cls");
    int n=-1,i;
    
    if(begin == NULL && end == NULL)
    {
        cout << "The group is empty!!!" << endl << "Press any key..." << endl;
        getch();
        return;
    }
    while ((n<1||n>N)&&(begin!=NULL))
    {
        cout << "Enter number to delete:" << endl;
        cin >> n;
        if (n==1)
        {
            rex = begin;            
            begin = begin->next;            
            delete rex;            
        }
        if (n>1&&n<N)
        {
            rex = begin;
            num = rex->next;
            for (i=1;i<n-1;i++) {num = num->next; rex = rex->next;}
            rex->next=num->next;            
            delete num;                    
        }        
    }    
    if(begin == NULL) end = NULL;    
}
void group :: show(void)
{
//    clrscr();
    system("cls");
    int i = 1;
    rex = begin;
    if(rex == NULL)
    {
        cout << "The is no runners!!!" << endl;
        getch();
        return;
    }
    
    while(rex != NULL)
    {
        cout << i <<". Name:\t" << rex->name
                << "\tZabeg: " << rex->zabeg
                << "\tStavka: " << rex->stavk
                << "\tKol-vo pobed: " << rex->pobed<< endl;
        rex = rex->next;
        i++;
    }
    cout << "Press any key..." << endl; getch();    
}
void group :: menu(void)
{
    int key = 0;
    do
    {
//        clrscr();
        system("cls");
        cout << "1 - add runner" << endl << "2 - delete runner" <<endl
                << "3 - show runners" << endl << "Esc - exit" << endl << "Press any key..." << endl;
        key = getch();
        switch(key)
        {
            case 49: add(); break;
            case 50: del(); break;
            case 51: show();
        }
    }while(key!=27);
}


void group::FileAdd (void)
{
    if(!CheckEmpty())
    return;
    rex=begin;
    ofstream out("file.txt", ios::out|ios::binary);
    if (!out)
    {
        cout << "Cannot open file for writing" << endl;
        return ;
    }
    while(rex!=NULL)
    {
        out << rex->name << " " << rex->zabeg << " " << rex->stavk << " " << rex->pobed << " ";
        rex=rex->next;
    }
    out.close();
}

void group::FileRead () 
{
    char a[120];
    ifstream Sout ("file.txt", ios::in|ios::binary);
    if (!Sout)
    {
        return ;
    }
    if(Sout.peek()=='\n')
    {
        Sout.close();
        return;
    }
    while(!Sout.eof()||!CheckEmpty())
    {
        //begin=NULL;
        rex = new runner;
        Sout >> rex->name >> rex->zabeg >> rex->stavk >> rex->pobed;
        //Sout >>    rex->name >> "\n" >> rex->zabeg >> "\n" >> rex->stavk >> "\n" >> rex->pobed >> "\n";
        if(begin==NULL)
        {
            begin=rex;
        }
        else
        {
            end->next=rex;        
        }
        end=rex;
        end->next=NULL;
        if(Sout.peek()=='\n') break;
    }
    cout << "Zagruzka iz fayla..." << endl;
    cout << "Nazhmite lubuyu klavishu..." << endl;
    getch();
    Sout.close();
}

int group::CheckEmpty() const
{
    if(begin==NULL)
        {
            cout<<"List is empty"<<endl;
            getch();
            return 0;
        }
    return 1;
}


однако при запуске в список добавляется мусор если файл пуст, и если мы что нибудь у даляем из списка, то на файле это никак не отражается... в чём причина? и как можно исправить?

Автор: Lycifer 14.5.2008, 09:24
На самом деле все просто:
Цитата

однако при запуске в список добавляется мусор если файл пуст

Дело в том что в файле может быть просто '\n', ну или он действительно пуст(вообще я не проверял), делай проверку что есть что считывать.
Цитата

и если мы что нибудь у даляем из списка, то на файле это никак не отражается... в чём причина? и как можно исправить? 

Самый легкий способ перезаписать файл, то и есть полностью, ну или с помощью сикгнета удалять(я же не знаю как у тебя там хранятся данные)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)