• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

[gelöst] Stringausgabe (C) ?

Hallo,

Ich bräuchte mal eure Hilfe:
In einem C-Programm möchte ich mit Werten mit Nachkommastellen (float) rechnen.
Das Ergebnis soll dann ein EUR-Betrag sein. Es soll also aus 44.6 schließlich ein String "44,60 EUR" werden.
Zu diesem Zweck habe ich eine Funktion geschrieben, die die Umwandlung der Zahl vornimmt.
Da Strings Arrays sind, und Funktionen keine ganzen Arrays zurückgeben können, wird stattdessen ein Zeiger auf das Array
zurückgegeben. Mit diesem Zeiger wird dann der String auf dem Bildschirm ausgegeben.
Leider gibt das Programm nicht wie erwartet "44,60" aus, sondern "8õÿ¿".
Sowas kommt ja häufiger vor.
Das Merkwürdige ist aber, wenn ich die Ausgabeanweisung einfach wiederhole, wird korrekt "44,60" ausgegeben.
Weiß jemand, wie das kommt ?

Hier mein Listing:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *z(float a);
main ()
{
float f=44.6;
/* Ruft Funktion z auf und übergibt f. Erhält Zeiger auf Stringarray zurück. Das Array wird ausgegeben: Ausgabe seltsamerweise "Xõÿ¿" */
printf("%s\n",z(f));
/* Dasselbe nochmal. Ausgabe nun korrekt "44,60". Warum das ? */
printf("%s\n",z(f));
}
char *z(float a)
{
char *x;
int i;
char b[20];
/* Schreibt übergebenen float a zweistellig nach String b */
sprintf(b,"%.2f",a);
/* Ersetzt . durch , */
for(i=0;i<strlen(b);i++)
{
if(b=='.') b=',';
}
x=b;
return x;
}

Übrigens: Wenn ich die main-Funktion stattdessen folgendermaßen fasse, erfolgt sogleich eine korrekte Ausgabe und ich kann mit d[] weiterarbeiten:

main ()
{
float f=44.6;
char d[20];
/* Ruft z auf und schreibt Zeigerarray nach d. */
sprintf(d,"%s",z(f));
printf("%s\n",d);
}

Ich wüßte aber trotzdem gern, was passiert war.


Beste Grüße
 
char *z(float a)
{
char *x;
int i;
char b[20];
/* Schreibt übergebenen float a zweistellig nach String b */
sprintf(b,"%.2f",a);
/* Ersetzt . durch , */
for(i=0;i<strlen(b);i++)
{
if(b=='.') b=',';
}
x=b;
return x;}


hier liegt der Hund begraben:
du hast b als lokale Stackvariable in deiner Funktion deklariert. Nach verlassen deiner Funktion werden ALLE Stackvariablen entfernt. Den Zeiger x lässt du auf irgendetwas zeigen, das gibt es gar nicht mehr ... und der Zeiger selber verschwindet auch nach verlassen der Funktion.
Der zweite Aufruf klappt dann zufällig, weil du Glück hast und die gleichen Speicherstellen erwischst....
 
Ok, ich sehe ein, ich hab noch keinen Plan.

Wenn ich b global, also vor main() deklariere, funzt's.

Vielen Dank für die Antwort !
 
Sinnvollerweise würdest Du bei solchen Aufgaben

entweder/
in der Funktion Speicherplatz allokieren und einen Zeiger zurückliefern, Problem: Du allokierst an einer Stelle und musst an einer anderen Stelle freigeben -> große Gefahr von memoryleaks -> unschön

oder/
Call-By-Rerence, d.h. einen weiteren Parameter (z.B. ein char-Array) übergeben und das in der Funktion füllen.
 
So, ich glaube, ich verstehe jetzt Strings, Arrays und Zeiger auf char etwas besser. Zeiger "x" im Code war gar nicht nötig. So sieht das jetzt aus und geht:

Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *z(float a);

main ()
{
float f=44.6;
printf("%s\n",z(f));
}

char *z(float a)
{
int i;
char *b;
b=(char *) malloc (20);
sprintf(b,"%.2f",a);
for(i=0;i<=strlen(b);i++)
{
if(b[i]=='.') b[i]=',';
}
return b;
}

(Inzwischen habe ich jedoch mein Projekt bereits in perl/Tk realisiert.)

Beste Grüße
 
Oben