[Edit]
Except for the behavior on error, atoi()
is equivalent to (int)strtol(nptr, (char **)NULL, 10)
. strtol()
accepts leading white space. OP's my_atoi(char* pointer)
does not. To remedy:
int my_atoi(const char* pointer) {
while (isspace((unsigned char) *pointer)) {
pointer++;
}
...
The below does describe a good way to handle INT_MIN
.
OTOH, handing values outside [INT_MIN...INT_MAX]
is is not defined by the C spec, so some simplifications can be had. See far below.
When a string represents INT_MIN
, (let's assume 32-bit int
) such as "-2147483648"
, code runs into int
overflow attempting to get to calculate 2147483648
. A simple way to solver this is rather than finding the positive value and then negating it, embrace the negative side of things. By doing the lion share of the math in the INT_MIN
to 0
range, we avoid UB. Down-side: some find this approach more challenging to follow.
Going to a wider integer or unsigned
it not always possible as the integer size of "text--> integer" routine may be the maximum size. Strictly speaking unsigned
does not always have a wider positive range than int
. In any case, all the math can be handled at the desired signed integer size without resorting to other types.
#include <ctype.h>
#include <limits.h>
int my_atoi(const char* pointer) { // good idea to make the `const`
int result = 0;
while (isspace((unsigned char) *pointer)) {
pointer++;
}
char sign = *pointer;
if (*pointer == '-' || *pointer == '+') { // text could lead with a '+'
pointer++;
}
int ch;
// isdigit() expects an unsigned char or EOF, not char
while ((ch = (unsigned char)(*pointer)) != 0) {
if (!isdigit(ch)) break;
ch -= '0';
// Will overflow occur?
if ((result < INT_MIN/10) ||
(result == INT_MIN/10 && ch > -(INT_MIN%10))) Handle_Overflow();
result *= 10;
result -= ch; // - , not +
pointer++;
}
if (sign != '-') {
if (result < -INT_MAX) Handle_Overflow();
result = -result;
}
return result;
}
Notes:
pointer%48
is confusing. What is special about 48? If you mean '0'
, then use pointer % '0'
.
"string: "232-19". What should I do then?" Recommend stopping conversion at "232" and returning the value 232. Could set errno
, but the typical atoi()
function does not do too much error handling.
On overflow, setting errno
, could happen, but again, typical atoi()
function does not do too much error handling. Suggest simple returning INT_MAX
or INT_MIN
.
If you want better error handling, change to something like the following and set an error status.
int my_atoi(const char *s, int *ErrorCode);
or location where things ended. If this are good, they ended at the '\0'
.
int my_atoi(const char *s, const char **endptr);
[Edit] Simplified: Removed out-of-range detection as C spec allows that. "If the value of the result cannot be represented, the behavior is undefined.
int my_atoi(const char* pointer) {
int result = 0;
while (isspace((unsigned char) *pointer)) {
pointer++;
}
char sign = *pointer;
if (*pointer == '-' || *pointer == '+') {
pointer++;
}
while (isdigit((unsigned char)*pointer)) {
result = result*10 - (*pointer++ - '0');
}
if (sign != '-') {
result = -result;
}
return result;
}