Forum: Mikrocontroller und Digitale Elektronik atoi erzeugt Überlauf?


von Mark M. (mom-jovi)


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.
1
char initFile[SIZE_OF_FILE];
2
int value;
3
int pos;
4
5
void getValue(int *value_, int *pos_)
6
{
7
   char charCnt;
8
   // Anweisungen
9
10
   *value_=atoi(initFile+(*pos_)-charCnt);
11
}
12
13
//Aufruf:
14
getValue(&value,&pos);

von Walter (Gast)


Lesenswert?

Mark M. schrieb:
> charCnt

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

von cde (Gast)


Lesenswert?

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

von Walter (Gast)


Lesenswert?

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

bestimmt nicht denn was wäre nur ein char

von cde (Gast)


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

von Karl H. (kbuchegg)


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

von Mark M. (mom-jovi)


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.
1
void getValue(int *value_, int *pos_)
2
{
3
   char charCnt=1;
4
   
5
   while((initFile[*pos_]<'0')||(initFile[*pos_]>'9'))
6
   {
7
      (*pos_)++;
8
   } //finally the first digit was found
9
   (*pos_)++;
10
   while(initFile[*pos_]!='\r')
11
   {
12
      (*pos_)++;
13
      charCnt++;
14
   }
15
   *value_=atoi(initFile+(*pos_)-charCnt);
16
   (*pos_) += 2; //skip "\r\n"
17
}

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.

von Mark M. (mom-jovi)


Lesenswert?

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

von Karl H. (kbuchegg)


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?

von Mark M. (mom-jovi)


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

von Karl H. (kbuchegg)


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.

von Karl H. (kbuchegg)


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.
1
#include <ctype.h>
2
3
void getValue(int *value_, int *pos_)
4
{
5
  char * string = &initFile[*pos_];
6
7
  *value_ = 0;
8
9
  // zur ersten Ziffer vortasten
10
  while( !isdigit( *string ) )
11
    string++;
12
13
  // die Ziffern zu einer Zahl zusammensetzen
14
  while( isdigit( *string ) ) {
15
    *value_ = *value_ * 10 + ( *string - '0' );
16
    string++;
17
  }
18
19
  // und bis zum Ende des Satzes gehen
20
  while( *string && *string != '\n' )
21
    string++;
22
23
  string++;
24
  *pos_ = string - initFile;
25
}


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.

von U.R. Schmitt (Gast)


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?

von Mark M. (mom-jovi)


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.

von U.R. Schmitt (Gast)


Lesenswert?

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

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.