Erstes großes Programm, so okay?



  • 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 ist

    char 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!


Anmelden zum Antworten