www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik atoi erzeugt Überlauf?


Autor: Mark M. (mom-jovi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich lese aus einem String "initFile" eine Zahl, von der ich weiß, wo sie 
anfängt ( pos - charCnt ).

Jatzt habe ich folgendes Problem: Wenn im String z.B. 300 steht, dann 
wird value_ eine 45 zugewiesen. atoi erzeugt also aus der 300 scheinbar 
einen Überlauf, denn 45 ist ja genau die Differenz von einem char zu 
300. Aber atoi bedeutet doch ascii to integer? Was passiert hier, und 
wie löse ich das?
Mein Programm läuft auf einem MSP430.
char initFile[SIZE_OF_FILE];
int value;
int pos;

void getValue(int *value_, int *pos_)
{
   char charCnt;
   // Anweisungen

   *value_=atoi(initFile+(*pos_)-charCnt);
}

//Aufruf:
getValue(&value,&pos);

Autor: Walter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mark M. schrieb:
> charCnt

wird nirgends belegt, da ist übrigens auch eine Compilerwarnung 
gekommen!

Autor: cde (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> *value_=atoi(initFile+(*pos_)-charCnt);
Soll das initFile[*pos-charCnt] heissen?

Autor: Walter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
cde schrieb:
>> *value_=atoi(initFile+(*pos_)-charCnt);
> Soll das initFile[*pos-charCnt] heissen?

bestimmt nicht denn was wäre nur ein char

Autor: cde (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Walter schrieb:
> cde schrieb:
>>> *value_=atoi(initFile+(*pos_)-charCnt);
>> Soll das initFile[*pos-charCnt] heissen?
>
> bestimmt nicht denn was wäre nur ein char
Uuuups, atoi mit was anderem verwechselt... 
kleinmachundleisewegschleich

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mark M. schrieb:

> wie löse ich das?

Indem du erstmal mehr Information postest.

Wie sieht dein String beispielsweise aus?
Was steht dann in *pos, wenn die Funktion aufgerufen wird?
Und welche Bedeutung hat charCnt? Wie wird es bestimmt?


> void getValue(int *value_, int *pos_)
> {
>    char charCnt;
>    // Anweisungen

Dein Problem steckt höchst wahrscheinlich genau hier in diesem Bereich, 
den du so lapidar mit "Anweisungen" abtust

Autor: Mark M. (mom-jovi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Na gut. Ich glaube aber nicht, dass charCnt wichtig zum Verständnis ist, 
auch wenn ich recht wenig Ahnung habe. Damit wird einfach nur die 
Position bestimmt, wo die Zahl anfängt. Ich glaube, dass hat mit dem 
Fehler bei atoi nichts zu tun.
void getValue(int *value_, int *pos_)
{
   char charCnt=1;
   
   while((initFile[*pos_]<'0')||(initFile[*pos_]>'9'))
   {
      (*pos_)++;
   } //finally the first digit was found
   (*pos_)++;
   while(initFile[*pos_]!='\r')
   {
      (*pos_)++;
      charCnt++;
   }
   *value_=atoi(initFile+(*pos_)-charCnt);
   (*pos_) += 2; //skip "\r\n"
}

Ich merke gerade, dass ich den Schlunz vor atoi weglassen kann, wenn ich 
atoi nur initfile+(*pos_) übergebe... :D Aber ich muss ja auch so die 
Zeichen bis zum \r\n zählen.

Autor: Mark M. (mom-jovi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kurz:
Mich interessiert, warum mit
char initFile[SIZE_OF_FILE]={' ','=',' ','3','0','0','\r','\n'};
nach
getValue(&value,&pos);
value den Wert 45 hat.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Deine Funktion hat zwar das Zeug für den OCCC, ist aber 
überraschenderweise tatsächlich soweit richtig.
Wie sieht der Aufruf auf? Hast du vor dem Aufruf pos einen vernünftigen 
Wert gegeben?

Autor: Mark M. (mom-jovi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
pos hat den Wert des Index, an dem die Zahl beginnt. Wenn im String 
initFile nur 30 statt 300 steht, dann funktioniert es und value==30.

Und was ist OCCC? Ich weiß, dass man es nicht umständlicher machen 
könnte :D

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mark M. schrieb:
> pos hat den Wert des Index, an dem die Zahl beginnt. Wenn im String
> initFile nur 30 statt 300 steht, dann funktioniert es und value==30.

Hast du irgendwelche Compile-Warnings.

Wie gesagt: Dein Code ist zwar maximal kompliziert, aber nichts desto 
trotz soweit richtig, solange der String nicht zu lange ist und char für 
den Compiler nicht ein signed Datentyp ist und du die Funktion mit einem 
vernünftigen Wert in pos aufrufst.

> Und was ist OCCC? Ich weiß, dass man es nicht umständlicher machen
> könnte :D
OCCC  = Obfuscated C Code Contest
Ein Wettbewerb, in dem es darum geht, ein Programm möglichst trickreich 
und möglichst verschleiert zu schreiben. Sprich: alle Register zu 
ziehen.
ZB. ein komplettes Schachprogramm in 145 Zeichen oder so.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich weiß zwar nicht, was da beim atoi schief geht.
Aber im Grunde braucht den keiner. Ist hier sowieso kontraproduktiv, 
weil du so ein paar mal durch den String läufst. Das können wir besser. 
Unter anderem auch mit besseren Fehlerabfragen.
#include <ctype.h>

void getValue(int *value_, int *pos_)
{
  char * string = &initFile[*pos_];

  *value_ = 0;

  // zur ersten Ziffer vortasten
  while( !isdigit( *string ) )
    string++;

  // die Ziffern zu einer Zahl zusammensetzen
  while( isdigit( *string ) ) {
    *value_ = *value_ * 10 + ( *string - '0' );
    string++;
  }

  // und bis zum Ende des Satzes gehen
  while( *string && *string != '\n' )
    string++;

  string++;
  *pos_ = string - initFile;
} 


Ich weiß, am Anfang ist das nicht leicht. Aber du solltest dich 
schnellstens mit Pointern wenigstens soweit anfreunden, dass du damit 
Stringverarbeitung machen kannst. Die Sichtweise mit Array und Index 
erweist sich da nämlich sehr oft als sehr umständlich. Vor allen Dingen 
deshalb weil man eine Hilfsvariable braucht (die Indexvariable), von der 
man den Datentyp nicht vernünftig festlegen kann

Anstelle von

  for( i = 0; i < strlen(String); ++i )
    Zeichen = String[i];
    mach was mit Zeichen

ist es einfacher einen Pointer auf ein Zeichen nach dem anderen im 
String zeigen zu lassen

  while( *String )    // oder while( *String != '\0' )
    Zeichen = *String;
    String++;

    mach was mit Zeichen
  }

macht genau das gleiche. Nur brauch ich kein i und ich muss im Vorfeld 
auch nicht wissen wie lang der String ist.

Autor: U.R. Schmitt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Blöde Frage (hab schon 5 Jahre kein C mehr programmiert)
stört sich atoi() nicht an dem \r\n?
Und selbst wenn whitespaces weggeworfen werden, der String geht doch 
dahinter weiter. atoi erwartet doch ein normalen Stringabschluss, und 
sein initFile geht doch dann in der nächsten Zeile wohl weiter.
Oder bin ich jetzt verkehrt?

Autor: Mark M. (mom-jovi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
U.R. Schmitt schrieb:
> atoi erwartet doch ein normalen Stringabschluss, und
> sein initFile geht doch dann in der nächsten Zeile wohl weiter.
> Oder bin ich jetzt verkehrt?

Aber in der nächsten Zeile steht keine Zahl, sondern erstmal wieder 
Buchstaben, und die werden laut 
http://www.cppreference.com/wiki/string/c/atoi ignoriert.

Autor: U.R. Schmitt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, danke!
Sorry bin Java verseucht, da fliegt sofort ne exception wenn was 
Ungültiges drinsteht :-).

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]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [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.