Verwirrung: dynamischer String, Zeiger / Array Dualität



  • Hallo,

    ich wollte mir eine kleine Funktion basteln, die mit malloc einen gewissen Speicherbereich allokiert, eine Zahl reingeschrieben wird, die Eingabge prüft und anschließend speichert...nur irgendwie komm ich grade mit Feldern / Zeigern durcheinander:

    #include <limits.h>
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
    char *str = NULL;
    char *ePtr = NULL;
    size_t len;
    long zahl = 0;
    unsigned i=0;
    
    str = malloc(LONG_MAX * sizeof(long));
    
    if(str == NULL)
    {
        printf("error!");
        free(str);
    }
    
    fgets(str,sizeof str, stdin);
    printf("\nfgets ok");
    
    len = strlen(str);
    
    puts(str);
    
    realloc(str, (len+1) * sizeof(long));
    
    for(i=0;i<((unsigned) len);i++)
    {
    if( !(str[i] < 48 && str[i] >57) )
    printf("\nFalsche Eingabe\n");
    }
    
    zahl = strtol(str,&ePtr,10);
    printf("zahl: %ld",zahl);
    
    free(str);
    
    return 0;
    }
    

    Wenn ich einen String (Array) wie folgt definiere:

    char str[999];
    

    steht

    str
    

    ja für die Adresse des ersten Elements. Diese ist aber auch in meinem str enthalten (str zeigt auf das erste Element vom allokierten Bereich), bzw. str[i] steht für mein i-tes Element (oder auch *(str+i) )...Das ganze klappt aber vorne und hinten nicht und ich bin irgendwie verwirrt...

    Grüße



  • Warum willst du mit malloc hantieren?
    Warum legst du den Speicherbereich, in welchem der Wert stehen soll, nicht einfach per Deklaration an, zumal du ja weißt, wieviel Werte du benötigst?
    malloc/free benutzt man normalweise nur, wenn man vorab die genaue Größe des Speicherbereichs bzw. Anzahl der Elemente NICHT kennt, also:

    long zahl;

    str = malloc(LONG_MAX * sizeof(long));
    

    Das wird wohl nix, rechne doch selber mal nach, wieviele Bytes hier allokiert werden sollen.

    und dann einfach direkt einlesen, ohne den Umweg über char*, also etwa

    if( 1==scanf("%ld",&zahl) )
      printf("%ld",zahl);
    else
      puts("Fehler");
    


  • Hallo,

    chmbw schrieb:

    ...Das ganze klappt aber vorne und hinten nicht und ich bin irgendwie verwirrt...

    Kein Wunder, da ist ja auch die eine oder andere Unstimmigkeit im Code.

    chmbw schrieb:

    str = malloc(LONG_MAX * sizeof(long));
    

    Hast du so viel RAM? 😮

    chmbw schrieb:

    if(str == NULL)
    {
        printf("error!");
        free(str);
    }
    

    Hier ist ein free nicht nötig, aber weitere Zugriffe auf str wie z.B. fgets, puts, etc. sind zu vermeiden, solange str NULL ist.

    chmbw schrieb:

    fgets(str,sizeof str, stdin);
    

    Mit sizeof str würdest du maximal ca. 4 oder 8 Zeichen einlesen.
    Hier ist sizeof str falsch, denn die Anzahl dynamisch allokierter Elemente lässt mit dem sizeof Operator nicht ermitteln. Du darfst maximal die an malloc übergebene Anzahl nehmen:

    unsigned n = 10;
    	char* s = malloc ( n ); // Hier ist n das gleiche wie n * sizeof(char), weil sizeof(char) immer 1 ist.
    	if ( s != NULL ) 
    	{
    		fgets ( s, n, stdin );
    		puts ( s );
    	}
    else
    ...
    ...
    	free ( s ); // Ein free ( NULL ) schadet nicht, falls malloc fehlschlägt.
    

    chmbw schrieb:

    len = strlen(str);
    

    Bedenke, dass ein '\n' wahrscheinlich auch mitgezählt und in der folgenden for Schleife abgefragt wird.

    chmbw schrieb:

    realloc(str, (len+1) * sizeof(long));

    Was hattest du hier vor? 😕

    chmbw schrieb:

    if( !(str[i] < 48 && str[i] >57) )
    

    Das ist überdenkenswert.

    chmbw schrieb:

    zahl = strtol(str,&ePtr,10);
    

    Für gewissenhafte Benutzer, die nie eine zu lange Zahl eingeben?

    Gruß,
    B.B.



  • ich weiß inzwischen was ich hier für nen mist verzapft habe, das ganze war eine dumme schnapsidee um 3 uhr morgens 😉 🙄 dennoch herzlichen dank für eure beiträge. die ursprüngliche überlegung war, dass ich eine zahl bis zum maximalen wertbereich einlese und die eingabe überprüfe, und danach den string auf die minimal erforderliche länge verkleiner...


Anmelden zum Antworten