Aiuto per programma sui file

di il
9 risposte

Aiuto per programma sui file

Ragazzi c'ho da fare questo programma. La traccia è:
Siete il proprietario di una ferramenta e avete bisogno di mantenere un inventario che possa dirvi quali e quanti attrezzi avete e il costo d'ognuno di essi. Scrivete un programma che inizializza il file con 100 record vuoti, vi consenta di immettere i dati relativi a ogni attrezzo, vi dia la possibilità di elencarli tutti, vi lasci eliminare un record per un attrezzo che non avete più, e vi permetta di aggiornare qualsiasi informazione nel file. Il numero di identificazione dell'attrezzo sarà anche quello del record. Usate le seguenti informazioni, come dati iniziali per il vostro file:

Record n° Nome attrezzo Quantità Costo
3 Martello 7 57.98

Ce ne sono anche altri di dati ma non li scrivo. Il programma non l'ho fatto per intero ma ho solamente inizializzato il file con i record vuoti, ho immesso dei dati, e il prog. me li dovrebbe visualizzare in un file "print.txt", scartando i record che hanno 0 come valore ovviamente. Qualcosa va storto ma non so cosa: questo è il codice. Il prog. si potrebbe fare anche con le classi però al momento mi accontento di farlo in un unico file con una struct. Per le altre funzioni cercherò di implementarle ma solo dopo aver corretto questi errori.

#include <iostream>
#include <fstream>
#include <cstdlib>
#include <iomanip>
#include <string>

using namespace std;

struct Ferramenta
{
       int ID;
       string nome;
       int quantita;
       float costo;
};

void output (ostream& out, const Ferramenta& Fer);
void textFile (fstream& readFromFile);

int main ()
{
       fstream File ("hardware.dat", ios::out | ios::in);
       
       if (!File)
       {
                 cerr << "File could not be opened." << endl;
                 exit(1);
       }
       
       Ferramenta Fer = { 0, "", 0, 0.0 };
            
       for (int i = 0; i < 100; i++)
          File.write( reinterpret_cast <const char*>(&Fer), sizeof(Ferramenta));
          
       cout << "Inserisci il numero di record (da 1 a 100, 0 per uscire)\n? ";
       cin >> Fer.ID;
       
       while (Fer.ID > 0 && Fer.ID <= 100)
       {
             cout << "Inserisci nome dell'attrezzo, la quantità e il costo\n? ";
             cin >> Fer.nome >> Fer.quantita >> Fer.costo;
             
             File.seekp( (Fer.ID - 1) * sizeof(Ferramenta) );
             
             File.write( reinterpret_cast <const char*>(&Fer), sizeof(Ferramenta) );
             
             cout << "Inserisci il numero di record\n? ";
             cin >> Fer.ID;
       }
       
       textFile (File);
       
       system ("pause");
       return 0;
}

void output (ostream& out, const Ferramenta& Fer)
{
     out << endl << setw(15) << setiosflags(ios::left) << Fer.ID
         << setw(25) << Fer.nome << setw(15) << Fer.quantita
         << setw(5) << Fer.costo;
}

void textFile (fstream& readFromFile)
{
     ofstream outPrintFile("print.txt", ios::out);
     
     if (!outPrintFile)
     {
                 cerr << "File could not be opened." << endl;
                 exit(1);
     }
     
     outPrintFile << setiosflags(ios::left) << setw(15) << "Record n°"
                  << setw(25) << "Nome attrezzo" << setw(15) << "Quantita'"
                  << setw(5) << "Costo";

                  
     readFromFile.seekg(0);
     
     Ferramenta fer;
     readFromFile.read(  reinterpret_cast <char*>(&fer), sizeof(Ferramenta) );
     
     while ( !readFromFile.eof())
     {
           if (fer.ID != 0)
              output (outPrintFile, fer);
              
     readFromFile.read(  reinterpret_cast <char*>(&fer), sizeof(Ferramenta) );
     }
}
Il problema è che se eseguo il programma e immetto un solo dato il dato viene visualizzato correttamente. Se ne immetto più di uno nel file print.txt invece stampa caratteri strani. Perchè? Grazie...

9 Risposte

  • Re: Aiuto per programma sui file

    1. Prova ad aprire il file in binario
    2. Controlla il file alla fine della prima scrittura
    3. sizeof su un oggetto non POD non funziona.
  • Re: Aiuto per programma sui file

    Ci sono dei problemi ho scritto anche il resto delle funzioni. Ma qualcosa non va bene. Incollo tutto il codice vedi se riesci a trovare errori perchè io non li vedo. Intanto per il parametro string della struttura dovrei utilizzare la getline perchè la cin al primo spazio si ferma, per il resto non saprei. Ho aperto il file in binario come mi hai detto...
    
    #include <iostream>
    #include <fstream>
    #include <cstdlib>
    #include <iomanip>
    #include <string>
    
    using namespace std;
    
    enum stato { NO, SI };
    
    struct Ferramenta
    {
           int ID;
           string nome;
           int quantita;
           float costo;
    };
    
    void menu();
    void output (ostream& out, const Ferramenta& Fer);
    void textFile (fstream& readFromFile);
    void updateRecord (fstream& updateFile);
    void newRecord (fstream& insertInFile);
    void deleteRecord (fstream& deleteFromFile);
    
    int main ()
    {
           fstream File ("hardware.dat", ios::out | ios::in | ios::binary);
           
           if (!File)
           {
                     cerr << "File could not be opened." << endl;
                     exit(1);
           }
            
           Ferramenta Fer = { 0, "", 0, 0.0 };
                
           for (int i = 0; i < 100; i++)
              File.write( reinterpret_cast <const char*>(&Fer), sizeof(Ferramenta));
           
           cout << "Inserisci il numero di record (da 1 a 100, 0 per uscire)\n? ";
           cin >> Fer.ID;
           
           while (Fer.ID > 0 && Fer.ID <= 100)
           {
                 cout << "Inserisci nome dell'attrezzo, la quantità e il costo\n? ";
                 cin >> Fer.nome >> Fer.quantita >> Fer.costo;
                 
                 File.seekp( (Fer.ID - 1) * sizeof(Ferramenta) );
                 File.write( reinterpret_cast <const char*>(&Fer), sizeof(Ferramenta));
                 
                 cout << "Inserisci il numero di record\n? ";
                 cin >> Fer.ID;
           }    
           
           int scelta;
           menu();
           cout << "Opzione -> ";
           cin >> scelta;
           
           while (scelta != 5)
           {
                 switch(scelta)
                 {
                               case 1:
                                    textFile(File);
                                    break;
                               case 2:
                                    updateRecord(File);
                                    break;
                               case 3:
                                    newRecord(File);
                                    break;
                               case 4:
                                    deleteRecord(File);
                                    break;
                               default:
                                    cout << "Scelta sbagliata\n";
                                    break;
                 }
             File.clear();
             menu();
             cout << "Opzione -> ";
             cin >> scelta;
           }
           
           system ("pause");
           return 0;
    }
    
    void menu()
    {
         cout << "1 - Invia al file \"print.txt\" i record immessi\n"
              << "2 - Modifica un record\n"
              << "3 - Aggiungi un record\n"
              << "4 - Cancella un record\n"
              << "5 - Esci\n";
    }
    
    void output (ostream& out, const Ferramenta& Fer)
    {
         out << endl << setw(15) << setiosflags(ios::left) << Fer.ID
             << setw(25) << Fer.nome << setw(15) << Fer.quantita
             << setw(5) << Fer.costo;
    }
    
    void textFile (fstream& readFromFile)
    {
         ofstream outPrintFile("print.txt", ios::out);
         
         if (!outPrintFile)
         {
                     cerr << "File could not be opened." << endl;
                     exit(1);
         }
         
         outPrintFile << setiosflags(ios::left) << setw(15) << "Record n°"
                      << setw(25) << "Nome attrezzo" << setw(15) << "Quantita'"
                      << setw(5) << "Costo";
                      
         readFromFile.seekg(0);
         
         Ferramenta fer;
         readFromFile.read(  reinterpret_cast <char*>(&fer), sizeof(Ferramenta) );
         
         while ( !readFromFile.eof())
         {
               if (fer.ID != 0)
                  output (outPrintFile, fer);
                
         readFromFile.read(  reinterpret_cast <char*>(&fer), sizeof(Ferramenta) );
         }
    }
    
    void updateRecord (fstream& updateFile)
    {
         stato st;
         
         int record;
         cout << "Inserisci il n° di record da modificare";
         cin >> record;
         
         updateFile.seekg( (record - 1)* sizeof(Ferramenta) );
         
         Ferramenta fer;
         
         updateFile.read( reinterpret_cast <char*>(&fer), sizeof(Ferramenta) );
         
         if (fer.ID != 0)
         {
                output (cout, fer);
                cout << "\nVuoi modificare il nome (SI/NO)?";
                
                if (st == SI)
                   cout << "Inserisci il nuovo nome:";
                   cin >> fer.nome;
                   
                cout << "\nVuoi modificare la quantita (SI/NO)?";
                
                if (st == SI)
                   cout << "Inserisci la nuova quantità:";
                   cin >> fer.quantita;
                   
                cout << "\nVuoi modificare il costo (SI/NO)?";
                
                if (st == SI)
                   cout << "Inserisci in nuovo costo (float):";
                   cin >> fer.costo;
                
                output (cout, fer);
                updateFile.seekp( (record - 1) * sizeof(Ferramenta) );
                updateFile.write( reinterpret_cast<const char*>(&fer), sizeof(Ferramenta) );
         }
         
         else
            cout << "Il record n° " << record << " non ha informazioni" << endl;
    }
    
    void newRecord (fstream& insertInFile)
    {
         int record;
         cout << "Inserisci il n° di record da inserire";
         cin >> record;
         
         insertInFile.seekg( (record - 1)* sizeof(Ferramenta) );
         
         Ferramenta fer;
         
         insertInFile.read( reinterpret_cast <char*>(&fer), sizeof(Ferramenta) );
         
         if (fer.ID == 0)
         {
                  cout << "Inserisci nome dell'attrezzo, la quantità e il costo\n? ";
                  cin >> fer.nome >> fer.quantita >> fer.costo;
                  fer.ID = record;
                  
                  insertInFile.seekp( (record - 1) * sizeof(Ferramenta) );
                  insertInFile.write( reinterpret_cast<const char*>(&fer), sizeof(Ferramenta) );
         }
         else
            cout << "Il record n° " << record << " contiene informazioni" << endl;
    }
                   
    void deleteRecord (fstream& deleteFromFile)
    {
         int record;
         cout << "Inserisci il n° di record da eliminare";
         cin >> record;
         
         deleteFromFile.seekg( (record - 1)* sizeof(Ferramenta) );
         
         Ferramenta fer;
         
         deleteFromFile.read( reinterpret_cast <char*>(&fer), sizeof(Ferramenta) );
         
         if (fer.ID != 0)
         {
                    Ferramenta Fe = { 0, "", 0, 0.0 };
                    deleteFromFile.seekp( (record - 1)* sizeof(Ferramenta) );
                    deleteFromFile.write( reinterpret_cast <const char*>(&Fe), sizeof(Ferramenta) );
                    
                    cout << "Il record n° " << record << " e' stato eliminato." << endl;
         }
         else
            cout << "Il record n° " << record << " non ha informazioni" << endl;
    }
    
  • Re: Aiuto per programma sui file

    String non è un POD
    http://en.wikipedia.org/wiki/Plain_Old_Data_Structure

    non puoi fare sizeof(Ferramenta) perche contiene un string dentro.
  • Re: Aiuto per programma sui file

    Ok Skynet mettendo un char nome[30] il programma funziona, anche se ho aggiunto modifiche dopo. Ma volendolo fare usando un oggetto string come si dovrebbe impostare? Magari se mi puoi dire anche come fare un programma del genere in modo più elegante e professionale magari con le classi..spiegami un po'. Grazie sempre..
  • Re: Aiuto per programma sui file

    Crei un ostream friend per Ferramenta. Così la classe sa come leggere/scrivere se stessa da/su disco. Sono abbastanza impegnato sto periodo per farti un programma completo, se riesci a combinare tu qualcosa poi vediamo il da farsi.
  • Re: Aiuto per programma sui file

    Non vorrei aprire un altro topic. Incollo qui il codice di un programma che funziona perfettamente du DevC++ mentre con Eclipse funziona ugualmente ma non mi pulisce lo schermo come vorrei che facesse utilizzando system("CLS"). Come mai? Incollo il codice:

    //File lista.h
    
    #ifndef LISTA_H
    #define LISTA_H
    
    struct Record
    {
           int elem;
           Record *succ;
    };
    
    class Lista
    {
          private:
                   Record *testa;
          public:
                   Lista() : testa(0) {}
                   ~Lista();
                   void push (const int& el);
                   void pop();
                   bool vuota() const { return (testa == 0); }
                   void stampa() const;
    };
    
    #endif
    
    //File lista.cpp
    
    #include <iostream>
    #include "Lista.h"
    
    using namespace std;
    
    Lista :: ~Lista()
    {
          Record *temp;
          while (testa)
          {
                temp = testa;
                testa = testa->succ;
                delete temp;
          }
    }
    
    //------------------------------------------------------------------------------
    
    void Lista :: push (const int& el) 
    {
          if(vuota())
          {
              Record *re = new Record;
              re->elem = el;
              re->succ = testa;
              testa = re;
          }
          else
          {
              Record *p = testa;
              Record *re = new Record;
              re->elem = el;
              
              if(!p->succ)
              {
                          if(p->elem > el)
                          {
                             re->succ = testa;
                             testa = re;      
                          }
                          else
                          {
                             re->succ = p->succ;
                             p->succ = re;
                          }
              }
              else
              {
                          if(p->elem > el)
                          {
                             re->succ = testa;
                             testa = re;
                          }
                          else
                          {
                              while ((p->succ) && (p->succ->elem < el))
                              {
                                 p = p->succ;
                              }
                          re->succ = p->succ;
                          p->succ = re;
                          }
              }      
          }
    }
    
    //------------------------------------------------------------------------------
    
    void Lista :: pop()
    {
         if (vuota())
            cout << "Pop non possibile. Lista vuota!\n";
         else
         {
             Record *temp = testa;
             testa = testa->succ;
             delete temp;
         }
    }
    
    //------------------------------------------------------------------------------
    
    void Lista :: stampa() const
    {
         if (vuota())
            cout << "Lista vuota\n";
         else
         {
             Record *temp = testa;
             while (temp)
             {
                   cout << temp->elem << " ";
                   temp = temp->succ;
             }
         }
    }
    
    //File main.cpp
    
    #include <cstdlib>
    #include <iostream>
    #include "Lista.h"
    
    using namespace std;
    
    void menu();
    
    int main ()
    {
          Lista l;
          int num, scelta;
          
          menu();
          cin >> scelta;
          
          while(scelta != 4)
          {
              switch(scelta)
              {
                 case 1:
                        cout << "Inserisci un intero: ";
                        cin >> num;
                        l.push(num);
                        break;
                 case 2:
                        cout << "Cancella elemento in testa..\n";
                        l.pop();
                        break;
                 case 3:
                        l.stampa();
                        break;
                 default:
                        cout << "Scelta errata\n";
              
              }
          system("pause");
          system("CLS");
          menu();
          cin >> scelta;
          }
          
          system ("pause");
          return 0;
    }
    
    void menu()
    {
         cout << "      Menu di selezione" << endl
              << "1 - Push" << endl
              << "2 - Pop" << endl
              << "3 - Stampa" << endl
              << "4 - Esci" << endl
              << "      Opzione -> ";
    }
    
  • Re: Aiuto per programma sui file

    Perche chiami le funzioni del OS?
    non ti basta una cosa del genere?
    
    cout << string(25,'\n');
    
  • Re: Aiuto per programma sui file

    Questo che hai scritto cosa significa? e soprattutto al posto di cosa devo metterlo nel programma di cui sopra? Io voglio che il menu non venga scritto in output centinaia di volte successivamente, ma per esempio se inserisco un intero mi esce la scritta press any key to continue io premo il tasto e mi pulisce lo schermo generando il menu senza riscriverlo. Questo succede usandlo il dev mentre con eclipse utilizzando la console e non la schermata nera del dos per intenderci, non succede. Mettendo quello che mi hai suggerito va 25 volte a capo..ma non è quello che voglio fare.
  • Re: Aiuto per programma sui file

    Andare 25 volte a capo per me significa pulire lo schermo, se non basta 25 metti 100 ma almeno non devi fare affidamento a delle chiamate del OS che non è detto che esistano. Per ovviare il system("pause") basterebbe pulire il cin con
    
    std::cin.ignore(std::numeric_limits<streamsize>::max(),'\n');
    
    Poi puoi mettere il tuo messaggio
    
    cout << "premi un tasto per continuare...."
    
    e poi basta un cin.get() per riprendere il programma.

    Per approfondire fatti una lettura quì
Devi accedere o registrarti per scrivere nel forum
9 risposte