Daten in Binärdatei schreiben...

wedhead

Mitglied
Hi @ all !

Benutze den Borland C++ Builder 6...
Ich bin dabei ein Consolenprogramm zu schreiben das wie eine Bank aufgebaut sein soll...

Dazu will ich die verschiedenen Daten wie kontonummer, inhaber, pin, kontostand usw in eine binärdatei "konten.dat" abspeichern um sie später wieder auslesen zu können.

Ich denke das es mit fstream/iostream funktionieren müsste, habe aber keine ahnung wie ich das angehen soll.

Hoffe ihr könnt mir weiterhelfen.

greez

Weedy



Quelltext:

Code:
#include <vcl.h>
#pragma hdrstop
#include <conio.h>
#include <iostream.h>
#pragma argsused
//---------------------------------------------------------------------------

//Klassendefinition
class standartk
{
  double kontostand;
  int kontonummer;
  int bankleizahl;
  char* inhaber;
  int pin;

  public:

//Konstruktoren
standartk (double startwert, int ktn, int blz, char* name, int code)
  {
    kontostand=startwert;
    kontonummer=ktn;
    bankleizahl=blz;
    inhaber=name;
    pin=code;
}


standartk ()
{
}


//Destruktor
~standartk()
{
cout<<endl<<"Kontostand = "<<kontostand<<endl;
}


//Ausgabe Kontostand
  int aus()
  {
    return kontostand;
  }

//Ausgabe Kontonummer
  int ktnummer()
  {
    return kontonummer;
  }


//Ausgabe Kontoinhaber
  char* aktinhaber()
  {
   return inhaber;
  }


//Ausgabe Pin
  int apin()
  {
  return pin;
  }


//Ausgabe BLZ
    int blzahl()
  {
    return bankleizahl;
  }


//Prozedur zum einzahlen
    int einzahlen (int ebetrag)
  {
    if (ebetrag<0)
    {
    ebetrag=0;
    cout<<"Keine negative Einzahlung möglich"<<endl;
    }
    else kontostand=kontostand+ebetrag;
   return kontostand;
  }


//Prozedur zum abheben
  int auszahlen (int abetrag)
  {
    if (abetrag<0)
    {
    abetrag=0;
    cout<<"Keine negative Auszahlung möglich"<<endl;
    }
    else if ((kontostand-abetrag)<-1000)
    {
      abetrag=(kontostand+1000);
      cout<<"Nur 1000€ Dispo"<<endl;
    }
    kontostand=(kontostand-abetrag);
  return kontostand;
  }


//Prozedur zum Pin ändern
  int paendern (int npin)
  {
  int npin1;
  int npin2;
    if (npin==pin)
    {
    cout<<endl<<"Bitte gewuenschten Pin eingeben: ";cin>>npin1;
    cout<<"Bitte gewuenschten Pin wiederholen: ";cin>>npin2;cout<<endl;
    if (npin1==npin2)
        {
        pin=npin1;
        }
    else cout<<endl<<"Pins stimmen nicht überein!"<<endl<<endl;
    }
    else cout<<endl<<"Pin-Code nicht korrekt"<<endl<<endl;
   return pin;
  }


//Prozedur zum Namen ändern
  char* naendern (char* id)
  {
  inhaber=id;
  return inhaber;
  }


};


//Anfangswerte für Konstruktor
standartk S1(500, 130049638, 54051990, "Jens", 1234);

//Hilfsvariablen
int ez;
int az;
int p;
char taste;
char* n;

//hauptprogramm
int main(int argc, char* argv[])
{
//Sprungmarke 1
loop1:

//Hauptmenü
 do
  {
    cout<<endl;
    cout<<"###############################"<<endl;
    cout<<"#                             #"<<endl;
    cout<<"#      Weedys Bank v1.3.6     #"<<endl;
    cout<<"#                             #"<<endl;
    cout<<"###############################"<<endl;
    cout<<"#                             #"<<endl;
    cout<<"# Kontostand anzeigen ----> K #"<<endl;
    cout<<"# Kontodaten anzeigen ----> D #"<<endl;
    cout<<"# Auf Konto Einzahlen ----> E #"<<endl;
    cout<<"# Von Konto Abheben ------> A #"<<endl;
    cout<<"# Kontodaten aendern -----> C #"<<endl;
    cout<<"# Beenden ----------------> B #"<<endl;
    cout<<"#                             #"<<endl;
    cout<<"###############################"<<endl<<endl;
    cout<<endl<<"Was moechten Sie? ";cin>>taste;

    switch (taste)
    {

    case 'k':case 'K': cout<<"Bitte geben Sie ihren Pin ein: ";cin>>p;clrscr();if (p==S1.apin()){cout<<endl<<"Ihr Kontostand belaeuft sich auf: "<<S1.aus()<<" eur"<<endl<<endl<<endl;} else {cout<<"Pin-Code nicht korrekt!"<<endl<<endl;}break;
    case 'd':case 'D': cout<<"Bitte geben Sie ihren Pin ein: ";cin>>p;clrscr();if (p==S1.apin()){cout<<endl<<"Kontonummer: "<<S1.ktnummer()<<endl<<"Bankleizahl: "<<S1.blzahl()<<endl<<"Kontoinhaber: "<<S1.aktinhaber()<<endl<<"Pin: "<<S1.apin()<<endl<<endl<<endl;} else {cout<<"Pin-Code nicht korrekt!"<<endl<<endl;} break;
    case 'e':case 'E': cout<<endl<<"Wieviel moechten Sie einzahlen? ";cin>>ez;ez=S1.einzahlen(ez);break;
    case 'a':case 'A': cout<<"Bitte geben Sie ihren Pin ein: ";cin>>p;cout<<endl;if (p==S1.apin()){cout<<endl<<"Wieviel moechten Sie abheben? ";cin>>az;clrscr();S1.auszahlen(az);} else {cout<<"Pin-Code nicht korrekt!"<<endl<<endl;}break;
    case 'c':case 'C': cout<<"Bitte geben Sie ihren Pin ein: ";cin>>p;cout<<endl;if (p==S1.apin()){clrscr();do
  {
//Untermenü 1
    cout<<endl;
    cout<<"###############################"<<endl;
    cout<<"#                             #"<<endl;
    cout<<"#      Weedys Bank v1.3.6     #"<<endl;
    cout<<"#                             #"<<endl;
    cout<<"###############################"<<endl;
    cout<<"#     Kontodaten aendern:     #"<<endl;
    cout<<"###############################"<<endl;
    cout<<"#                             #"<<endl;
    cout<<"# Kontodaten anzeigen ----> D #"<<endl;
    cout<<"# Pin-Code aendern -------> P #"<<endl;
    cout<<"# Namen aendern ----------> N #"<<endl;
    cout<<"# Zurueck zum Hauptmenue--> Z #"<<endl;
    cout<<"# Beenden ----------------> B #"<<endl;
    cout<<"#                             #"<<endl;
    cout<<"###############################"<<endl<<endl;
    cout<<endl<<"Was moechten Sie? ";cin>>taste;

    switch (taste)
    {
    case 'd':case 'D': clrscr();cout<<endl<<"Kontonummer: "<<S1.ktnummer()<<endl<<"Bankleizahl: "<<S1.blzahl()<<endl<<"Kontoinhaber: "<<S1.aktinhaber()<<endl<<"Pin: "<<S1.apin()<<endl<<endl<<endl;break;
    case 'p':case 'P': clrscr();cout<<endl<<"Bitte aktuellen Pin eingeben: ";cin>>p;S1.paendern(p);break;
    case 'n':case 'N': clrscr();cout<<endl<<"Bitte neuen Namen eingeben: ";cin>>n;S1.naendern(n);break;
    case 'z':case 'Z': clrscr();goto loop1;
    }
  }
//Abbruchbedingung Untermenü1
  while (taste !='B' && taste !='b'); } else {cout<<"Pin-Code nicht korrekt!"<<endl<<endl;}
    }
  }
//Abbruchbedingung Hauptmenü
  while (taste !='B' && taste !='b');
        getch();
}
 
Zuletzt bearbeitet:
Hallo,

in welcher Datenstruktur speicherst du eigentlich deine Konten?
hab in deinem Code nix darüber gefunden.. (hab ich's übersehn?)

Aber hier mal nen Codeschnipsel mit dem bestimmt was anfangen kannst:
Ist zwar nen Beispiel von mir aber kannst du bestimmt anpassen.
ich speicher nur nen Name und das alter...
Code:
Person person("Jan", 23);  // ist mein Objekt vom Typ Person
zu speichern...
Code:
fstream f("test.dat", ios::out | ios::binary);
if(f.good())
{
     f.write((char*)&person, sizeof(person));
}
f.close();
zu laden...
Code:
Person person4;  //variable anlegen
fstream f4("test.dat", ios::binary | ios::in);   
if(f4.good())
{
     while(f4.eof() != true) // falls man mehrere Objekte in der Datei hat, würde sie bei dir gleich in einer STL Liste speichern
     {
          f4.read((char*)&person4, sizeof(person4));  // Objekt aus Datei der Variable zuweisen
          cout << person4.getName() << endl;  // Objektinhalt ausgeben
          cout << person4.getInt() << endl;
     }
}
f4.close();
Ich würde beides in eine extra Funktion packen und dann immer aufrufen wenns in die Datei soll.

MfG Turri
 
binäre Dateien werden mit Zeichen gespeichert die teilweise nicht darstellbar sind.

klappts denn mit dem Laden aus der Datei?

MfG Turri
 
soweit bin ich noch nicht, dazu sind mir von gestern noch die daten verloren gegangen von meinem progg, ich hab mich jetzt nochma dran gemacht und werde gleich nochma mit der ein/ausgabe versuchen...
 
Hi.

Warum wollt ihr denn das unbedingt als Binärdatei speichern?

Seid ihr euch im Klaren das das mit Zeigern in den Strukturen nicht klappen kann?! Die Werte der Zeiger in der Struktur werden zwar gespeichert, haben allerdings keinen vernünftigen Wert mehr nachdem das Programm neu gestartet und die Datei geladen wird.

Außerdem ist das Speichern von Daten in einer Binärdatei im einfachsten Falle nicht portabel. Du kannst keine Veränderungen an der Struktur vornehmen ohne das die Binärdatei ungültig wird. Hinzu kommt das bei unterschiedlichen Compilern und Compileroptionen die Strukturen unterschiedlichen Größen haben können - was dazu führt, das die Datei nicht lesbar ist.

Warum speichert ihr nicht einfach alles in einer Textdatei? Man kann sich ja einfach ein Format ausdenken was erweiterbar ist und hat noch den Vorteil, man kann es auch mit einem normalen Editor betrachten und editieren.

Z.B.
Code:
[Person]
name = Schulz
vorname = Klaus
alter = 18

[Person]
name = Müller
vorname = Hans
alter = 33
In den eckigen Klammern steht meinetwegen der Klassenname, so das man auch weiß welche Klasse(Struktur) man nun erzeugen muß beim Einlesen. Danach folgen Schlüssel/Werte-Paare die nur noch in die entsprechenden Eigenschaften des Objektes einzutragen sind.
 
Würde mir auf die art natürlich auch gefallen, wobei ich sagen muss so wie ich den Code Oben angepasst habe funktioniert es einwandfrei:
Code:
  void save(standartk *z)
        {
        fstream f("test.dat", ios::out);
        if(f.good())
        {
        f.write((char*) z, sizeof(standartk));
        }
        f.close();
        cout<<"Schreibvorgang erfolgreich"<<endl;
        }

  void load(standartk *z)
        {
        fstream f("test.dat", ios::in);
        if(f.good())
        {
        f.read((char*) z, sizeof(standartk));
        }
        f.close();
        cout<<"Lesevorgang erfolgreich"<<endl;
        }
Bei deinem vorschlag trau ich mir nicht zu das ich das umsetzen kann, ich hab wenig ahnung von fstream und dem ganzen zeug musst du wissen.


greez

weedy
 
Zuletzt bearbeitet:
wedhead hat gesagt.:
so wie ich den Code Oben angepasst habe funktioniert es einwandfrei:
Das wage ich zu bezweifeln. Hast du schonmal probiert deine Datei einzulesen und die entsprechenden Elemente deiner Klasse auszugeben nachdem du das Programm neu gestartet hast?!

Wenn du den Namen des Inhabers ausgeben willst wird dein Programm höchstwahrscheinlich abstürzen (oder zumindest irgend einen Müll ausgeben), denn der Name des Inhabers wurde gar nicht gespeichert - nur ein Verweis darauf. (es könnte höchstens funktionieren wenn der Name fest im Programm gespeichert ist, aber das ist ja nur ein Spezialfall)

wedhead hat gesagt.:
Bei deinem vorschlag trau ich mir nicht zu das ich das umsetzen kann, ich hab wenig ahnung von fstream und dem ganzen zeug musst du wissen.
Aber du weißt doch auch wie man mit cout etwas ausgibt. Das ist doch genau das gleiche. Nur das du den fstream vorher mit einer Datei verbindest.

Du mußt es ja nicht unbedingt so machen wie ich das vorgeschlagen habe. Es reicht ja auch erstmal so:
Code:
void save (fstream& datei, const standardk& z) {
  // damit man nachher weiß wo ein Konto anfängt:
  datei << "[standartk]" << endl;

  datei << z.inhaber << endl;
  datei << z.startwert << endl;
  datei << z.kontonummer << endl;
  datei << z.bankleitzahl << endl;
  datei << z.pin << endl << endl;
}

Das Einlesen geht dann so:
Code:
// ein StandardKonto von der Datei datei lesen:
bool load (fstream& datei, standardk& z) {
  string str;

  while (getline (datei, str)) {
    if (str == "[standardk]")
      getline (datei, str);
      
      // für den Namen muß man Speicher
      // allozieren. Nachher wieder freigeben!
      z.inhaber = new char[str.length()+1]

      str.copy (z.inhaber, str.length ());

      datei >> z.startwert;
      datei >> z.kontonummer;
      datei >> z.bankleitzahl;
      datei >> z.pin;

      return datei;
    }
  }
}
So sollte das eigentlich funktionieren. Du mußt nur dran denken den Speicher für den Inhaber wieder mit
Code:
delete[] z.inhaber
freizugeben. Da solltest du dir überlegen ob es nicht besser wäre statt char* einen std::string zu nehmen.
 
Zurück