float to string mit ftoa - komische Ausgabe

OP #4965268
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
Moderator #4965281
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.
OP #4965323
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>
Gast #4965335
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
OP #4965362
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/
Moderator #4965462
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.
OP #4965529
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 :)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren