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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Запись и чтение из файла связного списка 
:(
    Опции темы
Hawaii
Дата 19.8.2007, 18:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Код

// linklist.cpp
// linked list
#include <iostream>
#include <fstream>
using namespace std;
////////////////////////////////////////////////////////////////
struct link                           //one element of list
   {
   int data;                          //data item
   link* next;                        //pointer to next link
   };
////////////////////////////////////////////////////////////////
class linklist                        //a list of links
   {
   private:
      link* first;                    //pointer to first link
       
   public:
      linklist()                      //no-argument constructor
         { first = NULL; }            //no first link
      void additem(int d);            //add data item (one link)
      void display();                 //display all links
      void diskOut();
      void diskIn();

   };
//--------------------------------------------------------------
void linklist::additem(int d)         //add data item
   {
   link* newlink = new link;          //make a new link
   newlink->data = d;                 //give it data
   newlink->next = first;             //it points to next link
   first = newlink;                   //now first points to this
   }
//--------------------------------------------------------------
void linklist::display()              //display all links
   {
   cout << endl;
   link* current = first;             //set ptr to first link
   while( current != NULL )           //quit on last link
      {
      cout << current->data << endl;  //print data
      current = current->next;        //move to next link
      }
   cout << endl;   
   }
//--------------------------------------------------------------
void linklist::diskOut()
   {
   ofstream outfile;
   int d;
   outfile.open("data.dat", ios::binary | ios::app);
   link* current = first;           
   while( current != NULL )          
      {
      d = current->data;
      outfile.write(reinterpret_cast<char*>(&d), sizeof(int));
      current = current->next;        
      }
   outfile.close();
   }
 

//--------------------------------------------------------------
void linklist::diskIn()
   {
               
   ifstream infile;
   int d;
   
   infile.open("data.dat", ios::binary );
   infile.seekg(0);
   infile.read((char*)&d,sizeof(int));
   while(infile)
      {    
      link* newlink = new link;
      newlink->data = d;
      newlink->next = first;    
      first = newlink; 
      infile.read((char*)&d,sizeof(int));    
      }
   }
//-------------------------------------------------------------   

////////////////////////////////////////////////////////////////
int main()
 {  
   linklist li;       
   
   int num;
   char ch;
   char ans;
   
   while(true)
   {
   cout << "What do you want to do? "
   "\n'a'-add to list"
   "\n's'-show the list"
   "\n'w'-write to file"
   "\n'r'-read file" 
   "\n'x'-exit" << endl; cin >> ans;
    switch(ans)
      {
      case 'a':  cout << "Enter link in the list: "; cin >> num; li.additem(num); break;      
      case 's':  li.display(); break;
      case 'w':  li.diskOut(); break;
      case 'r':  li.diskIn(); break;
      case 'x':  exit(0);
      default: cout << "Wrong command.";
      }
   }
   
   
   system("PAUSE");
   return 0;
 } 



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

PM MAIL   Вверх
DjoNIK
Дата 19.8.2007, 21:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Просто когда работает программа, то она работает с данными в ОП. Соответственно при создании и заполнении списка переменная li содержит данные в ОП. Когда ты записываеши данные в файл, то получаеться, что ты просто копируешь байты из ОП в файл. При чтении из файла данные копируються из файла в ОП, но у нас в ОП уже есть данные, т.е. к старым происходит прибавление новых данных(копии старых). Если же ты завершишь работу с программой, а потом запустишь её и прочитаешь из файла, то у тебя будет только одна копия - из файла, т.к ОП была пуста.
Если ты хочешь каждый раз при считывании получать только те данные, которые прочитал, то можно перед каждым считыванием затирать весь список.

PS: Если не ошибаюсь это код из Лафоре


--------------------
- Плесни-ка мне холодного кипятку.
- Как кипяток может быть холодным?! Ты, верно, хочешь кипяченой воды?
- Какая ещё кипяченая вода? Не пудри мне мозги - налейхолодного кипятку.
(разговор петербуржца и москвича)
PM MAIL ICQ   Вверх
Xenon
Дата 19.8.2007, 21:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Что-что тебе надо? 
Знакомый пример, кажется из лафорье. Во-первых тебе нужно сделать так, чтобы файл, в который ты сохраняешь, был не констатным, а ты мог другой выбирать. Тогда создай другой список, укажи файл заранее созданный и грузи список. Но на мой взгляд эти две фунции работы с файлом надо вынести из определения класса (но они все равно останутся интерфейсом класса, так как там будет упоминаться список). Эти фунция - это сериализация / десерилизация. И где твой деструктор? smile Лишняя память завелась?
Код

using namespace std;

////////////////////////////////////////////////////////////////
struct link                           //one element of list
{
   int data;                          //data item
   link* next;                        //pointer to next link
   link(int a_data, link* a_next):data(a_data), next(a_next) {}
};
////////////////////////////////////////////////////////////////
class linklist                        //a list of links
{
private:
    link* first;                    //pointer to first link
public:
    linklist():first(0) {}                      //no-argument constructor
    link* begin() const;
    void additem(int d);            //add data item (one link)
    void display() const;                 //display all links
    ~linklist();
};

link* linklist::begin() const
{
    return first;
}

void linklist::additem(int d)         //add data item
{
    first = new link(d, first);
}

void linklist::display() const            //display all links
{
    cout << endl;
    link* current = first;             //set ptr to first link
    while(current)           //quit on last link
    {
        cout << current->data << endl;  //print data
        current = current->next;        //move to next link
    }
    cout << endl;   
}

linklist::~linklist()
{
    link* current = first;
    while (current)
    {
        link* prev = current;
        current = current->next;
        delete prev;
    }
}

void diskOut(ofstream& outfile, const linklist& list)
{
    link* current = list.begin();          
    while(current)     
    {
        int data = current->data;
        outfile.write( reinterpret_cast<char*>(&data), sizeof(int) );
        current = current->next;        
    }
}
 
void diskIn(ifstream& infile, linklist& list)
{
    int d = 0;
    infile.seekg(0);
    infile.read( reinterpret_cast<char*>(&d),sizeof(int) );
    while( !infile.eof() )
    {    
        list.additem(d);
        infile.read( reinterpret_cast<char*>(&d),sizeof(int) );    
    }
}

int main(int argc, char argv[]) 
{
    linklist list;
    list.additem(10);
    list.additem(23);
    list.additem(25);
    std::ofstream out_file("d:\\mylist.dat");
    diskOut(out_file, list);
    out_file.close();
    std::ifstream in_file("d:\\mylist.dat");
    linklist new_list;
    diskIn(in_file, new_list);
    new_list.display();
    cin.get();
    return 0;
}


Это сообщение отредактировал(а) Xenon - 19.8.2007, 21:11


--------------------
user posted image  
PM MAIL   Вверх
Hawaii
Дата 20.8.2007, 00:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Я хочу сделать так, чтобы объекты типа linklist не создавались в main() . Как в этой программе. Здесь данные в ОП не пересекаются с данными на диске при вводе/выводе.
Код

// empl_io.cpp
// performs file I/O on employee objects
// handles different sized objects
#include <fstream>            //for file-stream functions
#include <iostream>
#include <typeinfo>           //for typeid()
using namespace std;
#include <process.h>          //for exit()

const int LEN = 32;           //maximum length of last names
const int MAXEM = 100;        //maximum number of employees

enum employee_type {tmanager, tscientist, tlaborer};
////////////////////////////////////////////////////////////////
class employee                //employee class
   {
   private:
      char name[LEN];         //employee name
      unsigned long number;   //employee number
      static int n;           //current number of employees
      static employee* arrap[];  //array of ptrs to emps
   public:
      virtual void getdata()
         {
         cin.ignore(10, '\n');
         cout << "   Enter last name: "; cin >> name;
         cout << "   Enter number: ";      cin >> number;
         }
      virtual void putdata()
         {
         cout << "\n   Name: " << name;
         cout << "\n   Number: " << number;
         }
      virtual employee_type get_type();  //get type
      static void add();      //add an employee
      static void display();  //display all employees
      static void read();     //read from disk file
      static void write();    //write to disk file
   };
//--------------------------------------------------------------
//static variables
int employee::n;              //current number of employees
employee* employee::arrap[MAXEM];  //array of ptrs to emps
////////////////////////////////////////////////////////////////
//manager class
class manager : public employee
   {
   private:
      char title[LEN];        //"vice-president" etc.
      double dues;            //golf club dues
   public:
      void getdata()
         {
         employee::getdata();
         cout << "   Enter title: ";          cin >> title;
         cout << "   Enter golf club dues: "; cin >> dues;
         }
      void putdata()
         {
         employee::putdata();
         cout << "\n   Title: " << title;
         cout << "\n   Golf club dues: " << dues;
         }
   };
////////////////////////////////////////////////////////////////
//scientist class
class scientist : public employee
   {
   private:
      int pubs;               //number of publications
   public:
      void getdata()
         {
         employee::getdata();
         cout << "   Enter number of pubs: "; cin >> pubs;
         }
      void putdata()
         {
         employee::putdata();
         cout << "\n   Number of publications: " << pubs;
         }
   };
////////////////////////////////////////////////////////////////   
//laborer class
class laborer : public employee
   {
   };
////////////////////////////////////////////////////////////////
//add employee to list in memory
void employee::add()
   {
   char ch;
   cout << "'m' to add a manager"
           "\n's' to add a scientist"
           "\n'l' to add a laborer"
           "\nEnter selection: ";
   cin >> ch;
   switch(ch)
      {                       //create specified employee type
      case 'm': arrap[n] = new manager;   break;
      case 's': arrap[n] = new scientist; break;
      case 'l': arrap[n] = new laborer;   break;
      default: cout << "\nUnknown employee type\n"; return;
      }
   arrap[n++]->getdata();     //get employee data from user
   }
//--------------------------------------------------------------
//display all employees
void employee::display()
   {
   for(int j=0; j<n; j++)
      {
      cout  << (j+1);           //display number
      switch( arrap[j]->get_type() )   //display type
         {
         case tmanager:    cout << ". Type: Manager";   break;
         case tscientist:  cout << ". Type: Scientist"; break;
         case tlaborer:    cout << ". Type: Laborer";   break;
         default: cout << ". Unknown type";
         }
      arrap[j]->putdata();    //display employee data
      cout << endl;
      }
   }
//--------------------------------------------------------------
//return the type of this object
employee_type employee::get_type()
   {
   if( typeid(*this) == typeid(manager) )
      return tmanager;
   else if( typeid(*this)==typeid(scientist) )
      return tscientist;
   else if( typeid(*this)==typeid(laborer) )
      return tlaborer;
   else
      { cerr << "\nBad employee type"; exit(1); }
   return tmanager;
   }
//--------------------------------------------------------------
//write all current memory objects to file
void employee::write()
   {
   int size;
   cout << "Writing " << n << " employees.\n";
   ofstream ouf;              //open ofstream in binary
   employee_type etype;       //type of each employee object

   ouf.open("EMPLOY.DAT", ios::trunc | ios::binary);
   if(!ouf)
      { cout << "\nCan't open file\n"; return; }
   for(int j=0; j<n; j++)     //for every employee object
      {                       //get its type
      etype = arrap[j]->get_type();
                              //write type to file
      ouf.write( (char*)&etype, sizeof(etype) );
      switch(etype)           //find its size
         {
         case tmanager:   size=sizeof(manager); break;
         case tscientist: size=sizeof(scientist); break;
         case tlaborer:   size=sizeof(laborer); break;
         }                    //write employee object to file
      ouf.write( (char*)(arrap[j]), size );
      if(!ouf)
         { cout << "\nCan't write to file\n"; return; }
      }
   }
//--------------------------------------------------------------
//read data for all employees from file into memory
void employee::read()
   {
   int size;                  //size of employee object
   employee_type etype;       //type of employee
   ifstream inf;              //open ifstream in binary
   inf.open("EMPLOY.DAT", ios::binary);
   if(!inf)
      { cout << "\nCan't open file\n"; return; }
   n = 0;                     //no employees in memory yet
   while(true)
      {                       //read type of next employee
      inf.read( (char*)&etype, sizeof(etype) );
      if( inf.eof() )         //quit loop on eof
         break;
      if(!inf)                //error reading type
         { cout << "\nCan't read type from file\n"; return; }
      switch(etype)
         {                    //make new employee
         case tmanager:       //of correct type
            arrap[n] = new manager;
            size=sizeof(manager);
            break;
         case tscientist:
            arrap[n] = new scientist;
            size=sizeof(scientist);
            break;
         case tlaborer:
            arrap[n] = new laborer;
            size=sizeof(laborer);
            break;
         default: cout << "\nUnknown type in file\n"; return;
         }                    //read data from file into it
      inf.read( (char*)arrap[n], size  );
      if(!inf)                //error but not eof
         { cout << "\nCan't read data from file\n"; return; }
      n++;                    //count employee
      }  //end while
   cout << "Reading " << n << " employees\n";
   }
////////////////////////////////////////////////////////////////
int main()
   {
   char ch;
   while(true)
      {
      cout << "'a' -- add data for an employee"
              "\n'd' -- display data for all employees"
              "\n'w' -- write all employee data to file"
              "\n'r' -- read all employee data from file"
              "\n'x' -- exit"
              "\nEnter selection: ";
      cin >> ch;
      switch(ch)
         {
         case 'a':            //add an employee to list
            employee::add(); break;
         case 'd':            //display all employees
            employee::display(); break;
         case 'w':            //write employees to file
            employee::write(); break;
         case 'r':            //read all employees from file
            employee::read(); break;
         case 'x': exit(0);   //exit program
         default: cout << "\nUnknown command";
         }  //end switch
      }  //end while
   return 0;
   }  //end main()




PM MAIL   Вверх
Xenon
Дата 20.8.2007, 00:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Создай в глобальной области видимости объект класса linklist smile


--------------------
user posted image  
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

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

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

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

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


 




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


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

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