Aus mehreren Editfeldern in Datei speichern

Guten Tag!

Ich habe folgendes Problem, dass ich so etwas wie einen Stundenplan in MFC (C++ 6.0) programmieren will und als Stundeneingabe je Tag 6 Editfelder habe, also insgesamt 30 Editfelder (Montag bis Freitag). Nun möchte ich aber diese Editfeldeingaben möglichst geordnet in eine Datei (.txt) speichern, so dass ich diese auch wieder korrekt einlesen kann. Bitte helft mir, ich stehe momentan komplett auf den Schlauch und diese Speichern/Laden Sache habe ich vorher auch noch nie ausprobiert.
Ich bin über jegliche Hilfe sehr dankbar und Beispielquellcode wäre wirklich klasse!

Vielen Dank im vorraus!
Toni

Guten Tag!

Ich habe folgendes Problem, dass ich so etwas wie einen
Stundenplan in MFC (C++ 6.0) programmieren will und als
Stundeneingabe je Tag 6 Editfelder habe, also insgesamt 30
Editfelder (Montag bis Freitag). Nun möchte ich aber diese
Editfeldeingaben möglichst geordnet in eine Datei (.txt)
speichern, so dass ich diese auch wieder korrekt einlesen
kann. Bitte helft mir, ich stehe momentan komplett auf den
Schlauch und diese Speichern/Laden Sache habe ich vorher auch
noch nie ausprobiert.
Ich bin über jegliche Hilfe sehr dankbar und Beispielquellcode
wäre wirklich klasse!

Hier der bisherige Ansatz meines Speichern Dialogs, der auch funktioniert nur ohne Speicherung der Editfeldeingaben:

void CStundenplanDlg::open\_mouth:nBTNSpeichern() 
{
 // TODO: Code für die Behandlungsroutine der Steuerelement-Benachrichtigung hier einfügen
 // Dialog zum Speichern einer Datei
 CFileDialog fileDlg(FALSE, ".txt", NULL, 0, "Textfile (\*.txt)|\*.txt|All Files (\*.\*)|\*.\*||");
 
 fileDlg.DoModal();
 
 CString pfad = fileDlg.GetPathName ();
 
 CFile datei;
 
 // Dies ist der String der gepeichert wird
 CString speicherString = "ABC";
 
 // Variable fuer die Dateilaenge erzeugen
 long int dateilaenge = speicherString.GetLength ();
 
 // Oeffnen der Datei zum Schreiben
 datei.Open (fileDlg.GetPathName(), CFile::modeCreate | CFile::modeWrite);
 
 // Inhalt des Strings in Datei schreiben
 datei.Write (speicherString, dateilaenge);
 
 // Schliessen der Datei
 datei.Close ();
}

Vielen Dank im vorraus!
Toni

Weiß denn hier keiner wie das evtl umzusetzen wäre?
Hab schon in 1000den Foren gesucht aber nichts gefunden bzw. vllt auch durch die Flut von Informationen überlesen.

Hallo!

Weiß denn hier keiner wie das evtl umzusetzen wäre?

Was ist denn eigentlich dein Problem, das Lesen/Schreiben aus/in Dateien oder das Herankommen an die Inhalte in den Editcontrols, oder beides?

Jan

1 Like

Das Schreiben in eine Datei funktioniert ja mit dem angegebenen Quellcode nur weiß ich nich so recht wie ich die Daten der einzelnen Editfelder strukturiert in eine solche Datei schreiben kann. Also weiß ich nicht so recht wie ich die eingegebenen Daten der Editfelder in eine Datei speichern kann, wie ich daran komme, wie du sagst. Wenn ich das erstmal hätte, dürfte der Rest ja kein Problem mehr sein, hoffe ich.

Danke schonmal!

Hallo!

Datei schreiben kann. Also weiß ich nicht so recht wie ich die
eingegebenen Daten der Editfelder in eine Datei speichern
kann, wie ich daran komme, wie du sagst. Wenn ich das erstmal
hätte, dürfte der Rest ja kein Problem mehr sein, hoffe ich.

Ok, es gibt 2 grundsätzliche Methoden, wobei man man sich bei beiden mehr oder weniger geschickt anstellen kann.

Die Hauruck-Methode: Du greifst unmittelbar auf die Controls zu. Jedes Control hat ja seine eigene ID, z.B. IDC_EDIT1. Mit GetDlgItem(IDC_EDIT1)->Get/SetWindowText(…) setzt du den Text im Editfeld bzw. liest ihn aus. Dafür gibt es sogar „Bequemlichkeits“-Funktionen, die da heißen GetDlgItemText() und SetDlgItemText().

Die politisch korrekte MFC-Methode: Für jedes Edit-Control eine Member-Variable erzeugen, also z.B. für das Control IDC_EDIT1 die CString-Member-Variable m_edit1. Das geht über den Klassenassistenten.
Dort wo man den Dialog initialisiert, meist in der Funktion OnInitDialog(), werden die Member-Variablen mit den Werten belegt, die dann im Edit-Control erscheinen sollen. Danach UpdateData(FALSE); nicht vergessen, denn damit erst werden die Variableninhalte in die Controls geschoben.
Auslesen der Controls: Bei dir müsste gleich am Anfang in der Funktion OnBTNSpeichern() stehen UpdateData(TRUE), um die Inhalte der Controls in die Membervariablen zu verschieben. Danach kannst du auf m_edit1 zugreifen, wie du es jetzt mit speicherString machst.

Bzgl. des Datei-Lesens und -Schreibens könntest Du dir vielleicht noch die Klasse CStdioFile angucken, die für Textdateien besser geeignet ist als CFile.

Jan

Danke erstmal für die Hilfe! Ich habe es allerdings dann noch anders gemacht. Allerdings habe ich jetzt ein Problem mit dem Speichern.

void CStundenplanDlg::open\_mouth:nBTNSpeichern() 
{
 // TODO: Code für die Behandlungsroutine der Steuerelement-Benachrichtigung hier einfügen
 UpdateData(TRUE);

 // Dialog zum Speichern einer Datei

 FILE \*fStundenplan;
 if( (fStundenplan=fopen("Stundenplan.txt","w")) == NULL) 
 {
 MessageBox("Speichern nicht erfolgreich!","Fehler",MB\_OK);

 }
 else
 {
 CString speicherString = "";

 for(int i=IDC\_ED\_ST\_1; iGetWindowText(m\_cs\_Stunde); //und übergibt die jeweiligen Werte an die Membervariable m\_cs\_Stunde 
 speicherString += m\_cs\_Stunde + "#"; //Die übergebenen Werte werden in einem String, getrennt durch eine # gespeichert
 }

 for(int r=IDC\_ED\_R\_1; rGetWindowText(m\_cs\_Raum);
 speicherString += m\_cs\_Raum + "#";
 }


 for(int d=IDC\_ED\_DOZ\_1; dGetWindowText(m\_cs\_Dozent);
 speicherString += m\_cs\_Dozent + "#" + "\n";
 }

 fputs(speicherString, fStundenplan);
 fclose(fStundenplan);
 }
}

soweit funktioniert das auch alles ganz toll und es wird auch alles gespeichert.
Nur kurz noch zum Verständnis:
Jede Stunde hat noch einen Raum und einen Dozenten als Angabe in einem jeweiligen extra Editfeld zur eingabe.

So nun mein Problem:
Wenn ich speichere sieht das ganze dummerweiße im *.txt so aus

Stunde1#Stunde2#Stunde3#Stunde4#Stunde5#Stunde6#Raum1#Dozent1#########Raum2#Dozent2#########Raum3#Dozent3#########Raum4#Dozent4#########Raum5#Dozent5#########Raum6#Dozent1#
#
#
#
#
#
#
#
#
Raum2#
Dozent2#
#
#
#
#
#
#
#
#
Raum3#
Dozent3#
#
#
#
#
#
#
#
#
Raum4#
Dozent4#
#
#
#
#
#
#
#
#
Raum5#
Dozent5#
#
#
#
#
#
#
#
#
Raum6#
Dozent6#

Das verwundert mich allerings, denn er müsste doch nach dem Quellcode erst die Stunden, dann die Räume und dann die Dozenten Speichern undzwar in so einer Struktur:

Stunde1#
Raum1#Dozent1#
Stunde2
Raum2#Dozent2#

Kann mir jemand sagen wo mein Denkfehler liegt? Danke nochmal!

Hallo!

for(int i=IDC_ED_ST_1; i#define IDC_ED_R_1 1060

#define IDC_ED_R_2 1061
#define IDC_ED_R_3 1062
#define IDC_ED_R_4 1063
#define IDC_ED_R_5 1064
#define IDC_ED_R_6 1065
Ich habe es mir nicht genauer angeguckt, könnte aber eines deiner Probleme unten sein.

Jede Stunde hat noch einen Raum und einen Dozenten als Angabe
in einem jeweiligen extra Editfeld zur eingabe.

Stunde1#
Raum1#Dozent1#
Stunde2
Raum2#Dozent2#

Kann mir jemand sagen wo mein Denkfehler liegt? Danke nochmal!

Also, in der 1. Schleife hängst du alle Stunden hintereinander, also „s1#s2#s3#s4#s5#s6#“. Unmittelbar daran hängst du alle Räume. Das ergibt dann „s1#s2#s3#s4#s5#s6#r1#r2#r3#r4#r5#r6#“. Unmittelbar daran hängst du alle Dozenten, aber diesmal immer jeweils mit Zeilenumbruch. „s1#s2#s3#s4#s5#s6#r1#r2#r3#r4#r5#r6#r1#\nr2#\nr3#\nr4#\nr5#\nr6#\n“. Das mit dem anderen Problem ergibt vielleicht dein Resultat.

Was du vermutlich willst ist in etwas sowas:

CString speicherString;
CString str;

for(int i=0;iGetWindowText(str); 
 speicherString += str + "#"; 
 GetDlgItem(IDC\_ED\_R\_1+i)-\>GetWindowText(str);
 speicherString += str + "#"; 
 GetDlgItem(IDC\_ED\_DOZ\_1+i)-\>GetWindowText(str); 
 speicherString += str + "#\n"; 
}

Jan

1 Like

Super! Damit hast du mir wirklich sehr geholfen! =) Die Nummerierung war komplett durcheinander. Nunja, jedenfalls iste s mir nun auch gelungen den Stundenplan schön strukturiert abzuspeichern mit folgenden Quelltext:

void CSchilling\_3Dlg::open\_mouth:nBTNSpeichern() 
{
 // TODO: Code für die Behandlungsroutine der Steuerelement-Benachrichtigung hier einfügen
 UpdateData(TRUE);

 // Dialog zum Speichern einer Datei

 FILE \*fStundenplan;
 if( (fStundenplan=fopen("Stundenplan.txt","w")) == NULL) 
 {
 MessageBox("Speichern nicht erfolgreich!","Fehler",MB\_OK);
 }
 else
 {
 CString speicherString = "";

 int i = 0;

 for(int s=IDC\_ED\_ST1; sGetWindowText(m\_cs\_Stunde); //und übergibt die jeweiligen Werte an die Membervariable m\_cs\_Stunde 
 speicherString += m\_cs\_Stunde + "#" + "\t\t\t"; //Die übergebenen Werte werden in einem String, getrennt durch eine # gespeichert
 }
 speicherString += "\n";

 int r = IDC\_ED\_R1;
 int d = IDC\_ED\_DOZ1;
 d += i; //Dozent in die jeweilige nächste Zeile rücken
 r += i; //Raum in die jeweilige nächste Zeile rücken 
 int R = r+32; //letztes Feld "Raum"
 int D = d+32; //letztes Feld "Dozent"

 for(r; rGetWindowText(m\_cs\_Raum); //Raum und ...
 speicherString += m\_cs\_Raum + "#";

 GetDlgItem(d)-\>GetWindowText(m\_cs\_Dozent); //Dozent Zeilenweiße auslesen
 speicherString += m\_cs\_Dozent + "#" + "\t\t\t";

 d+=8;
 }
 speicherString += "\n";

 i++; //Zeile 0 bis 7 hochzählen
 r++;
 d++;
 }
 fputs(speicherString, fStundenplan);
 fclose(fStundenplan);
 } 
}

Aber eine allerletzte frage hätte ich da dennoch. Wie kann ich denn statt den Tabs, feste Positionswerte angeben? Bei kleinen Wörtern bleibt es schön übersichtlich in der .txt gespeichert, allerdings verschiebt sich alles bei größeren Wörtern, was ja auch klar ist durch den Tabs. Danke nochmal!

Nunja, scheint wohl keiner ein Antwort darauf zu haben, wie man die Werte an feste Positionswerte wie in einer Tabelle schreiben kann, ohne das andere Werte dabei verrücken… Wird wohl auch so passen. Ich habe den Quellcode einfach nochmal hochgestellt und will mich hiermit auch gleich bei allen bedanken, die mir geholfen haben. Danke euch!

void CSchilling\_3Dlg::open\_mouth:nBTNSpeichern() 
{
 // TODO: Code für die Behandlungsroutine der Steuerelement-Benachrichtigung hier einfügen
 UpdateData(TRUE);

 // Dialog zum Speichern einer Datei

 FILE \*fStundenplan;
 if( (fStundenplan=fopen("Stundenplan.txt","w")) == NULL) //prüfen ob Datei schon vorhanden und geöffnet
 {
 MessageBox("Speichern nicht erfolgreich!","Fehler",MB\_OK);
 }
 else
 {
 CString speicherString = ""; //Initialisierung Speicherstring
 int KWoche = 0;

 SpeichereWerte();

 for(KWoche; KWocheiDelta == -1)
 {
 if(m\_iWoche 1) // vorhergehende Woche anzeigen bis minimal Kalenderwoche 1
 { 
 m\_iWoche--;
 LadeWerte();
 }
 }
 UpdateData(FALSE);

 \*pResult = 1;
}

void CSchilling\_3Dlg::SpeichereWerte() //Speichert Werte in ein Strukt-Array
{

 int Feld = 0;

 for(int s=IDC\_ED\_ST1; sGetWindowText(m\_cs\_Stunde); 
 Woche[m\_iWoche-1].Stunde[Feld] = m\_cs\_Stunde;
 Feld++;
 }
 Feld=0;

 for(int r=IDC\_ED\_R1; rGetWindowText(m\_cs\_Raum);
 Woche[m\_iWoche-1].Raum[Feld] = m\_cs\_Raum;
 Feld++;
 }
 Feld=0;

 for(int d=IDC\_ED\_DOZ1; dGetWindowText(m\_cs\_Dozent);
 Woche[m\_iWoche-1].Dozent[Feld] = m\_cs\_Dozent;
 Feld++;
 }
 Feld=0; 
}

void CSchilling\_3Dlg::LadeWerte() //Liest Werte aus ein Strukt-Array
{
 int Feld = 0;

 for(int s=IDC\_ED\_ST1; sSetWindowText(Woche[m\_iWoche-1].Stunde[Feld]); 
 Feld++;
 }
 Feld=0;

 for(int r=IDC\_ED\_R1; rSetWindowText(Woche[m\_iWoche-1].Raum[Feld]);
 Feld++;
 }
 Feld=0;

 for(int d=IDC\_ED\_DOZ1; dSetWindowText(Woche[m\_iWoche-1].Dozent[Feld]);
 Feld++;
 }
 Feld=0; 

}

Nunja, scheint wohl keiner ein Antwort darauf zu haben,

Ich bin zwar nicht so wahnsinnig sternchengeil, aber bei gar keinem Sternchen darf der Fragesteller ruhig mal selbst in der Doku nach formatierter Ausgabe suchen :wink:

Guck dir mal die CString-Funktion Format() an, bzw. deren „Mutter“ printf().

──────────────────────────────────────────────────────────────────┐
CString s1,s2;
s2 = "foo";
s1.Format("%20s",s2); // s1 == " foo"
s1.Format("%-20s",s2); // s1 == "foo "
──────────────────────────────────────────────────────────────────┘

Jan

1 Like

Oh sry! Hatte ich ganz übersehen… natürlich bekommt dieser Artikel ein Sternchen! ^^ Danke nochmal!