TSaveDialog Autosave-Funktion
-
warum willst du an den Button ran? speicher doch einfach so
die Speichernfunktion nimmt dir der Button auch nicht ab, die mußt du trotzdem selbst programmieren, denn der SaveDialog gibt dir nur den Dateinamen
also wo ist das Speichern?noch als Tip: für TMemo/TStringList u.ä. gibts die Methode SaveToFile
-
ja das hab ich schon gemacht. Habe ja bereits einen Speicherbutton, der ein SaveDialog öffnet. Dort steht auch schon jede Menge Code drin was alles gespeichert werden soll. Aber es macht ja eigentlich keinen Sinn, das ganze nochmal zu schreiben. Ich müsste im Prinzip einfach wieder diesen Code ausführen, den es ja schon gibt.
void __fastcall TF_HO::DatensatzSichernExecute(TObject *Sender) { //Speichern der Datensatzkommentare und Messdaten in txt-Datei: ofstream saveFile; this->HO_SaveDialog->FileName = F_Set->Set_Save_LE_Dateiname->Text; if (HO_SaveDialog->Execute()) { saveFile.open(HO_SaveDialog->FileName.c_str(), ios::out); saveFile << "Bezeichnung: " << HO_Datensatzkommentare_LE_Bezeichnung->Text.c_str() << endl; saveFile << "Bearbeiter : " << HO_Datensatzkommentare_LE_Bearbeiter->Text.c_str() << endl; saveFile << "Kommentar : " << HO_Datensatzkommentare_LE_Kommentar->Text.c_str() << endl; saveFile << "Probe : " << HO_Datensatzkommentare_LE_Probe->Text.c_str() << endl; saveFile << "Erstellt am: " << DateTimeToStr(Now()).c_str() << endl << endl; saveFile << "x:\t" << "Datum: " << "Zeit:\t" << endl << endl; int xLenght = HO_Messeinstellungen_LE_Messreihen->GetLength(); for (unsigned int i=0; i<batch.size(); i++) { saveFile << setw(xLenght) << i << "\t" << batch[i].Get_date().DateString().c_str() << " " << batch[i].Get_time().TimeString().c_str() << endl; } saveFile.close(); } F_HO->Caption = "BIOG-MSR 1.0 - " + HO_SaveDialog->FileName; }
-
Dann lager den Schreib-Code in eine eigene Funktion aus, die Du dann einfach entsprechend aufrufen kannst.
-
Joe_M. schrieb:
Dann lager den Schreib-Code in eine eigene Funktion aus, die Du dann einfach entsprechend aufrufen kannst.
die Idee hat ich auch schon. Ich dachte nur, das der Code dann noch unübersichtlicher wird. Ausserdem bekam ich damit Probleme, da er ja die Komponenten wie HO_SaveDialog bei der Definition der Funktion noch nicht kennt.
void DatenSpeichern() { ofstream saveFile; saveFile.open(HO_SaveDialog->FileName.c_str(), ios::out); saveFile << "Bezeichnung: " << HO_Datensatzkommentare_LE_Bezeichnung->Text.c_str() << endl; saveFile << "Bearbeiter : " << HO_Datensatzkommentare_LE_Bearbeiter->Text.c_str() << endl; saveFile << "Kommentar : " << HO_Datensatzkommentare_LE_Kommentar->Text.c_str() << endl; saveFile << "Probe : " << HO_Datensatzkommentare_LE_Probe->Text.c_str() << endl; saveFile << "Erstellt am: " << DateTimeToStr(Now()).c_str() << endl << endl; saveFile << "x:\t" << "Datum: " << "Zeit:\t" << endl << endl; int xLenght = HO_Messeinstellungen_LE_Messreihen->GetLength(); for (unsigned int i=0; i<batch.size(); i++) { saveFile << setw(xLenght) << i << "\t" << batch[i].Get_date().DateString().c_str() << " " << batch[i].Get_time().TimeString().c_str() << endl; } saveFile.close(); }
Sonst hätt ich eine Klasse geschrieben mit Methoden wie Dateien speichern, öffnen. Nur ist das halt doch ne sehr spezielle Klasse, die eigentlich dann nur mit diesem Programm funktioniert. Das ist ja nicht gerade objektorientiert. Ausserdem hätt ich da ja auch wieder das Problem, dass die Komponenten die ich anspreche noch gar nicht existieren.
-
Dann übergib doch einfach den Dateinamen als Parameter...
-
Etwa so + ein paar Vereinfachungen
void DatenSpeichern(const AnsiString& filename) { ofstream saveFile(filename.c_str()); // open ist nicht nötig // evtl. kann man noch einen Test ausführen, ob die Datei zum Schreiben geöffnet werden konnte. if( !saveFile.is_open()) return; // hier besser bool Rückgabetyp und false zurückgeben // hier dein Code // close wird bei Verlassen des Scopes sowieso ausgeführt und kann somit weggelassen werden }
-
Das gleiche Problem tritt dann auch mit den anderen Komponenten auf, die in der Funktion auftreten. Es kommen später auch noch mehr dazu. Ich kann doch nicht alle mit als Parameter aufnehmen oder?
bool DatenSpeichern(const AnsiString& filename) { ofstream saveFile(filename.c_str()); if( !saveFile.is_open()) { saveFile << "Bezeichnung: " << HO_Datensatzkommentare_LE_Bezeichnung->Text.c_str() << endl; saveFile << "Bearbeiter : " << HO_Datensatzkommentare_LE_Bearbeiter->Text.c_str() << endl; saveFile << "Kommentar : " << HO_Datensatzkommentare_LE_Kommentar->Text.c_str() << endl; saveFile << "Probe : " << HO_Datensatzkommentare_LE_Probe->Text.c_str() << endl; saveFile << "Erstellt am: " << DateTimeToStr(Now()).c_str() << endl << endl; saveFile << "x:\t" << "Datum: " << "Zeit:\t" << endl << endl; int xLenght = HO_Messeinstellungen_LE_Messreihen->GetLength(); for (unsigned int i=0; i<batch.size(); i++) { saveFile << setw(xLenght) << i << "\t" << batch[i].Get_date().DateString().c_str() << " " << batch[i].Get_time().TimeString().c_str() << endl; } return 0; } }
Aufruf:
void __fastcall TF_HO::DatensatzSichernExecute(TObject *Sender) { //Speichern der Datensatzkommentare und Messdaten in txt-Datei: this->HO_SaveDialog->FileName = F_Set->Set_Save_LE_Dateiname->Text; //übernimmt Standarddateinamen aus den Einstellungen if (HO_SaveDialog->Execute()) { DatenSpeichern(HO_SaveDialog->FileName); } F_HO->Caption = "BIOG-MSR 1.0 - " + HO_SaveDialog->FileName; }
Hab als Rückgabetyp jetzt bool genommen. Falls return 0 ausgeführt wird, bricht dann das Programm infach ab? Sonst könnte man ja auch ein Meldungsfenster ausgeben, dass auf den Fehler aufmerksam macht.
-
rudpower schrieb:
Hab als Rückgabetyp jetzt bool genommen. Falls return 0 ausgeführt wird, bricht dann das Programm infach ab? Sonst könnte man ja auch ein Meldungsfenster ausgeben, dass auf den Fehler aufmerksam macht.
hast du deinen Quellcode denn mal ausprobiert? ich glaube nicht dass da überhaupt was gespeichert wird, da du Braunsteins Hinweise nicht wirklich befolgt hast, hier nochmal mit dem Rückgabetyp:
bool DatenSpeichern(const AnsiString& filename) { ofstream saveFile(filename.c_str()); // open ist nicht nötig // evtl. kann man noch einen Test ausführen, ob die Datei zum Schreiben geöffnet werden konnte. if( !saveFile.is_open()) return false; // hier bool Rückgabetyp und false zurückgeben // hier dein Code ---> hier kommt erst dein anderer Quellcode zum Speichern // close wird bei Verlassen des Scopes sowieso ausgeführt und kann somit weggelassen werden }
und zur Verwendung des Rückgabewertes:
void __fastcall TF_HO::DatensatzSichernExecute(TObject *Sender) { //Speichern der Datensatzkommentare und Messdaten in txt-Datei: this->HO_SaveDialog->FileName = F_Set->Set_Save_LE_Dateiname->Text; //übernimmt Standarddateinamen aus den Einstellungen if (HO_SaveDialog->Execute()) { if (!DatenSpeichern(HO_SaveDialog->FileName)) ShowMessage("Klappt nicht"); } F_HO->Caption = "BIOG-MSR 1.0 - " + HO_SaveDialog->FileName; }
rudpower schrieb:
Das gleiche Problem tritt dann auch mit den anderen Komponenten auf, die in der Funktion auftreten. Es kommen später auch noch mehr dazu. Ich kann doch nicht alle mit als Parameter aufnehmen oder?
du kannst alles was du möchtest aufnehmen oder besser: alles was notwendig ist
-
hab hier irgendwo noch einen Fehler drin, kann ihn aber nicht finden. Hab das mal so umgesetzt.
Funktionsdefinition:
bool DatenSpeichern(const AnsiString& filename, const AnsiString& bezeichnung, const AnsiString& bearbeiter, const AnsiString& kommentar, const AnsiString& probe, int xLenght) { ofstream saveFile(filename.c_str()); if(!saveFile.is_open()) { return false; } saveFile << "Bezeichnung: " << bezeichnung.c_str() << endl; saveFile << "Bearbeiter : " << bearbeiter.c_str() << endl; saveFile << "Kommentar : " << kommentar.c_str() << endl; saveFile << "Probe : " << probe.c_str() << endl; saveFile << "Erstellt am: " << DateTimeToStr(Now()).c_str() << endl << endl; saveFile << "x:\t" << "Datum: " << "Zeit:\t" << endl << endl; for (unsigned int i=0; i<batch.size(); i++) { saveFile << setw(xLenght) << i << "\t" << batch[i].Get_date().DateString().c_str() << " " << batch[i].Get_time().TimeString().c_str() << endl; } }
Aufruf der Funktion:
void __fastcall TF_HO::DatensatzSichernExecute(TObject *Sender) { //Speichern der Datensatzkommentare und Messdaten in txt-Datei: this->HO_SaveDialog->FileName = F_Set->Set_Save_LE_Dateiname->Text; if (HO_SaveDialog->Execute()) { int xLenght = HO_Messeinstellungen_LE_Messreihen->GetLength(); if (!DatenSpeichern(HO_SaveDialog->FileName, HO_Datensatzkommentare_LE_Bezeichnung, HO_Datensatzkommentare_LE_Bearbeiter, HO_Datensatzkommentare_LE_Kommentar, HO_Datensatzkommentare_LE_Probe, xLenght)) { ShowMessage("Klappt nicht"); } } F_HO->Caption = "BIOG-MSR 1.0 - " + HO_SaveDialog->FileName; }
als Fehlermeldung bekomm ich:
[C++ Warnung] Start.cpp(112): W8070 Funktion sollte einen Wert zurückgeben.
-
bool DatenSpeichern(const AnsiString& filename, // ... if(!saveFile.is_open()) { return false; } // ... }
Und wo ist das return true im Erfolgsfall?
-
oh ja klar, das sollte ich setzen
Sehr komisch, den Fehler erhalt ich immer noch:bool DatenSpeichern(const AnsiString& filename, AnsiString bezeichnung, /*...*/) { ofstream saveFile(filename.c_str()); if(!saveFile.is_open()) return false; else if(saveFile.is_open()) { saveFile << "Bezeichnung: " << bezeichnung.c_str() << endl; //... return true; } }
-
hat sich erledigt. Hab den Fehler gefunden
Vielen Dank. Es funktioniert schon mal. Die Kompilierung geht durch. Bekomm nur die Warnung
[C++ Warnung] Start.cpp(111): W8070 Funktion sollte einen Wert zurückgeben.
WO der Fehler dort liegen soll weiss ich nicht. (Siehe Code vorheriger Beitrag)
Eine Frage noch: wann sollte das speichern denn schiefgehen. ich kann mir ausser, dass kein speicher mehr da ist keine situation vorstellen.
-
Der Compiler erkennt so Deine return-Anweisung nicht, da diese in eigenen Scopes liegen.
bool DatenSpeichern(const AnsiString& filename, AnsiString bezeichnung, /*...*/) { ofstream saveFile(filename.c_str()); if(!saveFile.is_open()) return false; else if(saveFile.is_open()) { saveFile << "Bezeichnung: " << bezeichnung.c_str() << endl; //... } return true; }
-
Das liegt an deinem else if. Das ist hier völlig sinnfrei. Wenn die Datei nicht geöffnet werden konnte machst du return false. Danach muss die datei ja offen sein. Also:
bool DatenSpeichern(const AnsiString& filename, AnsiString bezeichnung, /*...*/) { ofstream saveFile(filename.c_str()); if(!saveFile.is_open()) return false; saveFile << "Bezeichnung: " << bezeichnung.c_str() << endl; //... return true; }
-
alles klar. Es funktioniert! Vielen Dank für die Hilfe und Ratschläge.
wie kann ich ein Speicherfehler simulieren?