Namensverwaltung mit Zeigern und dynamischen Variablen



  • Hallo,
    ich bin noch ein Anfänger in C.
    Ich habe bis jetzt nur mehr Erfahrung in VB.NET

    Wie im Titel steht möchte ich Namen verwalten mit Zeigern und dynamischen Variablen.

    Es beim Programmstart die Anzahl der Namen angegeben werden, dann werden diese nacheinander eingegeben (Begrenzt auf 10 Namen und 50 Zeichen, Doppelnamen erlaubt). Bei der Eingabe sind nur Groß- und Kleinbuchstaben erlaubt, aber Trennzeichen ' ' und '-' für Doppelnamen. Das Zeilenwechselzeichen '\n' ist in einem Namen nicht zugelassen. Das String-Ablschlusszeichen '\0' soll auch berücksichtigt werden. Diese Namen sollen dann alle in ein dynamisches Feld mit char-Zeigern gespeichert werden.

    Dann sollen einfach alle nochmal so ausgegeben werden.
    Dann folgt, dass die Namen umgeformt werden sollen, also erster Buchstabe groß und der Rest klein.

    Die letzte Verarbeitung von den Namen ist dann, dass diese nach dem Alphabet sortiert werden sollen, aber nur die Zeiger der Felder sollen in der Reihenfolge geändert werden.

    Da sind dann noch 2 weitere Funktionen, eine den den Eingabepuffer leert und eine, welche die dynamischen Speicherbereiche wieder freigeben soll.

    Mein Stand:

    Soweit gebe ich in der main Funktion per Eingabe an, wie viele Namen ich verwalten möchte. Begrenze dann die Anzahl der Namen auf max. 10, oder min. 1.

    Ich habe dann nun 6 Funktionen:

    Eine Funktion zum Namen einlesen (da gibt es schon Probleme).
    Eine zum einfachen Ausgeben, der in den vorhandenen Zeigern.
    Eine zum Konvertieren (Groß- und Kleinschreibung).
    Eine zum Sortieren (Alphabet).
    Eine zum Puffer leeren (kein Problem).
    Und die letzte zum leeren der dynamischen Speicherbereiche.

    Wo ich jetzt schon hänge ist die erste Funktion zum Eingeben der Namen.
    Was ich dort nun bis jetzt habe ist nicht sehr viel (fast nichts).
    Ich weiß nicht wie man dort anfängt.

    /******************************************************************************/
    /* GetNamen     : Einlesen der Namen in ein Feld dynamischer Größe            */
    /******************************************************************************/
    /* Rueckgabewert: keiner                                                      */
    /* Eingang      : Inhalt des Namensarray und die Anzahl der Namen             */
    /* Ausgang      : keiner                                                      */
    /******************************************************************************/
    
    void GetNamen( char * NamPtrArr[], int NamAnz ) { 
    
    /* Vereinbarung von Variablen fuer die Funktion GetNamen                      */
    
    /* Programmcode der Funktion GetNamen                                         */
    /* ========================================================================== */
    
      printf(" weiter  mit [return]: ");                /* Auf Tastendruck warten */
      ClrStdIn();                             /* Funktion: Auf Tastendruck warten */
    
    }/* GetNamen() */
    

    Könnte mir da jemand helfen?

    Mit freundlichen Grüßen
    hudzi



  • Das fast ist zuviel.

    Wo hapert es denn?
    - Text einlesen? -> scanf, fgets
    - dynamischer Speicher? -> malloc, free
    - kein C-Buch? -> Bchladen, öffentliche/schulische Bibliothek



  • Ich habe das hier ausprobiert:
    (MAX_NAM_LEN ist eine Konstante mit dem Wert 50)

    /******************************************************************************/
    /* GetNamen     : Einlesen der Namen in ein Feld dynamischer Größe            */
    /******************************************************************************/
    /* Rueckgabewert: keiner                                                      */
    /* Eingang      : Inhalt des Namensarray und die Anzahl der Namen             */
    /* Ausgang      : keiner                                                      */
    /******************************************************************************/
    
    void GetNamen( char * NamPtrArr[], int NamAnz ) { 
    
    /* Vereinbarung von Variablen fuer die Funktion GetNamen                      */
    
    /* Verabeitung                                                                */
      char   AktNam[MAX_NAM_LEN];
      char * PtrNam;
      int    indAktNamPtr;
      int    Ende;
    
    /* Programmcode der Funktion GetNamen                                         */
    /* ========================================================================== */
    
      for ( indAktNamPtr = 0; indAktNamPtr < NamAnz; indAktNamPtr++)
        {
          printf(" Name %2d: ", indAktNamPtr + 1);
          fgets( AktNam, MAX_NAM_LEN+1, stdin );
          Ende = strlen(AktNam) - 1;
          if( AktNam[Ende] == '\n' )
              {
                AktNam[Ende] = '\0';
                Ende--;
              }
            else ClrStdIn();
    
          PtrNam = (char *) calloc( Ende+2, sizeof(char) );
    
          strcpy( PtrNam, AktNam );
    
          NamPtrArr[indAktNamPtr] = PtrNam;
        }
    
      printf(" weiter  mit [return]: ");                /* Auf Tastendruck warten */
      ClrStdIn();                             /* Funktion: Auf Tastendruck warten */
    
    }/* GetNamen() */
    

    Da sagt mir dann VS2008 beim auführen, dass

    NamPtrArr[indAktNamPtr] = PtrNam;
    

    nicht funktioniert.

    Mit freundlichen Grüßen
    hudzi



  • Der Compiler schreibt nicht "funktioniert nicht". Der gibt eine Menge mehr an Informationen an.
    Auch eine Fehlernummer mit Text dazu.
    Das macht der nicht zum Spaß, diese Informationen sind sehr hilfreich.

    Übersetzt du das Programm im C-Modus?

    Das +1 bei fgets ist falsch.
    sizeof(char) ist per Default 1.


  • Mod

    DirkB schrieb:

    Wo hapert es denn?





  • #include <stdlib.h>
    #include <stddef.h>
    #include <ctype.h>
    #include <string.h>
    #include <stdio.h>
    
    #define MAX_NAME_LENGTH	52
    
    void clear( FILE * file )
    {
    	int ch = 0;
    	while( ( ch = fgetc( file ) ) != '\n' && ch != EOF );
    }
    
    char* get_name( FILE * file )
    {
    	char buffer[ MAX_NAME_LENGTH ];
    	char *start = buffer;
    	char *result = NULL;
    	size_t length = 0;
    
    	if( !fgets( buffer, MAX_NAME_LENGTH, file ) ) return NULL;
    
    	while( *start && isspace( *start ) ) ++start;
    	length = strlen( start );
    
    	if( !length ) return NULL;
    
    	if( start[ length - 1 ] == '\n' ) start[ --length ] = '\0';
    
    	if( !( result = malloc( length + 1 ) ) ) return NULL;
    
    	strcpy( result, start );
    	return result;
    }
    
    void print( char ** names, size_t num_names )
    {
    	size_t i = 0;
    
    	if( !names ) return;
    
    	for( ; i < num_names; ++i )
    		printf( "#%Iu: %s\n", i + 1, names[ i ] );
    }
    
    void sort( char ** names, size_t num_names )
    {
    	int sorted = 1;
    	size_t i = 0;
    	char *temp = NULL;
    
    	do {
    		sorted = 1;
    
    		for( i = 0; i < num_names - 1; ++i ) {
    
    			if( strcmp( names[ i ], names[ i + 1 ] ) > 0 ) {
    
    				temp = names[ i ];
    				names[ i ] = names[ i + 1 ];
    				names[ i + 1 ] = temp;
    				sorted = 0;
    			}
    		}
    
    	} while( !sorted );
    }
    
    int main()
    {
    	size_t i = 0;
    	size_t j = 0;
    	size_t num_names = 0;
    	char ** names = NULL;
    
    	while( puts( "Wieviele Namen moechten Sie eingeben? (1-10)" ), scanf( "%Iu", &num_names ) != 1 || ( num_names < 1 || 10 < num_names ) ) {
    
    		fputs( "\nUngueltige Eingabe. Bitte wiederholen!\n\n", stderr );
    		clear( stdin );
    	}
    
    	if( !( names = malloc( num_names * sizeof( char * ) ) ) ) {
    
    		fputs( "\nNot enough memory!\n\n", stderr );
    		return EXIT_FAILURE;
    	}
    
    	clear( stdin );
    	putchar( '\n' );
    
    	for( ; i < num_names; ++i ) {
    
    		printf( "Bitte Name #%Iu eingeben: ", i + 1 );
    		names[ i ] = get_name( stdin );
    
    		if( !names[ i ] ) {
    
    			fputs( "\nEingabefehler. Programm wird abgebrochen.\n\n", stderr );
    
    			for( ; j < i; ++j ) free( names[ j ] ); 
    			free( names );
    			return EXIT_FAILURE;
    		}
    	}
    
    	puts( "\n\nIhre Eingabe:\n" );
    	print( names, num_names );
    
    	for( i = 0; i < num_names; ++i ) names[ i ][ 0 ] = toupper( names[ i ][ 0 ] );
    
    	puts( "\n\nIhre Eingabe konvertiert:\n" );
    	print( names, num_names );
    
    	sort( names, num_names );
    
    	puts( "\n\nIhre Eingabe sortiert:\n" );
    	print( names, num_names );
    
    	for( i = 0; i < num_names; ++i ) free( names[ i ] );
    	free( names );
    }
    

    // edit: hollapa



  • Die Fehlermeldung:
    "Eine nicht behandelte Ausnahme des Typs "System.NullReferenceException" ist in dynNamensFeld.exe aufgetreten.

    Zusätzliche Informationen: Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.

    > dynNamensFeld.exe!GetNamen(char** NamPtrArr = <Nicht definierter Wert>, int NamAnz = 3) Zeile 277 + 0x9 Bytes C++"

    NamPtrArr ist nicht definiert. Ich weiß nicht was ich damit anfangen soll.

    Wir sollen unsere Programme als C++\CLR - Konsolenanwendungen erstellen, aber normales C benutzen.

    @Swordfish: Danke für deinen ausführlichen Code. Ich werde den erstmal genauer durchgehen.



  • Swordfish schrieb:

    printf( "#%Iu: %s\n", i + 1, names[ i ] );
     scanf( "%Iu", &num_names ) != 1
    

    Was soll denn der Müll?



  • hudzi schrieb:

    Wir sollen unsere Programme als C++\CLR - Konsolenanwendungen erstellen, aber normales C benutzen.

    Dann bist du falsch hier, dafür gibt es ein entsprechendes Subforum.



  • Das was du da beschreibst ist ein Runtime-Error.
    Der kommt zur Laufzeit und nicht beim compilieren/linken.

    Du übergibst schon einen ungültigen Wert an deine Funktion GetNamen.

    Der Fehler liegt außerhalb der Funktion.



  • Wutz schrieb:

    Swordfish schrieb:

    printf( "#%Iu: %s\n", i + 1, names[ i ] );
     scanf( "%Iu", &num_names ) != 1
    

    Was soll denn der Müll?

    Könntest Du das spezifizieren?



  • Kannst du das spezifizieren?
    Nach welchem Standard ist %I ein gültiger Formatspezifizierer?



  • Ah den meinst. Tausche gerne %Iu gegen %zu .



  • Nur dass %zu erst C99 ist und VC2008 kein C99 kann.



  • Boah Wutz, in dem Fall bleib ich bei %Iu . Andere Vorschläge?



  • %I ist überhaupt kein Standard, %z wenigstens C99. Deshalb bleibt %I immer noch Müll.



  • Wutz schrieb:

    [...] VC2008 [...]

    .



  • Swordfish schrieb:

    void clear( FILE * file )
    {
    	int ch = 0;
    	while( ( ch = fgetc( file ) ) != '\n' && ch != EOF );
    }
    
    }
    

    @Swordfish: Kannst du mir erklären warum du FILE * file benutzt? Ich darf es nicht benutzen.

    Wutz schrieb:

    Dann bist du falsch hier, dafür gibt es ein entsprechendes Subforum.

    @Wutz: Ich programmiere aber nicht mit dem Framework. Ich soll CLR als Projekttyp auswählen, aber normales C benutzen.



  • hudzi schrieb:

    NamPtrArr ist nicht definiert. Ich weiß nicht was ich damit anfangen soll.

    hahahahaha
    woher hast du denn den code copygepastet?
    🙄



  • hudzi schrieb:

    Ich habe dann nun 6 Funktionen:
    ...
    Eine zum Puffer leeren (kein Problem).
    ...

    hudzi schrieb:

    Swordfish schrieb:

    void clear( FILE * file )
    {
    	int ch = 0;
    	while( ( ch = fgetc( file ) ) != '\n' && ch != EOF );
    }
    

    @Swordfish: Kannst du mir erklären warum du FILE * file benutzt? Ich darf es nicht benutzen.


Anmelden zum Antworten