Forum: Compiler & IDEs atoi verrechnet sich aber warum?


von Daniel (Gast)


Lesenswert?

Hi

hab da ein kleines Problem mit der Funktion "atoi".

Der Code soll aus meinen Nachrichten ein Command und einen wert 
interpretieren. Das Command wird immer perfekt kopiert. Der Wert wird 
imemr perfekt kopiert aber die letzten 3 Zeilen sind die wichtigsten. 
Sobald ich den Wert umwandele klappt es beim ersten mal danach kommt nur 
noch mist. Dachte immer atoi kann Zeichen in max 16Bit werte umwandeln.

Habe folgenden Code:

void command()
{
  char fifo[15] = "";      //copyed command
  uint8_t pfifo = 0;    //current fifo point
  char command[10];    //command
  uint8_t pcommand = 0;  //current command point
  char value[5] = "!!!!!";//value as Charakters
  uint8_t pvalue = 0;    //current value point
  uint16_t val = 0;    //value
  bool ok = false;        //OK FLAG

  char buffer[5];
  char massage[20];

  //Reset Command found Flag
  uart.comm_found = false;

  //Read and Write Pointer equal?
  if(uart.rx.pread == uart.rx.pwrite)
    return false;

  //Copy Command from RX Fifo
  do
  {
    fifo[pfifo] = uart.rx_buffer[uart.rx.pread];
    uart.rx_buffer[uart.rx.pread] = '!';


    uart.rx.pread++;
    pfifo++;
    uart.rx.used_size--;

    if(uart.rx.pread >= uart.rx.size)
      uart.rx.pread = 0;

    if(pfifo > 15)
      return false;

  }
  while(uart.rx_buffer[uart.rx.pread] != '#');

  //copy and delete the last '#'
  fifo[pfifo] = uart.rx_buffer[uart.rx.pread];
  uart.rx_buffer[uart.rx.pread] = '!';
  uart.rx.pread++;

  if(uart.rx.pread >= uart.rx.size)
    uart.rx.pread = 0;

  //Copy Command from Fifo
  pfifo = 0;
  while(fifo[pfifo] != '=')
  {
    command[pcommand] = fifo[pfifo];

    pcommand++;
    pfifo++;

    if(pcommand > 10)
      return false;
  }

  command[pcommand] = '\0';

  //Jump over '='
  pfifo++;

  //Copy Value from Fifo
  while(fifo[pfifo] != '#')
  {
    value[pvalue] = fifo[pfifo];

    pvalue++;
    pfifo++;

    if(pvalue > 5)
      return false;
  }

  //Clean Value
  while(value[4] == '!')
  {
    value[4] = value[3];
    value[3] = value[2];
    value[2] = value[1];
    value[1] = value[0];
    value[0] = ' ';
  }


  send_uart(", ");

  val = atoi(value);

  itoa(val,buffer,10);
  send_uart(buffer);
}

Jemand eine Idee?

von Axel R. (axelroro)


Lesenswert?

Hallo,
ohne das Programm jetzt genauer analysiert zu haben: Die Falle ist oft, 
dass man einen uint Wert an itoa verfüttert, dieser den aber als signed 
int verarbeitet. Mag also sein, dass atoi noch funktioniert, aber die 
darauffolgende Ausgabe von itoa schief geht. Ggfs dafür utoa nehmen.

Ohne Gewähr - bin auch nicht so der Experte.

Gruss
Axel

von Daniel (Gast)


Lesenswert?

Danke für die schnelle Antwort aber wenn ich nee if anweisung drangäng 
um bei einem bestimten wert etwas zu machen klappt es auch nicht. Die 
umwandlung mit itoa past eigentlich ziemlich gut.

von Daniel (Gast)


Lesenswert?

So

mir ist noch was aufgefallen scheinbar scheint er die vorigen werte zu 
behalten warum auch immer. Sende ich zb. relay=1# was das relay anziehen 
lassen soll dann ist der wert denn ich zurück bekomme 1 also stimmt ja.

Sende ich dann relay=2# dann bekomme uch den wert 21 zurück. Sende ich 
relay=5# dann bekomme ich 521 zurück. schon komisch sende ich relay=0# 
dann ändert sich nichts und ich bekomme den alten wert wieder also 521.

von (prx) A. K. (prx)


Lesenswert?

Du hast das abschliessende 0-Byte vergessen.

von Daniel (Gast)


Lesenswert?

ok hab den fehler gefunden.

Bei atoi müssen die anderen Zeichen alle " " blanks sein damit es geht. 
Hatte bevor ich den Code hier gepostet hatte immer eine 0 davor gemacht.

Aber warum findet man die Fehler immer so schnell wenn man hier ein 
Beitrag auf gemacht hat. Hab gestern 2 Stunden daran rum probiert ohne 
erfolg.

von Floh (Gast)


Lesenswert?

Daniel schrieb:
> while(fifo[pfifo] != '#')
>   {
>     value[pvalue] = fifo[pfifo];
>
>     pvalue++;
>     pfifo++;
>
>     if(pvalue > 5)
>       return false;
>   }

lösch mal pvalue vor dieser Schleife (also nullsetzen).
Das könnte auf das beschriebene Verhalten führen.

von Fabian (Gast)


Lesenswert?

Hatte ich auch eben erst gedacht, ob pvalue ist in der Funktion privat 
und diese wird nur einmal durchlaufen. Beim starten wird es ja null 
gesetzt.

von Karl H. (kbuchegg)


Lesenswert?

Daniel schrieb:

> Jemand eine Idee?

Ja.

Punkt 1
   Wenn du Schwierigkeiten hast, weil du nicht weißt, was in einer
   Variablen drinnensteht, dann musst du dir Einblick in die Variable
   verschaffen. Das kann sein ein Debugger, das kann aber auch sein
   dass man sich ganz einfach ein paar Ausgabeanweisungen kurzfristig
   einbaut, die einem zeigen was Sache ist
   In deinem Fall möchtest du gerne wissen, was in value drinnen
   steht.
   Na dann mach dir doch eine send_uart( value) und schau nach was
   drinnen steht!

Punkt 2
   Deine Funktion macht viel zu viel!
   Wenn du einen Fifo hast, dann bau dir Funktionen, die sich um die
   Fifo Verwaltung kümmern. Nicht mehr!
   Aufbauend auf diesen Funktionen baust du dann weitere Funktionen
   auf, die zb einen String aus dem Fifo rauskopieren. Funktionen die
   Einzelteile aus dem String extrahieren etc. Lauter Dinge, die du
   einzeln testen kannst (indem du dir zb das Ergebnis über UART
   ausgeben lässt)
   Und erst dann, wenn du einen entsprechenden Baukasten hast, setzt
   du mit diesen Funktionen deinen Command Line Parser zusammen.

Punkt 3
   Kauf dir ein C Buch. Lerne wie String Verarbeitung in C funktioniert
   und welche Funktionen du fix&fertig zur Verfügung hast und setze
   sie auch ein!

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Punkt 4
•Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
Und Code Tags verwenden ;)

von Wolfgang Horn (Gast)


Lesenswert?

Daniel schrieb:
> Aber warum findet man die Fehler immer so schnell wenn man hier ein
> Beitrag auf gemacht hat. Hab gestern 2 Stunden daran rum probiert ohne
> erfolg.

Hi, Daniel,

„Eine gute wissenschaftliche Theorie sollte einer Bardame erklärbar 
sein.“ (Ernest Rutherford)

Gelegentlich hilft es schon, wenn ich mein Problem für meine Bardame 
formuliere :-).

Im Rückblick - wenn ich mich abgemüht habe mit eigentlich simplen 
Problemen, war nicht das Problem das Problem, sondern ein Denkfehler.
Banal, nicht wahr? Genauer gesagt, ein Fehler in der Suchstrategie.

Ärzte sollen davon auch nicht ganz frei sein.

Ciao
Wolfgang Horn

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.