open_memstream() richtig nutzen.



  • Hallo,
    es geht hier um Zeile 34-37 hauptsächlich
    nun ich habe ein Problem mit der Nutzung von open_memstream().
    Ich habe mir schon bei https://pubs.opengroup.org/onlinepubs/9699919799/functions/open_memstream.html durchgelesen worum es sich bei open_memstream() handelt.
    Das Ziel ist es ein stream an formatMoney2 zu übergeben, der dann mir die Ausgabe gibt und dass dan in result speichert. Leider funktioniert es nicht.
    Mein Gedanke dazu war:
    ich übergebe open_memstream einmal den char** buffer (in dem Fall &result) und die size_t* lenght (in dem Fall characterCount+1).
    Jedoch mach ich da was falsch und ich kriege am ende der Ausführung einen "Speicherabzugfehler".
    Kann mir da jemand helfen?

    #include <inttypes.h>
    #include <stdbool.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    /*
     * hat keinen Pointer, deswegen auch keine Ausgabe dazu
     */
    void formatMoney2(int64_t cents, FILE* stream) {
    	bool isNegative = cents < 0;
    	cents = (isNegative ? -cents : cents);
    	int64_t euros = cents/100;
    	cents -= 100*euros; // cents = 0
    
    	fprintf(stream, "%s%"PRId64".%02"PRId64" euros\n", (isNegative ? "-" : ""), euros, cents); //formatMoney
    }
    
    char* formatMoney3(int64_t cents) {
    	bool isNegative = cents < 0;
    	cents = (isNegative ? -cents : cents);
    	int64_t euros = cents/100;
    	cents -= 100*euros; // holt sich die cents 0.x
    
    	size_t* characterCount = 0;
    	if(isNegative) characterCount++;	//space for the sign //vorzeichen (schulden)
    	for(int64_t i = euros; i; i /= 10) characterCount++;	//space for the full euros (bis i == 0 ist)
    	if(!euros) characterCount++;	//space for the zero if we don't have full euros (falls euro == 0, dann gebe vorher 0 aus, zb 0.65)
    	characterCount += 3;	//space for the dot and the two cent digits (für .89)
    	characterCount += strlen(" euros");	//space for unit string
    
    	char* result = malloc(sizeof(char)*30);
    	FILE* stream = open_memstream(&result, characterCount+1);
    	formatMoney2(cents, stream);
    	fclose(stream);
    	return result;
    }
    
    void printMoney(uint64_t cents, char* (*formatter)(int64_t cents)) {
    	char* string = formatter(cents);
    	printf("formatMoney(%"PRId64", %p) = %s\n", cents, formatter, string);
    	free(string);
    }
    
    int main() {
    
    	formatMoney2(-196720000000000, stdout);
    	formatMoney2(-314, stdout);
    	formatMoney2(-31, stdout);
    	formatMoney2(-3, stdout);
    	formatMoney2(0, stdout);
    	formatMoney2(2, stdout);
    	formatMoney2(27, stdout);
    	formatMoney2(271, stdout);
    
    	printMoney(-196720000000000, formatMoney3);
    	printMoney(-314, formatMoney3);
    	printMoney(-31, formatMoney3);
    	printMoney(-3, formatMoney3);
    	printMoney(0, formatMoney3);
    	printMoney(2, formatMoney3);
    	printMoney(27, formatMoney3);
    	printMoney(271, formatMoney3);
    }
    
    
    


  • @pcovc sagte in open_memstream() richtig nutzen.:

    ich übergebe open_memstream einmal den char** buffer (in dem Fall &result) und die size_t* lenght (in dem Fall characterCount+1).

    These functions are similar to fmemopen() except that the memory is always allocated dynamically by the function, and the stream is opened only for output.



  • am ende der Ausführung einen "Speicherabzugfehler

    Und was sagt der Debugger?



  • open_memstream ist kein C-Sprachstandard,
    UB bei %p, da nur für Datenzeiger definiert, nicht für Funktionen.

    #include <inttypes.h>
    #include <stdbool.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    /*
     * hat keinen Pointer, deswegen auch keine Ausgabe dazu
     */
    void formatMoney2(int64_t cents, FILE* stream) {
    	bool isNegative = cents < 0;
    	cents = (isNegative ? -cents : cents);
    	int64_t euros = cents/100;
    	cents -= 100*euros; // cents = 0
    
    	fprintf(stream, "%s%"PRId64".%02"PRId64" euros\n", (isNegative ? "-" : ""), euros, cents); //formatMoney
    }
    
    char* formatMoney3(int64_t cents) {
    	bool isNegative = cents < 0;
    	cents = (isNegative ? -cents : cents);
    	int64_t euros = cents/100;
    	cents -= 100*euros; // holt sich die cents 0.x
    
    	size_t characterCount;
    
    	char* result;
    	FILE* stream = open_memstream(&result, &characterCount);
    	formatMoney2(cents, stream);
    	fclose(stream);
    	return result;
    }
    
    void printMoney(uint64_t cents, char* (*formatter)(int64_t cents)) {
    	char* string = formatter(cents);
    	printf("formatMoney(%"PRId64", %p) = %s\n", cents, formatter, string);
    	free(string);
    }
    
    int main() {
    
    	formatMoney2(-196720000000000, stdout);
    	formatMoney2(-314, stdout);
    	formatMoney2(-31, stdout);
    	formatMoney2(-3, stdout);
    	formatMoney2(0, stdout);
    	formatMoney2(2, stdout);
    	formatMoney2(27, stdout);
    	formatMoney2(271, stdout);
    
    	printMoney(-196720000000000, formatMoney3);
    	printMoney(-314, formatMoney3);
    	printMoney(-31, formatMoney3);
    	printMoney(-3, formatMoney3);
    	printMoney(0, formatMoney3);
    	printMoney(2, formatMoney3);
    	printMoney(27, formatMoney3);
    	printMoney(271, formatMoney3);
    	
    	return 0;
    }
    

    https://onlinegdb.com/rk5T2yJCB



  • @Wutz

    Soweit ich weiß schon.
    https://www.gnu.org/software/libc/manual/html_node/String-Streams.html

    @Wutz sagte in open_memstream() richtig nutzen.:

    open_memstream ist kein C-Sprachstandard,

    Wieso ein UB bei %p. Der gibt mir doch einfach den Pointer der in formatMoney liegt.

    UB bei %p, da nur für Datenzeiger definiert, nicht für Funktionen.



  • @pcovc sagte in open_memstream() richtig nutzen.:

    Soweit ich weiß schon.

    Was Du verlinkst ist eine Dokumentation zur glibc, das hat nichts mit einem Standard (ANSI/ISO) zu tun.



  • @manni66
    nach fclose in Zeile 36 kriege ich:
    Program received singal SIGSEGV, Segmentation fault.
    in _IO_mem_finish at memstream.c:136

    Ich kann damit nicht so viel anfangen. vielleicht kannst du mir dazu was sagen?



  • @Swordfish sagte in open_memstream() richtig nutzen.:

    Was Du verlinkst ist eine Dokumentation zur glibc, das hat nichts mit einem Standard (ANSI/ISO) zu tun.

    ach ich habe was falsch bei der antwort verstanden.
    Aber es sollte doch trotzdem mit open_memstream() lösbar sein oder nicht?
    Zumindest sagt es die aufgabenstellung:
    Diese Variante soll nicht selbst den String zusammensetzen, sondern auf formatMoney2() zurückgreifen indem sie zunächst einen FILE* mit open_memstream( )erzeugt,dann mit formatMoney2() den String in diesen Stream reinschreibt, und zum Schluss mit fclose() den Stream schließt und den Ergebnisstring zurückgibt.



  • @Wutz
    Ich muss mich entschuldigen. Der Ansatz hat mir doch sehr geholfen.
    Nun stimmt es auch.



  • @others (damit man nicht lange suchen braucht) Der Fehler liegt an den falschen Parametern für open_memstream(). Die Funktion erwartet als zweiten Parameter einen Pointer auf size_t. Wahrscheinlich war gewollt *characterCount zu inkrementieren, nicht den Pointer selbst. (Was aber auch keinen sinn hat weil sich open_memstream() nicht um den wert des size_t schert.)


  • Mod

    Offtopic: Ja, ja, ja, ich kümmere mich drum. Der Thread war vielleicht 5 Sekunden im falschen Forum und schon sind 2 Meldungen da...



  • @SeppJ
    Stimmt. Danke dafür


Anmelden zum Antworten