I am learning C. As a task, I need to write a get_int
function that will convert a char*
to int
. What parts can I improve here? I'm especially interested in how I can improve/rewrite the overflow checking.
#include <stdio.h>
#include <ctype.h>
#include <limits.h>
#define MINIUNIT_MAIN
// https://github.com/urin/miniunit/blob/master/miniunit.h
#include "miniunit.h"
int get_int(char *string) {
int i = 0;
while (isspace(string[i])) {
i++;
}
char sign = string[i] == '-' ? '-' : '+';
if (string[i] == '-' || string[i] == '+') {
i++;
}
int result = 0;
while (string[i] != '\0' && isdigit(string[i])) {
// Check for overflow
if (INT_MIN / 10 > result || (INT_MIN / 10 == result && INT_MIN % 10 >= -(string[i] - '0'))) {
return sign == '-' ? INT_MIN : INT_MAX;
}
result = result * 10 - (string[i] - '0');
i++;
}
return sign == '-' ? result : -result;
}
int main(void) {
test_case("Simple numbers", {
expect("0", get_int("0") == 0);
expect("1", get_int("1") == 1);
expect("12", get_int("12") == 12);
expect("199", get_int("199") == 199);
expect("1000", get_int("1000") == 1000);
expect("214748364", get_int("214748364") == 214748364);
expect("214748500", get_int("214748500") == 214748500);
});
test_case("Invalid input", {
expect("Empty string", get_int("") == 0);
expect("Spaces", get_int(" ") == 0);
expect("Spaces and numbers", get_int(" 123") == 123);
expect("Plus sign", get_int("+") == 0);
expect("Minus sign", get_int("-") == 0);
expect("Letters", get_int("abc") == 0);
expect("Letters and numbers", get_int("123abc") == 123);
expect("Dot and numbers", get_int("123.4") == 123);
});
test_case("Negative numbers", {
expect("-0", get_int("-0") == 0);
expect("-1", get_int("-1") == -1);
expect("-5", get_int("-5") == -5);
expect("-12", get_int("-12") == -12);
expect("-1000", get_int("-1000") == -1000);
});
test_case("Overflows", {
expect("INT_MAX", get_int("2147483647") == INT_MAX);
expect("INT_MAX + 1", get_int("2147483648") == INT_MAX);
expect("INT_MAX + 10", get_int("2147483657") == INT_MAX);
expect("INT_MAX + 1000", get_int("2147484647") == INT_MAX);
expect("INT_MIN", get_int("-2147483648") == INT_MIN);
expect("INT_MIN - 1", get_int("-2147483649") == INT_MIN);
expect("INT_MIN - 10", get_int("-2147483658") == INT_MIN);
expect("INT_MIN - 1000", get_int("-2147484648") == INT_MIN);
});
}
const char*
\$\endgroup\$isspace(0)
to returnfalse
in one loop, and then carefully protect against testingisdigit(0)
in the next \$\endgroup\$