Offtopic: Ori suntem atoi ori nu mai suntem!0ptr wrote:Mi se pare o cretinitate sa discuti de wchar_t cand e vorba de atoi() dar sunt convins ca exista specimene ce-si pun problema asta.

Offtopic: Ori suntem atoi ori nu mai suntem!0ptr wrote:Mi se pare o cretinitate sa discuti de wchar_t cand e vorba de atoi() dar sunt convins ca exista specimene ce-si pun problema asta.
Hai sa nu exageram cu limbajul.0ptr wrote:Mi se pare o cretinitate sa discuti de wchar_t cand e vorba de atoi() dar sunt convins ca exista specimene ce-si pun problema asta.
Sorry!Marius Bancila wrote:
Hai sa nu exageram cu limbajul.0ptr wrote:Mi se pare o cretinitate sa discuti de wchar_t cand e vorba de atoi() dar sunt convins ca exista specimene ce-si pun problema asta.
Code: Select all
int my_atoi(const char* p)
{
int result = 0;
char sign;
while(isspace(*p)) /* skip witespace */
{
p++;
}
sign = *p; /* store sign */
if((sign == '+') || (sign == '-'))
{
p++; /* skip sign */
}
while(isdigit(*p))
{
result = 10 * result + *p - '0';
p++; /* next digit */
}
return (sign == '-') ? -result : result;
}
...atat si-o dunga... cei mai multi ar "uita" partea cu "skip witespace". Pe langa acestia, multi s-ar apuca voiniceste de testat daca nu cumva argumentu-i NULL, daca nu cumva rezulta overflow si alte jmecherii pe care atoi-ul original (ca si alte functii C standard) nu le face.0ptr wrote:scrieti codul ce implementeaza functia C int atoi(const char* pChar).
Code: Select all
while(isdigit(*p))
{
result = 10 * result + *p - '0';
p++; /* next digit */
}
Code: Select all
unsigned int d;
while(*p && (d = *p -'0') < 10)
{
result = 10 * result +d;
p++; /* next digit */
}
Desigur, daca vrem, o putem "cripta" cat de tare vrem.null wrote:Bucla:ar putea fi scrisa ca:Code: Select all
while(isdigit(*p)) { result = 10 * result + *p - '0'; p++; /* next digit */ }
reducand numarul de operatii in plus prin folosirea lui isdigit().Code: Select all
unsigned int d; while(*p && (d = *p -'0') < 10) { result = 10 * result +d; p++; /* next digit */ }
Fara misto, m-am racit gura (se pare, cel putin pana acum) aici spunand "specificatii".xxscorp wrote:Fara misto nici din partea mea, sa presupunem ca se foloseste acel atoi intr-un aparat de radioterapie, sa citeasca user input-ul (adica de la tehnician) si sa calculeze doza. Sau ca sa fiu si mai rau, sa calculeze atenuarea aplicata cu un scut in calea radiatiilor. Ii dau programului lui 42 urmatorul input: 5000000042. Cred ca ar fi frumos sa dea acel INT_MAX (2147483647 deci), insa el imi da voiniceste 705032746. Fukushima frate!
Observati ca nu am zis nimic de whitespace, isdigit sau alte chichite si chichineturi (cam lame de altfel) care se pot specifica si verifica mai mult sau mai putin usor, am gasit insa un bug mult mai subtil si mai greu de depistat chiar si in acel cod "trivial". Daca era insa mai complex, nu prea as fi avut sanse sa-l pot gasi si... go figure!
P.S. Exemplul cu aparatul de radioterapie l-am dat pentru ca au fost in realitate cazuri de erori de programare (de fapt era combinatie de design al aparatului si de eroare de programare) care s-au soldat si cu decese parca.
Am pornit de la "atoi" si-am ajuns la "atoi42".xxscorp wrote:Eu zic asa: daca nu faci ceva si spui asta - e ok. Daca faci insa, fa-o bine!
Problema e ca atoi42 face test de overflow, dar nu il face bine. Si problema mare e ca nu greseste decat uneori, si atunci cand greseste o face tacut si subtil (da rezultat gresit, nu crapa, nu tipa).
De asta m-am referit la varianta lui si nu am zis nimic de celelalte implementari (care nu fac testul deloc si despre care s-au spus deja destule).
Daca inteleg eu bine, se da mana libera celui care le implementeaza sa faca sau sa nu faca verificari gen overflow. Sau mai degraba sugereaza sa nu faca.The functions atof, atoi, atol, and atoll need not affect the value of the integer
expression errno on an error. If the value of the result cannot be represented, the
behavior is undefined.
Code: Select all
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
int main()
{
// Note: under VS2005 this prints "Overflow", while under VS6.0 prints "Ok".
const char* p = "9223372036854775808"; // _I64_MAX + 1
__int64 res = _atoi64(p);
if(ERANGE == errno)
{
if((_I64_MAX == res) || (_I64_MIN == res))
{
printf("Overflow");
}
}
else
{
printf("Ok");
}
return 0;
}
Mi-ai luat vorba de pe limba. Apreciez faptul ca intrebarea mea a strarnit atata interes si s-a ajuns la discutii tot mai detaliate. Sunt convins ca foarte multi interievatori ar fi multumiti cu toate implementarile propuse.Marius Bancila wrote:Am impresia ca s-a plecat de la o intrebare de interviu si s-a ajuns la un requirement de functie de biblioteca.