Forum: Mikrocontroller und Digitale Elektronik float to string mit ftoa - komische Ausgabe


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Michael D. (sirs)


Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen!

Für meine Ausgabe über UART hab ich mir eine funktion programmiert, die 
zwei Teile Text und eine float-Zahl übergeben bekommt. Zum testen zieht 
eine Schleife einfach immer 0.1 von n=3.141592 ab. Allerdings 
funktioniert die Ausgabe nur manchmal richtig:

Ausgabe:
1
float 3.14159                                                                
2
float 3.04159                                                               
3
float 2.28623                                                              
4
float 2.18623                                                              
5
float 2.08623                                                              
6
float 2.0/-))                                                              
7
float 2.//-))                                                              
8
float 2../-))                                                              
9
float 2.-/-))                                                             
10
float 2.24159                                                            
11
float 2.14159                                                               
12
float 2.04159                                                               
13
float 1.28623                                                            
14
float 1.18623                                                                
15
float 1.08623                                                                
16
float 1.0/-))                                                                
17
float 1.//-))                                                                
18
float 1../-))                                                               
19
float 1.-/-))                                                               
20
float 1.24159

Fast die gleiche Funktion hab ich mir schon mal gebaut, um einfache Int 
mit Text anzuzeigen, da verwende ich itoa statt ftoa. Die läuft auch 
einwandfrei. Aber was stimmt an dem Code hier nicht?? Braucht ftoa 
irgendwas besonderes um den String richtig zu kreieren?

1
uint8_t Send_UART_FloatWithText(char* textbefore, float number, char* textafter){
2
3
  char* numsend = "0.00000";
4
  ftoa(number, numsend, 5); //value, string, resolution, 5 Nachkommastellen fest
5
  uint8_t textlength = strlen(textbefore)+strlen(numsend)+strlen(textafter);
6
  
7
  if(textlength<=UART_MAXSTRLEN){
8
    char buffer[UART_MAXSTRLEN];
9
    snprintf(buffer, UART_MAXSTRLEN, "%s%s%s", textbefore, numsend, textafter); //print to buffer
10
    Send_UART(buffer);
11
  }else{
12
    Send_UART("ERROR: Text too long!");
13
  }
14
  return textlength;
15
}

Bin grad überfragt, drum frag ich euch ;)

Edit: läuft auf einem Xmega-Baustein, nuf falls wer fragt

: Bearbeitet durch User
von Yalu X. (yalu) (Moderator)


Bewertung
0 lesenswert
nicht lesenswert
Michael D. schrieb:
> char* numsend = "0.00000";
>   ftoa(number, numsend, 5); //value, string, resolution, 5 Nachkommastellen fest

String-Literale (hier "0.00000") dürfen nicht überschrieben werden.
Definiere numsend stattdessen so:

1
  char numsend[8];

Edit:

Auch die ftoa-Funktion erscheint mir verdächtig. Woher kommt die? In der
AVR-Libc ist die m.W. nicht enthalten.

: Bearbeitet durch Moderator
von Michael D. (sirs)


Bewertung
0 lesenswert
nicht lesenswert
Danke für die schnelle Antwort. Geht mit der Variante leider immer noch 
nicht. Selbes Ergebnis.

Warum ollte das so sein? Ein String ist doch auch nur ein Array aus 
Chars, oder?

Edit: ftoa war in einer lib drin, die ich eingebunden habe, genau wie 
das itoa, also irgendeine davon:

#include <stdint.h>
#include <stddef.h>
#include <avr/io.h>
#include <errno.h> //für Umwandlung str to int
#include <limits.h> //Maxima/Minima der Int,...
#include <string.h>
#include <ctype.h>  //zum Testen auf alphanumerische Zeichen und Co
#include <math.h>

: Bearbeitet durch User
von Georg G. (df2au)


Bewertung
0 lesenswert
nicht lesenswert
Michael D. schrieb:
> ftoa war in einer lib drin

GCC kennt kein ftoa. Kann es sein, dass dein ftoa buggy ist?

von wendelsberg (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Michael D. schrieb:
1
snprintf(buffer, UART_MAXSTRLEN, "%s%s%s", textbefore, numsend, textafter);
 //print to buffer

Bau das doch mal so um, da siehst Du woher welce Zeichen kommen.
1
 snprintf(buffer, UART_MAXSTRLEN, "%s#%s#%s", textbefore, numsend,  textafter);
 //print to buffer

wendelsberg

von Dirk B. (dirkb2)


Bewertung
2 lesenswert
nicht lesenswert
Michael D. schrieb:
> Warum isollte das so sein? Ein String ist doch auch nur ein Array aus
> Chars, oder?

Weil der Text (die Zeichen) woanders im Speicher liegt.

Stringliterale sind const char *

von Michael D. (sirs)


Bewertung
0 lesenswert
nicht lesenswert
Dirk B. schrieb:
> Stringliterale sind const char *

Stimmt, die sind ja vorinitialisiert.

Das Problem liegt wohl wirklich in dieser ftoa, woher auch immer mein 
gcc sie kennt (arbeite übrigens nicht mit Atmel studio). Gut sichtbar an 
diesem Versuch von Wendelsberg:
float #1.08623#
float #1.0/-))#
float #1.//-))#
War mir aber auch vor dem Versuch schon klar, weil Text hat immer ohne 
Probleme funktioniert.

Gibt es jemand der eine gute ftoa geschreiben hat? Hab hier nur eine die 
irgendwie komsich ist
https://ucexperiment.wordpress.com/2016/02/23/lean-and-mean-float-to-string-conversion-ftoa/

von Michael D. (sirs)


Bewertung
1 lesenswert
nicht lesenswert
http://www.geeksforgeeks.org/convert-floating-point-number-string/

Hab mal diese ftoa Funktion eingebaut und natürlich in myftoa umbenannt 
um Konflikte zu vermeiden. Kommt interessanterweise genau das gleiche 
Ergebnis raus.

von Georg G. (df2au)


Bewertung
2 lesenswert
nicht lesenswert
Michael D. schrieb:
> Gibt es jemand der eine gute ftoa geschreiben hat?

Im GCC nennt sich die Funktion dtostrf()

von Michael D. (sirs)


Bewertung
0 lesenswert
nicht lesenswert
GEIL, es geht! Danke an alle!

char numsend[8];
dtostrf (number, 3, 5, numsend);

macht die Umwandlung in einen String richtig und die kann ich dann wie 
oben aneinanderhängen. Wo dieses falsche ftoa hergekommen ist das er 
trotzdem geklannt hat? Keine Ahnung...

von Stefan K. (stefan64)


Bewertung
0 lesenswert
nicht lesenswert
Gibt es einen Grund, warum Du nicht gleich alles von snprintf() machen 
lässt?

Viele Grüße, Stefan

von Yalu X. (yalu) (Moderator)


Bewertung
2 lesenswert
nicht lesenswert
Michael D. schrieb:
> http://www.geeksforgeeks.org/convert-floating-point-number-string/

Diese Funktion versagt, wenn die Nachkommastellen nicht als int
darstellbar sind.

Beispiel:

In der dritten Ausgabezeile sollte 2.94159 ausgegeben werden. Die
Nachkommastellen sind 94159. Die Zahl 94159 ist aber nicht als
16-Bit-Integer darstellbar. Die Konvertierung scheint das 17. Bit
einfach abzuschneiden, so dass 94159 - 0x10000 = 28623 übrigbleibt.
Die ausgabe lautet deswegen 2.28623.

In der sechsten Ausgabezeile werden die zu int konvertierten
Nachkommastellen sogar negativ, was zu den seltsamen Symbolen führt.

Wenn du maximal vier Nachkommastellen ausgibst, sollte die Funktion
immer funktionieren.

von Michael D. (sirs)


Bewertung
0 lesenswert
nicht lesenswert
Stefan: snprintf hat mir aus irgendeinem Grund bei %s%f%s statt des 
floats in der Mitte nur ein Fragezeichen geliefert, egal was als Float 
übergeben wurde.

Yalu: Danke für die Erklärung der komischen Zeichen! Sowas sieht man 
nicht auf Anhieb. Und es vervollständigt den Thread :)

von Dirk B. (dirkb2)


Bewertung
1 lesenswert
nicht lesenswert
Michael D. schrieb:
> snprintf hat mir aus irgendeinem Grund bei %s%f%s statt des
> floats in der Mitte nur ein Fragezeichen geliefert, egal was als Float
> übergeben wurde.

Du musst die Floating-Point Version von snprintf nehmen.
Die ist in einer anderen/zusätlichen Library.

von W.S. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Michael D. schrieb:
> Bin grad überfragt, drum frag ich euch ;)

Tja.

Lade dir die Lernbetty runter und benutze conv.c von dort, das läuft 
auch auf einem AVR und die dortige Float-Konvertierung funktioniert.

W.S.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.