Erstes großes Programm, so okay?
-
Hallo Leute, ich hab mir vor kurzem c beigebracht und hab jetzt das erste mal ein relativ großes programm mit Stukturen geschrieben. Die Angabe des Programm hab ich von einem Freund, der das in der Schule machen musste.
Aufgabe dieses Programm:
----Schülerverwaltung----
Erstelle ein Programm zur Verwaltung von Daten in welchem die Standardfunktionen zur
Datenverwaltung realisiert sind:- Eingabe
- Ausgabe aller Daten
- Ändern (Datensatz suchen und überschreiben)
- Löschen
- Ausgabe eines einzelnen Datensatzes (Suche nach Name)
-> Die Daten sind in Form von Strukturen zu verwalten.
-> Eingegebene Daten sind, sofern möglich auf Richtigkeit zu prüfen
-> Aufruf der einzelnen Funktionen durch ein zentrales Menü.Zu erfassen sind die folgenden Daten:
Name, Vorname, Geburtsdatum (ist auf Richtigkeit zu prüfen in einer eigenen Funktion),
KlasseBezeichnung und Noten von maximal 20 Unterrichtsgegenständen (in einer Liste)
Die Anzahl der Gegenstände und Schueler hab ich jetzt nicht genau wie in der Angabe.
Ich habe das Programm etwas ausführlicher gemacht: Bei mir kann man noch Noten und Gegenstände aendern, hinzufügen und noch ein paar andere kleinigkeiten.Das Programm habe ich ausführlich getestet und es scheint alles zu funktionieren.
Nun zu meiner Bitte: Weil das ja mein erstes großes Programm ist, bin ich mir nicht sicher, ob das so stimmt wie ich das ganze schreibe und ob es C- Profis ganz anders machen würden, oder nur kleine veränderungen!
Ich war mir nicht ganz sicher bei den verschachtelten cases und ich habe so wenig wie möglich breaks eingebaut (hab irgendwo gelesen, man soll statt breaks eher schleifenbedingungen nehmen). Oder wie würde ihr die Kommentare setzen, oder kann man was mit meinen Kommentaren anfangen, wenn jemand anders den Quelltext lesen soll? Mehr oder weniger?. Bei den globalen Variablen bin ich mir auch nicht ganz sicher, ob das so passt, die soll man ja so wenig wie mögich verwenden...Bitte um hilfreiche tipps, und ich vertrag auch Kritik ;).
Wäre schonmal froh, wenn sich jemand die Mühe macht, den Quelltext zu lesen
Dann weiß ich in Zukunft besser wie ich C- Programme schreiben soll
Hier der Quelltext:
/**********************************************************/ /* Beschreibung: Dieses Programm verwaltet Datein, */ /* in welchem die Standardfunktionen zur Datenverwaltung */ /* realisiert sind */ /**********************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> /**********************************************************/ /* Strukturendefinition */ /**********************************************************/ struct schueler { // Struktur fuer 200 Schueler char vorname[20]; char name[20]; char gebdatum [5]; char klasse[5]; struct faecher { // Struktur fuer je 20 Faecher/Schueler char fach[20]; int note; } faecher[20]; } schueler[200]; /**********************************************************/ /* Funktionskoepfe */ /**********************************************************/ void eingabe(void); // Schueler eingeben void ausgabe(void); // Schueler ausgeben void suche(void); // Schueler suchen void aendernLoeschen(void); // Wählen zwischen Schueler aendern oder loeschen void aendern(void); // Schueler aendern void loeschen(void); // Schueler loeschen void speichern(void); // Schueler auf Festplatte speichern /**********************************************************/ /* Globale Variablen */ /**********************************************************/ int i = 1; // Eingabe der Schueler int l = 1; // Alle andern Funktionen mit Schuelern int n = 1; // Zaehlen aktueller Faecher /**********************************************************/ /* */ /* Hauptprogramm */ /* */ /**********************************************************/ int main() { /* Hier werden alle Felder mit nichts befuellt */ for(l=1;l<=20;l++) { strcpy(schueler[l].vorname,""); strcpy(schueler[l].name,""); for(n=1;n<=20;n++) strcpy(schueler[l].faecher[n].fach,""); } while(1) { // Hauptmenue bleibt immer (außer wenn exit(EXIT_FAILURE)) system("cls"); // Clear Screen int menue = 0; // Dient zum Aufrufen eines Untermenüs des Zentralmenüs /********************************/ /******** Zentrales Menü ********/ /********************************/ printf("----SCHUELERVERWALTUNG----\n\n"); printf("1: Eingabe\n"); printf("2: Ausgabe aller Schueler\n"); printf("3: Suchen eines Schuelers\n"); printf("4: Daten speichern\n"); printf("5: Programm beenden\n"); scanf("%d", &menue); switch(menue) { // Aufrufen der einzelnen Funktionen case(1): eingabe(); break; case(2): ausgabe(); break; case(3): suche(); break; case(4): speichern(); break; case(5): return 0; // Programm beendem default: printf("Falsche Eingabe"); } } } /**********************************************************/ /* Funktionsname: eingabe */ /* */ /* gibt die Schueler ein */ /* */ /* Parameter: keine */ /**********************************************************/ void eingabe() { int x = 1; // fuer die Anzahl der Faecher, die Sie eingeben wollen int j = 1; // auswählen, ob noch mehr Schueler einzugeben sind while(j == 1) { // Solange j == 1 werden Schueler eingegeben /* Leeren String suchen */ while((strcmp(schueler[i].vorname,"")!=0)&&(strcmp(schueler[i].name,"")!=0)&&(l<=200)) l++; system("cls"); // Clear Screen /******************************************/ /******** Schueler werden eingeben ********/ /******************************************/ printf("%d. Schueler:", i); printf("\nVorname: "); scanf("%s", schueler[i].vorname); printf("\nName: "); scanf("%s", schueler[i].name); printf("\nGeburtsdatum [d.m.j]: "); scanf("%s", schueler[i].gebdatum); printf("\nWollen Sie ein Fach+Note eingeben? (1/0): "); scanf("%d", &x); n = 1; // n wieder auf 1 setzen, falls veraendert wurde while(x == 1) { // Solange x==1 werden Faecher eingegeben printf("\nFach: "); scanf("%s", schueler[i].faecher[n].fach); printf("\nNote: "); scanf("%d", &schueler[i].faecher[n].note); printf("Noch ein Fach? (1/0): "); scanf("%d", &x); n++; } printf("\nNoch einen Schueler eingeben ? (1/0)"); // 0 --> zurueck ins Hauptmenue 1 --> Naechster Schueler scanf("%d", &j); i++; // i++, fuer naechsten Schueler } } // Ende der Funktion /**********************************************************/ /* Funktionsname: ausgabe */ /* */ /* gibt die eingegebenen Schueler aus */ /* */ /* Parameter: keine */ /**********************************************************/ void ausgabe() { system("cls"); // Clear Screen l = 1; // Zählvariable zum ausgeben der Schueler vom Anfang bis zum Ende int k = 1; // Fuer 1. Schueler, 2. Schueler usw... while(l < 200) { // Bis zum letzen Schueler /* Dieses if ueberprueft, ob in dem String etwas steht, oder ob er leer ist */ if((strcmp(schueler[l].vorname,"")!=0)&&(strcmp(schueler[l].name,"")!=0)&&(l<=200)) { /* Ausgeben der Strings, in denen ein Schueler existiert */ printf("%d. Schueler:", k); printf("\n\tVorname: %s", schueler[l].vorname); printf("\n\tName: %s", schueler[l].name); printf("\n\tGeburtsdatum: %s\n\n", schueler[l].gebdatum); n=1; // n wieder auf 1 setzen, falls veraendert wurde /* Dieses while ueberprueft, ob in dem String etwas steht, oder ob er leer ist */ while(n <= 19) { if(strcmp(schueler[l].faecher[n].fach,"")!=0) { printf("\t%s: ", schueler[l].faecher[n].fach); printf("\t%d\n", schueler[l].faecher[n].note); } n++; } printf("\n"); k++; // z.B. 1. Schueler auf 2. Schueler erhoehen } l++; // Naechster Schueler } system("PAUSE"); // Konsole wird nicht geschlossen } /**********************************************************/ /* Funktionsname: suche() */ /* */ /* Sucht einen Schueler und wenn gefunden, dann aufrufen */ /* von aendernLoeschen Funktion */ /* */ /* Parameter: keine */ /**********************************************************/ void suche() { system("cls"); // Clear Screen char vornameSuche[20]; // String fuer den Vornamen den sie suchen char nameSuche[20]; // String fuer den Namen den sie suchen printf("Vorname: "); scanf("%s", vornameSuche); printf("\nName: "); scanf("%s", nameSuche); l = 1; // l wieder auf 1 setzen, falls veraendert wurde while(l < i) { // Jeden Schueler vergleichen int ret = strcmp(schueler[l].vorname, vornameSuche); // Vorname vergleichen; ret ist der Rückgabewert der Funtion strcmp (vergleicht 2 Strings) if(ret == 0) { // Wenn Rückgabewert 0 ist, dann ist der Vorname identisch ret = strcmp(schueler[l].name, nameSuche); // Name vergleichen if(ret == 0) { aendernLoeschen(); // Wenn Vorname und Name übereinstimmen diese Funktion aufrufen break; // Aus Schleife hüpfen } } l++; // Naechsten Schueler ueberpruefen } if(l == i) { // Wenn jeder Schueler kontrolliert wurde und nicht mit Gesuchtem übereinstimmt... system("cls"); // Clear Screen printf("Schueler nicht gefunden!\n"); system("PAUSE"); // Konsole wird nicht geschlossen } } /**********************************************************/ /* Funktionsname: aendernLoeschen() */ /* */ /* Sucht einen Schueler und man wird gefragt, ob man ihn */ /* loeschen, oder aendern will */ /* */ /* Parameter: keine */ /**********************************************************/ void aendernLoeschen() { int aendernloeschenMenue = 0; // Auswahlvariable fuer das Menue int error = 0; // Solange Falsche Eingabe, erneuter Versuch system("cls"); // Clear Screen /* Gesuchter Schueler wird nochmals ausgegeben */ printf("\n\tVorname: %s", schueler[l].vorname); printf("\n\tName: %s", schueler[l].name); printf("\n\tGeburtsdatum: %s\n\n", schueler[l].gebdatum); n=1; // n wieder auf 1 setzen, falls veraendert wurde while(n <= 19) { if(strcmp(schueler[l].faecher[n].fach,"")!=0) { printf("\t%s: ", schueler[l].faecher[n].fach); printf("\t%d\n", schueler[l].faecher[n].note); } n++; } /* Menue zum auswaehlen ob Schueler aendern oder loeschen */ while(error == 0) { // Solange falsche Eingabe, Eingabe wiederholen printf("1: Aendern, 2: Loeschen, 3: zurueck\n"); scanf("%d", &aendernloeschenMenue); system("cls"); // Clear Screen switch(aendernloeschenMenue) { // Aufrufen der einzelnen Funktionen case(1): /* AENDERN */ aendern(); error = 1; break; case(2): /* LOESCHEN --> Nichts in String schreiben */ strcpy(schueler[l].vorname,""); strcpy(schueler[l].name,""); strcpy(schueler[l].gebdatum,""); for(n=1;n<20;n++) strcpy(schueler[l].faecher[n].fach,""); error = 1; break; case(3): error = 1; // Zurueck ins Hauptmenue break; default: printf("Fehlerhafte Eingabe\n\n"); error = 0; // Wenn falsche Eingabe nochmal abfragen } } } /**********************************************************/ /* Funktionsname: aendernLoeschen() */ /* */ /* Einzelnen Daten des Schuelers aendern */ /* */ /* Parameter: keine */ /**********************************************************/ void aendern() { int aendernMenue = 0; // Auswahlvariable; was man ändern will int error = 0; // Solange Falsche Eingabe, erneuter Versuch int error_2 = 0; // Solange Falsche Eingabe, erneuter Versuch int error_3 = 0; // Solange Falsche Eingabe, erneuter Versuch char fach[20]; // String zum suchen des Faches int note; // Integer zum suchen der Note system("cls"); // Clear Screen while (error_3 == 0) { // Solange falsche Eingabe, Eingabe wiederholen system("cls"); // Clear Screen /* Gesuchter Schueler wird nochmals ausgegeben */ printf("\n\tVorname: %s", schueler[l].vorname); printf("\n\tName: %s", schueler[l].name); printf("\n\tGeburtsdatum: %s\n\n", schueler[l].gebdatum); n=1; while(n <= 19) { if(strcmp(schueler[l].faecher[n].fach,"")!=0) { printf("\t%s: ", schueler[l].faecher[n].fach); printf("\t%d\n", schueler[l].faecher[n].note); } n++; } printf("\nVornamen aendern: 1\n"); printf("Namen aendern: 2\n"); printf("Geburtsdatum aendern: 3\n"); printf("Noten aendern: 4\n"); printf("Zurueck: 5\n"); scanf("%d", &aendernMenue); /* In diesem switch kann man alle bisher eingegebenen Daten aendern */ switch(aendernMenue) { case(1): /* Neuer Vorname */ printf("\nNeuer Vorname: "); scanf("%s", schueler[l].vorname); break; case(2): /* Neuer Name */ printf("\nNeuer Name: "); scanf("%s", schueler[l].name); break; case(3): /* Neues Geburtsdatum */ printf("\nNeues Geburtsdatum: "); scanf("%s", schueler[l].gebdatum); break; case(4): /* Noten aendern */ printf("\nFach loeschen: 1"); printf("\nNeues Fach: 2"); printf("\nNote aendern: 3\n"); scanf("%d", &aendernMenue); /* In diesem switch kann man alle faecher veraendern */ switch(aendernMenue) { /* Fach loeschen */ case(1): error_2 = 0; while(error_2 == 0) { printf("\nFach eingeben: "); scanf("%s", fach); for(n=1;n<=20 && error_2 == 0;n++) { // Jeden Schueler durchlaufen if(strcmp(fach, schueler[l].faecher[n].fach) == 0) { // Wenn gesuchtes Fach mit existierendem Fach uebereinstimmt... strcpy(schueler[l].faecher[n].fach,""); // Nichts in das Existierende reinschreiben printf("Erfolgreich geloescht\n"); system("PAUSE"); error_2 = 1; // for-Schleife beenden } } error_2 = 1; // while-Schleife beenden if(n==21) { // Wenn alle Faecher durgelaufen und Fach nicht gefunden printf("Fach nicht gefunden\n"); system("PAUSE"); error_2 = 1; } } break; /* Neues Fach */ case(2): printf("\nFach eingeben: "); scanf("%s", fach); printf("Note eingeben: "); scanf("%d", ¬e); n = 1; // n wieder auf 1 setzen, falls veraendert wurde while(strcmp(schueler[l].faecher[n].fach,"")!=0) n++; // Leeren String suchen strcpy(schueler[l].faecher[n].fach,fach); // In leeren String das neue Fach kopieren schueler[l].faecher[n].note = note; // Note kopieren printf("Erfolgreich erstellt\n"); error_3 = 0; break; /* Note aendern */ case(3): while(error_2 != 2) { printf("\nFach eingeben: "); scanf("%s", fach); error_2 = 0; for(n=1;n<=20 && error_2 != 1;n++) { // Jeden Schueler durchlaufen if(strcmp(schueler[l].faecher[n].fach, fach) == 0) { // Wenn gesuchtes Fach mit existierendem Fach uebereinstimmt... printf("Neue Note eingeben: "); scanf("%d", ¬e); schueler[l].faecher[n].note = note; // Neue Note eintragen printf("Erfolgreich ueberschrieben\n"); system("PAUSE"); error_2 = 1; // for-Schleife beenden } } if(n==21) { printf("Fach nicht gefunden\n"); system("PAUSE"); system("cls"); } error_2 = 2; // while-Schleife beenden } break; // break fuer case(3) } break; // break fuer case(4) case(5): error_3 = 1; // zurueck ins Hauptmenue break; default: system("cls"); printf("\nFehlerhafte Eingabe\n\n"); error = 1; // Eingabe wiederholen break; } } }
mfg Sund0se
-
hiiiii!
du verträgst kritik, das ist gut, wohl bekommts und los gehts:
1)
also, mein ansi c compiler mag den code nicht compilieren.
grund, nicht ansi c konforme deklarationen wie z.b.int menue = 0; int k = 1;
usw.
möglicherweise wollen/sollen auch andere deinen code übersetzen und haben/mögen keinen C99/C++ compiler?
2)
funktion speichern fehlt. char klasse[5]; scheint ungenutzt.
char gebdatum [5]; bisken wenig zeichen?
3)struct schueler { // Struktur fuer 200 Schueler
char vorname[20];
char name[20];
char gebdatum [5];
char klasse[5];
struct faecher { // Struktur fuer je 20 Faecher/Schueler
char fach[20];
int note;
} faecher[20];
} schueler[200];die struktur faecher lässt sich bestimmt auch in anderen programmteilen benutzen. auch wenn nicht, mach den code leserlicher, hol die struktur da raus und lege lieber satt dessen eine instanz an. verbau dir nicht deinen quellcode.
/* Hier werden alle Felder mit nichts befuellt */
int menue = 0;
for(l=1;l<=20;l++) {
strcpy(schueler[l].vorname,"");
strcpy(schueler[l].name,"");
for(n=1;n<=20;n++)
strcpy(schueler[l].faecher[n].fach,"");
}mach dir das leben einfacher, benutz die array-initialisierung mit 0. ( siehe code in main(). )
printf("\nNoch einen Schueler eingeben ? (1/0)");
benutz eindeutige eingabeaufforderungen wie 'j' / 'n', "ja"/"nein" etc.
int i = 1; // Eingabe der Schueler
int l = 1; // Alle andern Funktionen mit Schuelern
int n = 1; // Zaehlen aktueller Faechernixa gutta. globale variablen lieber static deklarieren, meist hat man es mit
modulen zu tun.- prüfung der puffergrenzen/arraygrenzen, siehe kommentare
scanf("%s", schueler[i].name); <--- absturzgefahr, eingabe absichern.
// Solange x==1 werden Faecher eingegeben
...
n++; <--- absturzgefahr, arraygrenze absichern.
scanf("%d", &menue); <-- ganz üble kiste das, absichern. (siehe weiter unten.)
for(l=1;l<=20;l++) <--- 0 bis maximal bis 19! siehe auch andere arrays/* Leeren String suchen */
while((strcmp(schueler[i].vorname,"")!=0)&&(strcmp(schueler[i].name,"")!=0)&&(l<=200)) l++;lieber anzahl speichern und ab index anzahl-1 weiter eingeben (aufwendiger).
8.1)
bei der eingabe eines buchstabens anstatt einer zahl geht das programm in eine
endlosschleife über. grund: scanf nicht abgesichert ( siehe weiter oben. )
8.2)
will man sich die schüler anzeigen lassen, obwohl noch nix eingegeben wurde, werden unnötiger weise 200 mal strukturen abgefragt. abhilfe: zählvariabe, strukturenarray nacheinander befüllen, verkettete liste etc. damit würden auch die globalen variablen entfallen. die löschfunktion wäre abzuändern.
danach erscheint die meldung: drücken sie eine beliebige taste...
man denkt, das programm sei zu ende. es fehlt eine meldung nach dem motto: "keine einträge vorhanden" oder so, mit einer option zur rückkehr zum menü ...
8.3)
die option noch ein fach eingeben funzt nicht richtig.
8.4)
deine funktion aendern() ist mächtig gewaltig umständlich und fehlt als option im zentralen menü.sei nicht so knauserig mit den arraygrößen.
denk an namen wie Pippilotta Viktualia Rallgordina Pfefferminza Efraimstochter Langstrumpf
arrayindizes beginnen bei 0 und enden bei der anzahl ihrer elemente -1. alles in allem sind einige funktionen vieeeeeel zuuuuuu laaaaaaang. lieber in möglichst wiederverwendbare teilschritte aufteilen. (keine bange, das kommt mit der zeit.)Lass dich nicht allzu dolle entmutigen, ein 'bombensicheres' Programm zu schreiben ist nicht ganz
so einfach und braucht einiges an Übung/Erfahrung/Aufwand.Näherungslösung/ Verbesserungsvorschläge für die Datenstruktur:
#include <time.h> //////////////////////////////////////////////////////////////////////////// // Diese Daten besser in eine Konfigurationsdatei auslagern, um // das Programm flexibler zu machen. // Die Variablen in den Strukturen würden dann char* vorname, // char* name, Fach* lauten, etc. Stichwort: malloc und co. // ANZAHL_FAECHER_MAX, NAMELEN_MAX, etc. würden gänzlich entfallen. // Das würde hier jetzt aber zu weit gehen, ich habe Feierabend. :D char* faecher[] = {"Mathematik", "Deutsch", "Sport", "Ansi C", "etc." }; char* klassen[] = {"1A", "1B", "etc."}; //////////////////////////////////////////////////////////////////////////// #define ANZAHL_FAECHER_MAX 20 #define NAMELEN_MAX 64 typedef struct {// Verkürzung des Quellcodes, Einführung eines neuen Datentypen. unsigned fach_id; // Speichert den Index (ID) eines Fachs. unsigned note; }Fach; typedef struct {// dito. char vorname[NAMELEN_MAX]; char name[NAMELEN_MAX]; time_t geburtstag; // Bei der Eingabe ins time_t Format umwandeln. unsigned klassen_id; // Speichert den Index (ID) einer Klasse. Fach fach[ANZAHL_FAECHER_MAX]; }Schueler; /* // Alternativ ( flexibler, aufwändiger. ): typedef struct { Schueler* schueler; Schueler* next; unsigned n; // Momentane Anzahl in der Liste. }SchuelerListe; */ #define N 200 int main() { int i = 0, j = 0; // Strukturelemente sauber mit 0 initialisieren. // Setzt alle Elemente auf 0. Schueler sc[N] = {0}; // Alternativ als Liste: SchuelerListe list; // Überzeuge dich, das auch die eingebetteten Elemente 0 sind: for ( i = 0; i < N; i++ ) for ( j = 0; j < ANZAHL_FAECHER_MAX; j++ ) printf("%d", sc[i].fach[j].fach_id ); // Jepp, 0. // ... to be continued ... return 0; }
So, jetzt hab ich erstmal keinen Bock mehr. Tipps zur Absicherung der Eingaben etc, vllt. ein anderes mal.
Gruß,
a.
-
Vielleicht die Funktionen kleiner machen, dafür aber mehr davon.
Damit meine ich, daß man Sachen wievoid ausgabe() { system("cls"); // Clear Screen l = 1; // Zählvariable zum ausgeben der Schueler vom Anfang bis zum Ende int k = 1; // Fuer 1. Schueler, 2. Schueler usw... while(l < 200) { // Bis zum letzen Schueler /* Dieses if ueberprueft, ob in dem String etwas steht, oder ob er leer ist */ if((strcmp(schueler[l].vorname,"")!=0)&&(strcmp(schueler[l].name,"")!=0)&&(l<=200)) { /* Ausgeben der Strings, in denen ein Schueler existiert */ printf("%d. Schueler:", k); printf("\n\tVorname: %s", schueler[l].vorname); printf("\n\tName: %s", schueler[l].name); printf("\n\tGeburtsdatum: %s\n\n", schueler[l].gebdatum); n=1; // n wieder auf 1 setzen, falls veraendert wurde /* Dieses while ueberprueft, ob in dem String etwas steht, oder ob er leer ist */ while(n <= 19) { if(strcmp(schueler[l].faecher[n].fach,"")!=0) { printf("\t%s: ", schueler[l].faecher[n].fach); printf("\t%d\n", schueler[l].faecher[n].note); } n++; } printf("\n"); k++; // z.B. 1. Schueler auf 2. Schueler erhoehen } l++; // Naechster Schueler } system("PAUSE"); // Konsole wird nicht geschlossen }
zerlegt, zum Beispiel in
int schueler__istFrei(struct schueler* this) { return (strcmp(this->vorname,"")==0)||(strcmp(this->name,"")==0); } void schueler__ausgabe(struct schueler* this,int k) { /* Ausgeben der Strings, in denen ein Schueler existiert */ int n; printf("%d. Schueler:", k); printf("\n\tVorname: %s", this->vorname); printf("\n\tName: %s", this->name); printf("\n\tGeburtsdatum: %s\n\n", this->gebdatum); /* Dieses while ueberprueft, ob in dem String etwas steht, oder ob er leer ist */ for (n=0 ; n <= 19; n++) { if (strcmp(this->faecher[n].fach,"")!=0) { printf("\t%s: ", this->faecher[n].fach); printf("\t%d\n", this->faecher[n].note); } } printf("\n"); } void ausgabe() { system("cls"); // Clear Screen int k = 1; // Fuer 1. Schueler, 2. Schueler usw... for (l=1 ; l < 200 ; l++) { // Bis zum letzen Schueler /* Dieses if ueberprueft, ob in dem String etwas steht, oder ob er leer ist */ if (!schueler__istFrei(&schueler[l])) { schueler__ausgabe(&schueler[l],k); k++; // z.B. 1. Schueler auf 2. Schueler erhoehen } } system("PAUSE"); // Konsole wird nicht geschlossen }
So Sachen wie schueler__istFrei kannste mit ein wenig Glück dann uch in anderen Funktionen verwenden. Aber darum gehts gar nicht. Es geht nur drum, die Funktionen übersichtlicher zu machen. Aufräumen führt dann automatisch zur objektorientierten Programmierung, die entgegen anderslautender Gerüchte natürlich auch in C angemessen ist.
-
volkard schrieb:
Aufräumen führt dann automatisch zur objektorientierten Programmierung, die entgegen anderslautender Gerüchte natürlich auch in C angemessen ist.
das stimmt, aber es geht auch ohne zwei _ hintereinander.
-
;fricky schrieb:
aber es geht auch ohne zwei _ hintereinander.
Ja, ich hätte CamelCase_CamelCase schreiben sollen, wie Henkman&the_Underscores jetzt auch verabschiedet haben.
Aber das blaue this ist ganz allein Dir gewidmet.
-
;fricky schrieb:
aber es geht auch ohne zwei _ hintereinander.
Das ist so wie ++. Da muß halt auch __ rein. Wechen däm Obscheckt.
Das geht in C genauso kompakt und wiederverwertbar. Aber, Hauptsache wir
haben C-Code in C++-Syntax.
-
Scheppertreiber schrieb:
Das geht in C genauso kompakt und wiederverwertbar. Aber, Hauptsache wir haben C-Code in C++-Syntax.
Wenn ich recht informiert bin, geht
int schueler__istFrei(struct schueler* this) { return (strcmp(this->vorname,"")==0)||(strcmp(this->name,"")==0); }
gar nicht auf einem C++-Compiler, sondern nur auf einem C-Compiler.
Ich würde mal behaupten, das ist C++-Code in C-Syntax und nicht wie Du geraten hast C-Code in C++-Syntax.
-
Funktioniert auch unter C++, wenn man vorher
#define this that
schreibt -)
volkard und ;fricky, die Protagonisten der neuen Doku-Soap...
-
volkard schrieb:
Aber das blaue this ist ganz allein Dir gewidmet.
passt schon, es gibt 'nen codegenerator, der c-code ausspuckt und der auch 'this' nimmt. allerdings 'malloc'd' der sich noch 'ne struct, auf die sich das this bezieht. das fehlt noch bei dir.
ich hätte CamelCase_CamelCase schreiben sollen, wie Henkman&the_Underscores jetzt auch verabschiedet haben.
double__underscores hab u.a. ich ihm gestern (im IRC) wieder ausgeredet.
-
volkard schrieb:
Aufräumen führt dann automatisch zur objektorientierten Programmierung, die entgegen anderslautender Gerüchte natürlich auch in C angemessen ist.
Huh? Wer behauptet denn so einen Blödsinn? Natürlich kann das angemessen sein, wo kommen wir denn sonst hin?
volkard schrieb:
Ja, ich hätte CamelCase_CamelCase schreiben sollen, wie Henkman&the_Underscores jetzt auch verabschiedet haben.
Das hast du mit deinem absurden __Vorschlag ja auch schlau hinbekommen.
C++ forever schrieb:
volkard und ;fricky, die Protagonisten der neuen Doku-Soap...
denn zusammen rockt ihr die bude
Immerhin verstehe ich diesmal, worum es geht.
-
Danke Leute, habt mir echt geholfen und hab das Programm jetzt soweit ausgebessert, doch ein paar Sachen von abcok verstehe ich noch nicht so ganz:
1.) array-initialisierung mit 0, weil ich hab mir verkettet Listen noch nicht angesehen und für sowas braucht man verk. Listen, oder?
2.) Etwas absichern (z.B. Eingabe mit scanf) versteh ich auch nicht. Meinst du mit fflush(stdin)den Tastaturpuffer leeren?
3.) Wo geht bei dir die Funktion Fach eingeben nicht? Bei mir geht die pefekt...?!
4.) Wie würdet ihr die Funktion aendern() verkürzen? Ich habe Noten ändern (das case im case) als eigene Funktion gemacht.
5.) Wenn ich z.B bei "Wollen Sie noch ein Fach eingeben? (ja: 1 nein: 0)" 1231 eingebe, geht er gleich zum zweiten Schueler und überspringt alles unter der Eingabe in der Schleife. Hat das was mit dem Absichern zu tun?
Bitte um Hilfe
lG und danke nochmals
Sund0se
-
hi,
zu 1)
das initialisiert alle elemente des Arrays Schueler mit 0:Schueler schueler[200] = {0};
zu 2)
ein programm sollte nicht abstürzen, wenn anstatt einer angeforderten
zahl ein buchstabe eingegeben wird. das war mit absichern gemeint.
dafür gibt es u.a. die möglichkeit: einen puffer wählen, der groß genug istchar buf[BUFSIZ] = {0};
und für die eingaben fgets benutzen ( die legendären funktionen wie clear_buffer, fflush(stdin), etc. entfallen dann gänzlich ) und aus diesem puffer alle weiteren infos wie zahlen, namen, datum etc. mittels sscanf etc. extrahieren.
BUFSIZ ist die größe des eingabepuffers in bytes und in stdio.h definiert.zu 3)
aber nur wenn der benutzer keinen fehler macht(buchstaben statt zahl eingibt). siehe 2)zu 4)
funktion aendern() in teilaufgaben zerlegen und kleine funktionen draus machen.
z.b. kannst du für namen eingeben und namen ändern eine funktion gemeinsam nutzen.
zu 5)
ja, das hat damit zu tun.hier noch die eine oder andere funktion als anregung, um zu zeigen was ich mit teilaufgaben und kleinen funktionen meine:
#define ARRSIZ 64 // Entfernt einen Zeilenumbruch, der von fgets eingefügt wird. void remove_newline ( char* buf ) { char* p = strrchr ( buf, '\n' ); if (p) *p = 0; } typedef struct { char name[ARRSIZ]; char vorname[ARRSIZ]; }Schueler; // Allgemeine Eingabefunktion. // allow_void_input bestimmt, ob eine Leereingabe erlaubt/nicht erlaubt ist. int input ( char* buf, int bufsize, int allow_void_input ) { do { fgets ( buf, bufsize, stdin ); remove_newline (buf); if ( ferror (stdin) ) { perror ("input"); exit(1); } if ( allow_void_input == 0 && *buf == 0 ) puts ("Eine Leereingabe ist nicht erlaubt!"); }while ( *buf == 0 && allow_void_input == 0 ); } void vorname_nachname_eingabe ( char* msg, char* buf, int bufsize, int allow_void ) { printf("%s ", msg ); input ( buf, bufsize, allow_void ); } void vornamen_eingeben ( Schueler* ps ) { char buf[BUFSIZ] = {0}; if ( ps == NULL ) return; do { vorname_nachname_eingabe ( "Vornamen eingeben:", buf, sizeof(buf), 0 ); if ( strlen(buf) >= sizeof(ps->vorname)) puts("Der eingegebene Vornamen ist zu lang."); else if ( strlen ( buf ) > 0 ) strcpy(ps->vorname, buf); }while ( strlen(buf) >= sizeof(ps->vorname) ); } Schueler* schueler_suchen_vorname ( Schueler* ps, int n ) { int i; char buf[BUFSIZ] = {0}; printf ("Vorname: "); input ( buf, sizeof ( buf ), 0 ); for ( i = 0; i < n; i++ ) if ( strcmp ( buf, ps[i].vorname ) == 0 ) return &ps[i]; return NULL; } void schueler_anzeigen ( Schueler* ps ) { printf ( "Vorname: %s\n", ps->vorname ); // printf ( "Nachname: %s\n", ps->name ); } void alle_schueler_anzeigen ( Schueler* ps, int n ) { int i; for ( i = 0; i < n; i++ ) if ( *ps[i].vorname != 0 ) schueler_anzeigen ( &ps[i] ); } #define N 300 int main() { Schueler* ps = NULL; Schueler schueler[N] = {0}; int allow_void = 0; // Bestimmt, ob eine Leereingabe erlaubt/nicht erlaubt ist vornamen_eingeben ( &schueler[0] ); printf ("Alle Schueler anzeigen. "); alle_schueler_anzeigen ( &schueler[0], N ); printf ("Schueler suchen. "); ps = schueler_suchen_vorname ( &schueler[0], N ); if ( ps != NULL ) puts ("Schueler gefunden"); else puts ("Schueler nicht gefunden"); if ( !ps ) return 0; // Gleiche Funktion wie für die Eingabe zum Ändern benutzen: allow_void = 1; // Leere Eingabe genehm. puts("Vornamen aendern, Abbruch mit Entertaste."); vornamen_eingeben ( ps, allow_void ); printf ("Alle Schueler anzeigen. "); alle_schueler_anzeigen ( &schueler[0], N ); return 0; }
einen schueler hinzuzufuegen würde ca. so aussehen:
void neuen_schueler_eingeben ( Schueler* ps ) { vornamen_eingeben ( ps ); nachnamen_eingeben ( ps ); geburtsdatum_eingeben ( ps ); klasse_eingeben ( ps ); // USW }
du siehst, das programm ist in teilaufgaben zerlegt, die von kleinen
funktionen erledigt werden, wobei die funktionen nicht mehr als ca. 15 zeilen lang sind.
-
okay, super, vielen dank
hab jetzt das ganze mit zeiger gemacht und es geht super.
hätt da noch ne frage bzg. der funktion loeschen
wenn der zeiger ps vom typ Schueler auf den schueler zeigt, den man löschen will, muss man doch einfach
*ps[x].vorname = 0;
da er bei der abfrage bei alle_schueler_anzeigen sowieso abfragt, ob der vorname nicht 0 ist, oder wie würdet ihr es machen?
wenn so, wie kommt ihr dann auf das x?
scheint ne blöde frage zu sein, steh aber echt auf der leitung!