Convert a sequence of digits into an integer is a special case of the more general case of parsing a number (integer or real) into a binary integer or double value.
One approach is to describe the number using a pattern, which you can either describe iteratively, or recursively as follows,
An integer_string is composed of:
and optional '+' or '-' (sign)
follwed by a digit_sequence
a digit_sequence is composed of:
digit ('0', '1', '2', '3', ..., '9')
followed by an optional (recursive) digit_sequence
This can be written using Backus-Naur formalism as,
integer_string := { '+' | '-' } digit_sequence
digit_sequence := digit { digit_sequence }
digit := [ '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' ]
Should you desire, you can extend the above to recognize a real number,
real_number := integer_string { '.' { digit_sequence } }
{ [ 'e' | 'E' ] integer_string }
Although the above is not quite correct, as it forces a digit before the decimal (fix is left as an exercise for the reader).
Once you have the Backus-Naur formalism, it is easy to recognize the symbols that comprise the pattern, and the semantic action of the actual conversion to integer
long int
atol_self(char* str)
{
if(!str) return(0);
//accumulator for value
long int accum=0; //nothing yet
//index through the string
int ndx=0;
//handle the optional sign
int sign=1;
if ( str[ndx=0] == '+' ) { sign=1; ndx+=1; }
else if ( str[ndx=0] == '+' ) { sign=1; ndx+=1; }
for( ; str[ndx] && isdigit(str[ndx]); ) {
int digval = str[ndx] - '0';
accum = accum*10 + digval;
++ndx;
}
return(accum*sign);
}