sprintf() mit dynamischer Speichervariable



  • Hallo!
    Ich habe mal eine kurze Frage. Ich möchte einen float-Wert in eine Zeichenkette umwandeln. sprintf() speichert das Ergebnis ja in der Variable des ersten Parameters. Aber ich weiß nicht, wie viel Speicherplatz ich reservieren muss. Und im Voraus zu reservieren wäre eine Speicherverschwendung. Das Ergebnis möchte ich in char *umwandlung speichern. Kann mir da jemand helfen? Ich weiß echt nicht weiter. 😞

    MfG
    Keks



  • snprintf mit angegebener Bufferlänge von Null schreibt nichts und gibt zurück, wie viel Platz benötigt worden wäre. Daraus ergibt sich folgende Möglichkeit:

    int chars_needed;
    char *buffer;
    
    chars_needed = snprintf(NULL, 0, "%f", wert) + 1;
    buffer = malloc(chars_needed);
    sprintf(buffer, "%f", wert);
    
    /* ... */
    
    free(buffer);
    


  • seldon schrieb:

    snprintf mit angegebener Bufferlänge von Null schreibt nichts und gibt zurück, wie viel Platz benötigt worden wäre. Daraus ergibt sich folgende Möglichkeit:

    int chars_needed;
    char *buffer;
    
    chars_needed = snprintf(NULL, 0, "%f", wert) + 1;
    buffer = malloc(chars_needed);
    sprintf(buffer, "%f", wert);
    
    /* ... */
    
    free(buffer);
    

    Aber dann müsste der gleiche Vorgang zwei mal ausgeführt werden, wobei beim zweiten mal erst gespeichert wird.



  • brisant schrieb:

    Aber dann müsste der gleiche Vorgang zwei mal ausgeführt werden, wobei beim zweiten mal erst gespeichert wird.

    Das ist wahr, standardkonform geht es aber leider nicht anders. Eine weitere Möglichkeit wäre, über den Rückgabewert von snprintf() "auszuprobieren", ob ein vorher reservierter Speicherbereich ausreichend groß war, und die Formatierung gegebenenfalls mit einem größeren Buffer zu wiederholen. Bestensfalls muss die Formatierung dann nur einmal durchgeführt werden.

    Eine letzte Möglichkeit wäre die Verwendung der GNU-/BSD-Erweiterung asprintf(). Diese Funktion reserviert den benötigten Speicherplatz selbst, ist jedoch nicht in Standard-C enthalten.

    Eszett schrieb:

    Und im Voraus zu reservieren wäre eine Speicherverschwendung.

    Der nötige Speicherplatz für eine Umwandlung einer Gleitkommazahl in einen String lässt sich aber gut nach oben abschätzen. Da Speicherplatz in der Regel sowieso nicht byte-weise reserviert werden kann, hält sich die "Verschwendung" auch in Grenzen.



  • Beim ersten mal wird nicht der ganze Vorgang ausgeführt - ich gehe davon aus, dass die Prüfung, wie viel Platz zum Formatieren eines floats benötigt wird, sehr viel einfacher zu machen sein dürfte als die eigentliche Formatierung.

    Richtig ist, dass die Eingabedaten zweimal ausgewertet werden müssen - aber wenn das erste mal noch kein Speicher vorliegt, sehe ich keine andere, sinnvolle Möglichkeit. Eine Funktion, die sich so verhielte, müsste intern genau das selbe machen - oder einen dynamischen Speicherbereich intern nach Bedarf erweitern, was wohl kaum effizienter sein dürfte.



  • scimansix schrieb:

    brisant schrieb:

    Aber dann müsste der gleiche Vorgang zwei mal ausgeführt werden, wobei beim zweiten mal erst gespeichert wird.

    Das ist wahr, standardkonform geht es aber leider nicht anders. Eine weitere Möglichkeit wäre, über den Rückgabewert von snprintf() "auszuprobieren", ob ein vorher reservierter Speicherbereich ausreichend groß war, und die Formatierung gegebenenfalls mit einem größeren Buffer zu wiederholen. Bestensfalls muss die Formatierung dann nur einmal durchgeführt werden.

    Eine letzte Möglichkeit wäre die Verwendung der GNU-/BSD-Erweiterung asprintf(). Diese Funktion reserviert den benötigten Speicherplatz selbst, ist jedoch nicht in Standard-C enthalten.

    Eszett schrieb:

    Und im Voraus zu reservieren wäre eine Speicherverschwendung.

    Der nötige Speicherplatz für eine Umwandlung einer Gleitkommazahl in einen String lässt sich aber gut nach oben abschätzen. Da Speicherplatz in der Regel sowieso nicht byte-weise reserviert werden kann, hält sich die "Verschwendung" auch in Grenzen.

    asprintf läuft super, jedoch nur unter Linux. Für Windows gibts sowas nicht, oder?



  • asprintf fordert in glibc vor allem anderen erstmal 100 Byte Speicher an. Wenn Speicherverschwendung für dich ein Problem ist, würde ich es für diesen Zweck nicht benutzen.



  • snprintf ist kein C89.
    Prüfe mit FLT_MAX/FLT_MIN einmalig in deinem Programm, wieviel chars deine aktuelle Umgebung für deinen *printf Formatspezifizierer braucht und benutze den Wert dann.


Anmelden zum Antworten