atoi gibt mir unerwartete Werte aus
-
Hi
ich will aus einer textdatei einen Wert auslesen, also einen integer wert. Dieser soll von einem anderen programm hochgezaehlt werden, damit ich erkennen kann ob das programm(welches den wert hochzaehlt) noch lauft oder haengt.
Alles soweit kein problem. Das mit dem hochzaehlen mach ich von hand um zu testen ob meine funktion zum auslesen richtig funktioniert. Was mir aufgefallen ist, dass atoi() mir bei zu großen bzw. zu kleinen werten irgendwelche werte ausgibt.(also werte die ausserhalb von INT_MAX und INT_MIN liegen) eigentlich sollte atoi bei diesen faellen INT_MAX bzw. INT_MIN zurueck geben, das tut es aber nicht und ich versteh nicht warum.
hier meine funktion zum auslesen:
FILE *lifeRequest; char *lifeRequestPath = "h:\\remote\\scheduler\\lebt noch.txt"; char intString[12]; int stringValue=-1; lifeRequest = fopen( lifeRequestPath, "r" ); if( lifeRequest != NULL ) { //position of the first charakter of the lifeRequest Counter fseek( lifeRequest, 79, SEEK_SET ); for( int i=0 ; i<12 ; i++ ) { intString[i] = fgetc( lifeRequest ); if( intString[i] == '\n' ) { stringValue = atoi( intString ); break; }else if( i == 11 && intString[i-1] != '\n' ) { stringValue = atoi( intString ); break; } } fclose( lifeRequest ); return stringValue; }else { return -1; }
Damit rufe ich die funktion auf und ueberpruefe den rueckgabewert
die funktion heisst lifeRequest()int r = -123; int puffer; while(1) { wait_s(3); //hier wird nur 3 sekunden gewartet puffer = lifeRequest(); if( (puffer != 0 || puffer != -1) && puffer != r ) { r = puffer; printf("\nlebt noch!!! %d\n",puffer); }else if( puffer == 0 || puffer == -1 ) { printf("\ngeht nicht!!! %d\n",puffer); }else { printf("\ner ist tot!!! %d\n",puffer); } }
-
Kläre mit einem Debugger folgende Fragen:
Um welches atoi geht es?
Welchen Wert hat intString zu dem Zeitpunkt?
Wie ermittelst Du, dass der Rückgabewert von atoi ausserhalb INT_MIN,INT_MAX liegt (was technisch eigentlich schon garnicht gehen kann)?
Ist intString nullterminiert?Vermutlich hast Du die Lösung danach schon (um die Funktion selbst durchzuarbeiten habe ich gerade keine Lust).
-
erstmal danke für die schnelle antwort
ich habe rausgefunden was das problem war.
atoi macht garnicht das, was ich dachte.hierher weis ich wie atoi funktioniert
http://www.cplusplus.com/reference/clibrary/cstdlib/atoi.html
Return Value
....
If the correct value is out of the range of representable values, INT_MAX or INT_MIN is returned.damit ist gemeint, wenn der übergebene wert ausserhalb vom wertebereich von integer liegt, dann wird INT_MAX oder INT_MIN zurückgegeben.
das stimmt aber garnicht. Bei mir hat atoi einfach sozusagen weitergezählt und es entstand dadurch ein überlauf. Wenn mann natürlich bei dem Wert INT_MAX eins weiter zählt ist man durch den überlauf bei INT_MIN
aber das ist was anderes als es bei cplusplus.com beschrieben ist.Liegt das eventuell an der version von visual c++ 6.0 oder was habe ich übersehen?
-
blechtrommler schrieb:
das stimmt aber garnicht. Bei mir hat atoi einfach sozusagen weitergezählt und es entstand dadurch ein überlauf.
wenn mich nicht alles täuscht, ist der rückgabewert von 'atoi' implementation-defined, wenn der string zu lang ist. d.h. du müsstest den string vorher zurechtstutzen, z.b. auf die maximale anzahl der dezimalstellen (mit vorzeichen?) von 'int' beschneiden.
-
das bringt leider nichts. Der überlauf hat nichts mit der länge des strings zu tun, ok vielleicht indirekt, wichtig sind die ersten ziffernkette in dem string, wobei vorstehende leerzeichen ignoriert werden und das vorzeichen wird natürlich auch noch interpretiert.
um den überlauf zu vermeiden müsste man den int wert der ersten ziffernkette dieses strings kennen befor man ihn atoi übergibt, aber gerade das ist ja der haken an der sache.
es würde zwar gehen, dass ich schaue, ob die einzelnen charakter in gewissen
konstelationen INT_MAX überschreiten und das dann in irgeneiner form behandeln,
aber dafür müsste man ja schauen, für jede länge bis zur maximallänge von ich glaube 11 zeichen(wenn man das vorzeichen mit nimmt), ob der string immernoch in dem bereich ist und entsprechende maßnahmen treffenwas besserer fällt mir da nicht ein, aber so ein "if else grab" will ich eigentlich vermeiden
-
wenn dein atoi zickt, dann mach dir doch selber ein 'atoi'. das geht ganz einfach: *neuer_wert = vorheriger_wert 10 + aktuelles_zeichen-'0' damit hast du dann alle möglichkeiten.
-
~fricky schrieb:
wenn dein atoi zickt, dann mach dir doch selber ein 'atoi'. das geht ganz einfach: *neuer_wert = vorheriger_wert 10 + aktuelles_zeichen-'0' damit hast du dann alle möglichkeiten.
aso jetzt versteh ich wieso es einen überlauf bei atoi gibt, wenn der integer mit dieser formel berechnet wird ist das ja klar.
naja, dann muss ich mal schauen, wie lange das programm laufen soll und ob es überhaupt schlimm ist, wenn es einen überlauf gibt :D, dann muss ich das einfach bei der abfrage berücksichtigen
oh man, viel wind um (fast)nichts...
danke, wenigstens wieder was dazugelernt