Kundenverwaltung mit CSV, bitte um Hilfe!!!
-
Danke an alle für eure Hilfe, besonders an dich flamer!
Das Programm ist fast fertig.
Ich habe nur ein Problem und zwar wenn ich einen neuen Datensatz erstelle,
möchte ich Stings in Variablen einlesen und diese dann ins CSV schreiben. Das Funktioniert auch prima und zwar so:printf("\nwollen Sie eine weiter Eingabe machen? JA=9/NEIN<>9\n");
scanf("%d",&eingabe);if(eingabe==9){
while(eingabe==9) {
char Vname[STRINGSIZE],Nname[STRINGSIZE],Adr[STRINGSIZE],Plz[STRINGSIZE],ORT[STRINGSIZE],LAND[STRINGSIZE];
counter++;
realloc(kunde,sizeof(kunde) * counter);
printf("\nBitte Vornamen eingeben: ");
scanf("%s",Vname);
printf("\nBitte Nachnamen eingeben: ");
scanf("%s",Nname);
printf("\nBitte Adresse eingeben: "); //Da liegt das Problem !!!
scanf("%s",Adr);
printf("\nBitte PLZ eingeben: ");
scanf("%s",Plz);
printf("\nBitte Ort eingeben: ");
scanf("%s",ORT);
printf("\nBitte Land eingeben: ");
scanf("%s",LAND);
fprintf(datei3,"%d,%s,%s,%s,%s,%s,%s\n",counter,Vname,Nname,Adr,Plz,ORT,LAND);
printf("\nwollen Sie eine weiter Eingabe machen? JA=9/NEIN<>9\n");
scanf("%d",&eingabe);
}
}nur bei Adresse funktioniert es nicht, weil ich muss ja folgendes abfragen:
zB Teststrasse 1
also ein Sting mit Space.
Der wird nicht genommen ins CSV wird unter Adresse -> Teststrasse geschrieben und die Hausnummer 1 wird schon ins nächste "Feld" PLZ geschrieben.
PLZ wird dann natürlich garnicht abgefragt, sondern es wird gleich die Eingabe das Orts erwartet.Ich bitte euch mir noch einmal aus der Patsche zu helfen.
Vielleicht hast wieder du, flamer, eine Idee?lg Phil
-
Hmm. scanf() ist eine ******.
printf("\nBitte Adresse eingeben: "); //Da liegt das Problem !!! scanf("%s",Adr);
Man könnte scanf() anweisen, auch noch eine Zahl zu holen:
scanf("%s %d",Adr);
Allerdings hab ich meistens unrecht, wenn ich über scanf() rede --
das mußt du selbst testen.
Ich selbst verwende scanf() so gut wie nie.
Deshalb hatten wir auch zu strtok() o.ä. geraten.Du solltest wirklich die Code-Tags verwenden (die Buttons unter den Smileys),
sonst bin ich scheinbar der einzige, der deinen Code liest...
-
Danke für eure großartige Unterstützung.
Das Programm läuft sehr schön nur hab ich leider noch immer Probleme mit der dynamischen Speicheranpassung, realloc.Der Code sieht wie folgt aus:
[code]#include<string.h> #include <stdio.h> #include <stdlib.h> #define STRINGSIZE 100 typedef struct { char Kundennummer[sizeof(int)]; char Vorname[40]; char Nachname[40]; char Adresse[80]; char PLZ[5]; char Ort[20]; char Land[20]; } KUNDEN ; int main(int argc, char **argv) { int i,c,counter=0; char string[STRINGSIZE]; FILE *datei; FILE *datei2; FILE *datei3; datei=fopen(argv[1], "r"); datei2=fopen(argv[1], "r"); datei3=fopen(argv[1], "a+"); while( (c=fgetc(datei)) != EOF) { if(c == '\n') counter++; } //printf("Counter = %d \n",counter); KUNDEN *kunde = malloc(sizeof(*kunde) * counter); for(i=0;i<counter;i++) { fgets(string,STRINGSIZE,datei2); int a=0; char *ptr; ptr = strtok(string, ","); while(ptr != NULL) { if(a==0) strcpy(&kunde[i].Kundennummer, ptr); else if(a==1) strcpy(&kunde[i].Vorname, ptr); else if(a==2) strcpy(&kunde[i].Nachname, ptr); else if(a==3) strcpy(&kunde[i].Adresse, ptr); else if(a==4) strcpy(&kunde[i].PLZ, ptr); else if(a==5) strcpy(&kunde[i].Ort, ptr); else if(a==6) strcpy(&kunde[i].Land, ptr); a++, ptr = strtok(NULL, ","); } fprintf(stdout,"Kundennummer von %s %s,\nWohnhaft in %s, %s %s %s \nlautet: %s\n\n", kunde[i].Vorname,kunde[i].Nachname,kunde[i].Adresse,kunde[i].PLZ,kunde[i].Ort,kunde[i].Land,kunde[i].Kundennummer); } //free(kunde); int eingabe=0; printf("\nwollen Sie eine weiter Eingabe machen? JA=9/NEIN<>9\n"); scanf("%d",&eingabe); if(eingabe==9){ while(eingabe==9) { char Vname[STRINGSIZE],Nname[STRINGSIZE],Adr[STRINGSIZE],HNr[STRINGSIZE],Plz[STRINGSIZE],ORT[STRINGSIZE],LAND[STRINGSIZE],buf[STRINGSIZE]; [b]counter++; //counter ist eine int zaehlvariable <--------- !!!! KUNDEN *kunde = realloc(kunde,(sizeof(*kunde)/(counter-1)) * counter); // <-[/b] strcpy(&kunde[counter].Kundennummer, atoi(counter)); printf("\nBitte Vornamen eingeben: "); scanf("%s",Vname); strcpy(&kunde[counter].Vorname, Vname); printf("\nBitte Nachnamen eingeben: "); scanf("%s",Nname); strcpy(&kunde[counter].Nachname, Nname); printf("\nBitte Strasse eingeben: "); scanf("%s",Adr); printf("\nBitte Hausnummer eingeben: (0 für keine)"); scanf("%s",HNr); if(atoi(HNr)!=0) { strcat(Adr," "); strcat(Adr,HNr); } strcpy(&kunde[counter].Adresse, Adr); printf("\nBitte PLZ eingeben: "); scanf("%s",Plz); strcpy(&kunde[counter].PLZ, Plz); printf("\nBitte Ort eingeben: "); scanf("%s",ORT); strcpy(&kunde[counter].Ort, ORT); printf("\nBitte Land eingeben: "); scanf("%s",LAND); strcpy(&kunde[counter].Land, LAND); fprintf(datei3,"%d,%s,%s,%s,%s,%s,%s\n",counter,Vname,Nname,Adr,Plz,ORT,LAND); printf("\nwollen Sie eine weiter Eingabe machen? JA=9/NEIN<>9\n"); scanf("%d",&eingabe); } } for(i=0;i<counter;i++) { fprintf(stdout,"Kundennummer von %s %s,\nWohnhaft in %s, %s %s %s \nlautet: %s\n\n", kunde[i].Vorname,kunde[i].Nachname,kunde[i].Adresse,kunde[i].PLZ,kunde[i].Ort,kunde[i].Land,kunde[i].Kundennummer); } free(kunde); return EXIT_SUCCESS; } [/code]
Thx für eure Mühen
lg phil[cpp]
-
jetzt hab ich erst verstanden was du mit den code-tags gemeint hast.
-
KUNDEN *kunde = realloc(kunde,(sizeof(*kunde)/(counter-1)) * counter);
man: realloc ist ein wenig kompilzierter als malloc().
Tim hat das in einem FAQ-Post erklärt (3.2):
http://www.c-plusplus.net/forum/viewtopic-var-t-is-206606.htmlTrotzdem nehme ich nicht an, daß das Problem daran liegt (könnte aber sein).
Ich habe leider keinen Compiler zur Hand, und dein Code ist schon eher schwer
im Kopf auszuführen.
Vielleicht geht sich's heute Abend aus, wenn nicht, seh ich mir's in den nächsten
Tagen genauer an.jetzt hab ich erst verstanden was du mit den code-tags gemeint hast.
-
Bin leider nicht schlau geworden aus dem Beispiel.
Ich hab auch folgendes probiert;
printf("Groesse Feld vor realloc = %d", sizeof(*kunde)); kunde = (KUNDEN*)realloc(kunde,sizeof(KUNDEN)*100); printf("Groesse Feld nach realloc = %d", sizeof(*kunde));
ich hab mir eine unterschiedliche Rückmeldungen von sizeof erhofft aber da tut sich leider nichts durchs realloc.
flamer schrieb:
Vielleicht geht sich's heute Abend aus
Das wäre echt spitze von dir, eigentlich hätte ich ja schon letzten Donnerstag abgeben sollen, habs aber bis diesen Donnerstag, sprich morgen abend, rauszögern können.
Der Rest funktioniert, zwar nicht schön - mit einigen Warnungen des Compilers - aber er funktioniert. Schön wäre zwar ohne Warnung aber seis drum.
Doch leider brauche ich die Erweiterung vom Array weil das ein Teil der Aufgabenstellung war
Leider komm ich einfach nicht drauf.
Deshalb bin ich für jeden Rat dankbar.
Lg Phil
-
Ich mach sonst nicht die Hausaufgaben für andere, aber diesmal mach ich eine Ausnahme.
Ich poste also eine Modifikation deines Programmes, die funktioniert;
aber nur sehr wenig getestet.Ich mache das, weil ich den Eindruck habe, daß du dich schon sehr gequält hast,
außerdem bist du sehr freundlich.
Von mir aus gib meinen Code als Hausübung ab, aber bitte schau ihn dir genau an,
und überlege, warum ich manches anders gemacht habe, als du. Im Zweifel kannst du
ja hier nachfragen.
Das ganze ist nur eine Modifikation, und keine Beispiel für schönen Stil, weil
es eher unübersichtlich ist.#include <string.h> #include <stdio.h> #include <stdlib.h> // ein bißchen größer, zur Sicherheit #define STRINGSIZE 1000 typedef struct { /* die Sache mit sizeof(int) war ein dummer Scherz, wollte sagen: nimm nicht zu wenig Platz für die Nummer an. Ich nehm halt mal 10, sizeof(int) ist meistens 4 -- du hattest nur 3, und in 3 Bytes passt nicht mal eine halbwegs große Zahl */ char Kundennummer[10]; char Vorname[40]; char Nachname[40]; char Adresse[80]; char PLZ[5]; char Ort[20]; char Land[20]; } KUNDEN; // global, damit stirb() sie kennt // (also wegen der Fehlerbehandlung, die du ausgelassen hattest) FILE *datei = NULL; KUNDEN *kunde = NULL; int stirb(char *warum, int code) { fprintf(stderr, warum); if (datei) fclose(datei); if (kunde) free(kunde); exit(code); } int main(int argc, char **argv) { int i, c, counter = 0; char string[STRINGSIZE]; if (argc < 2) stirb("Zu wenige Argumente.\n", 3); datei = fopen(argv[1], "r"); while ((c = fgetc(datei)) != EOF) if (c == '\n') counter++; fseek(datei, 0, SEEK_SET); // so springt man wieder zum Anfang printf("Counter = %d \n",counter); KUNDEN *kunde = malloc(sizeof(*kunde) * counter); for (i = 0; i < counter; i++) { fgets(string, STRINGSIZE, datei); int a = 0; char *ptr; ptr = strtok(string, ","); while (ptr != NULL) { if (a == 0) strcpy(kunde[i].Kundennummer, ptr); else if (a == 1) strcpy(kunde[i].Vorname, ptr); else if (a == 2) strcpy(kunde[i].Nachname, ptr); else if (a == 3) strcpy(kunde[i].Adresse, ptr); else if (a == 4) strcpy(kunde[i].PLZ, ptr); else if (a == 5) strcpy(kunde[i].Ort, ptr); else if (a == 6) strcpy(kunde[i].Land, ptr); a++, ptr = strtok(NULL, ","); } fprintf(stdout, "Kundennummer von %s %s,\nWohnhaft in %s, %s %s %s \nlautet: %s\n\n", kunde[i].Vorname, kunde[i].Nachname, kunde[i].Adresse, kunde[i].PLZ, kunde[i].Ort, kunde[i].Land, kunde[i].Kundennummer); } fclose(datei); int eingabe = 0; printf("\nwollen Sie eine weiter Eingabe machen? JA=9/NEIN<>9\n"); scanf("%d", &eingabe); while (eingabe == 9) { int temp; KUNDEN *reallocated; counter++; reallocated = realloc(kunde, sizeof(*kunde) * counter); if (!reallocated) stirb("realloc ging schief\n", 1); kunde = reallocated; sprintf(kunde[counter-1].Kundennummer, "%d", counter); printf("\nBitte Vornamen eingeben: "); scanf("%s", kunde[counter-1].Vorname); printf("\nBitte Nachnamen eingeben: "); scanf("%s", kunde[counter-1].Nachname); printf("\nBitte Strasse eingeben: "); scanf("%s", kunde[counter-1].Adresse); printf("\nBitte Hausnummer eingeben: (0 für keine)"); scanf("%d", &temp); if (temp != 0) sprintf(kunde[counter-1].Adresse, "%s %d", kunde[counter-1].Adresse, temp); printf("\nBitte PLZ eingeben: "); scanf("%s", kunde[counter-1].PLZ); printf("\nBitte Ort eingeben: "); scanf("%s", kunde[counter-1].Ort); printf("\nBitte Land eingeben: "); scanf("%s", kunde[counter-1].Land); if (!(datei = fopen(argv[1], "a"))) stirb("Kann Datei nicht schreiben.\n", 2); fprintf(datei, "%s,%s,%s,%s,%s,%s,%s\n", kunde[counter-1].Kundennummer, kunde[counter-1].Vorname, kunde[counter-1].Nachname, kunde[counter-1].Adresse, kunde[counter-1].PLZ, kunde[counter-1].Ort, kunde[counter-1].Land); fclose(datei); printf("\nwollen Sie eine weiter Eingabe machen? JA=9/NEIN<>9\n"); scanf("%d", &eingabe); } for (i = 0; i < counter; i++) { fprintf(stdout, "Kundennummer von %s %s,\nWohnhaft in %s, %s %s %s \nlautet: %s\n\n", kunde[i].Vorname, kunde[i].Nachname, kunde[i].Adresse, kunde[i].PLZ, kunde[i].Ort, kunde[i].Land, kunde[i].Kundennummer); } free(kunde); stirb("", EXIT_SUCCESS); }
Danke für eure großartige Unterstützung.
Gerne, ich hoffe aber, daß du was dazulernst und irgendwann selbst hier
Lösungen postest. Wäre mir lieber als alle Dankbarkeit.
-
Und bitte denk darüber nach, wie man durch bösartige Eingaben in das Programm
Pufferüberläufe erzeugen kann.ich hab mir eine unterschiedliche Rückmeldungen von sizeof erhofft aber da tut sich leider nichts durchs realloc.
Ja, das liegt daran, daß realloc() wahrscheinlich gut funktioniert hat,
aber sizeof(*kunde) ist immer gleich. Man muß sich merken, wie viel Speicher
man bekommen hat.
-
Und bau noch die Fehlerbehandlung ein, für die möglichen Fehler, die ich
übersehen habe...
-
flamer schrieb:
sizeof(*kunde) ist immer gleich
aber ich multipliziere doch mit counter oder mit 100 hab ich es auch schon probiert, müsste da nicht etwas anderes raus kommen?
oder hab ich grad einen Denkfehler?lg Phil
-
Hier mal ein Tutorial zu realloc:
http://www.hs-augsburg.de/~sandman/c_von_a_bis_z/c_016_007.htmMfG f.-th.
-
aber ich multipliziere doch mit counter oder mit 100 hab ich es auch schon probiert, müsste da nicht etwas anderes raus kommen?
oder hab ich grad einen Denkfehler?Wahrscheinlich ein Kommunikationsproblem.
sizeof(*kunde)
Das ist die Größe der Kunden-Struktur, und die ist konstant.
Natürlich ändert sich das Ergebnis vonsizeof(*kunde) * counter
wenn man counter ändert.
Der sizeof-Operator funktioniert nur für "einzelne" Dinge, und als Ausnahme
für Arrays, aber nicht für Zeiger (da ist ein subtiler Unterschied).
Speicher von malloc() wird via Zeiger angesprochen, deshalb ist sizeof nutzlos.
Daher sage ich: man muß sich's merken.
-
OK danke dir.
Leider gibt mir der von dir veränderte Code eine Memory Map Meldung die so beginnt aus:
*** glibc detected *** ./a.out: double free or corruption (!prev): 0x0804b008 ***
wenn ich mit <>9 die erneute Eingabe verneine.
Tritt das Problem bei dir auch auf oder liegt das an meiner Umgebung?
lg Phil
-
habs lösen können, ich hab mich noch etwas mit free und fclose spielen müssen.
-
Und ich hab's nicht testen können, weil ich bis jetzt gebraucht hab, um
die Unix-Kiste zu reparieren. (Auf Windows hat's den Fehler nicht hervorgebracht)Spät, aber doch:
Man muß nur nach jedem fclose() die Variable datei wieder auf NULL setzen,
sonst wird sie in stirb() noch einmal geschlossen.Und man muß das free() am Ende von main() einfach rausnehmen.