ASCII to Integer, a2i

advertisement
CS 162
Introduction to Computer Science
Chapter 5
ASCII to Integer Conversion
Herbert G. Mayer, PSU
Status 11/9/2014
1
Syllabus
 #include <stdio.h> for getchar()
 Convert Decimal Digits to int
 Account for Sign
 Check integer Overflow on 16-Bit
 Maxint on 32-Bit
2
Specify a2i() Conversion
 Reading one input char at a time, assuming the
character is a decimal digit ‘0’..’9’
 Convert this ASCII string of decimal digits to its
corresponding integral value
 For example, the incoming string “123” is converted
to the integer hundred-and-twenty-three, i.e. 12310
 Be aware that this input is indeed a sequence of
ASCII character, not an integer value
 So we have to convert the digit ‘5’ for example to the
integer value 5, by subtracting from character ‘5’ the
value character ‘0’, and the difference is 5
 Int value of ‘5’ is: ‘5’ – ‘0’
3
Implement a2i() Conversion
int a2i( void )
{ // a2i
int number = 0;
while( ( ( c = getchar() ) >= '0' ) && ( c <= '9' ) ) {
number = number * 10 + ( c - '0' );
} //end while
return number;
} //end a2i
int main()
{ // main
cout << “Enter a decimal number: ” << endl;
cout << "The number was:” << a2i() << endl;
return 0;
} //end main
4
Discuss Code for a2i() Conversion
 The assumption in the code is that a sequence of
decimal digits can be read
 However, if not a single digit is entered, the correct
result of 0 is generated, due to initialization of
number; see “int number = 0;”
 A crucial test is: ( c = getchar() ) >= '0' ...
 Here a side-effect happens: A character is read from
standard in, and it is tested. Test becomes more
complex, but no further input happens
 The current number is shifted left by 1 decimal
position (multiply by 10) and the digit value is added
5
Account for Sign in a2i()
 Before reading one decimal digit at a time, check for
optional negative sign ‘-’ or a redundant positive
sign ‘+’
 Former ‘-’ will change the resulting value, by
inverting the sign
 State of ‘-’ has to be remembered; see variable neg
 The latter ‘+’ is silently skipped
 Once the sign is handled, proceed as before with the
decimal digits that make the number
6
Implement Sign in a2i()
int is_digit( char c )
{ // is_digit
return ( c >= '0' ) && ( c <= '9' );
} //end is_digit
int a2i0( void )
{ // a2i0
int number = 0;
int neg
= 0;
if ( c == '-' ) {
neg = 1;
c = getchar();
}else if ( c == '+' ) {
c = getchar();
} //end if
while ( is_digit( c ) ) {
number = number * 10 + ( c - '0' );
c = getchar();
} //end while
return neg ? -number : number;
} //end a2i0
7
Discuss Sign in a2i
 State variable neg is solely used to determine at the
end, whether sign inversion happens
 Here we us a conditional expression:
return neg ? -number : number;
 For the initial state of neg = 0, the decimal computed
so far is returned
 But if neg is set to a non-zero state, the sign is
inverted, all accomplished in a single conditional
expression
 Note separation of the 2 options via the : and ?
operators!
8
Specify Overflow in a2i() on 16-Bit
 Delicate programming matter, analyzed by sample of
a fictitious 16-bit architecture
 On 16-bit computer the largest possible integer =
32767
 On a two’s-complement architecture, the largest
negative value = -32768
 Both cases have to be handled, without the overflow
actually occurring, so we probe the growing integer
value, before the next multiply by 10, MAX10 = 3276
 Also track, whether scanning a negative int literal, in
which case the largest next decimal digit for 3276 is
8, versus the positive literal, for which largest next
decimal digit fir 3276 is 7
9
Specify Overflow in a2i() on 16-Bit
 Scanning a positive decimal int literal:




If number scanned so far is less than 3276, which is max
32767 / 10, then scanning 1 more digit is safe, do
number = number * 10 + ( c-'0’ );
But if number scanned so far is in critical range 3276, then
only some digits are safe, namely ‘0’..’7’
Else there will be positive overflow
 Scanning a negative decimal int literal:




If number scanned so far is less than 3276, which is max
32767 / 10, then scanning 1 more digit is safe, do
number = number * 10 + ( c-'0’ );
But if number scanned so far is in critical range 3276, then
only some digits are safe, namely ‘0’..’8’
Else there will be negative overflow
10
Check for Overflow in a2i()
#define MAX
32767
#define MAX10 3276
// i.e. integer divide 32767 / 10 = 3276
. . .
int a2i1( void )
{ // a2i
int number = 0;
int neg
= 0;
if ( c == '-' ) {
neg = 1;
c = getchar();
}else if ( c == '+' ) {
c = getchar();
// keep neg = 0
} //end if
while ( is_digit( c ) ) {
if ( number > MAX10 ) {
printf( "Overflow 1. max = %d\n", MAX );
}else if ( number == MAX10 ) {
if ( c == '9' ) {
printf( "Overflow 2. max = %d\n", MAX );
}else if ( c == '8' ) {
if ( neg ) {
number = -32768;
}else{
printf( "Overflow 3. max = %d\n", MAX );
} //end if
}else{
number = number * 10 + ( c - '0' );
} //end if
}else{
number = number * 10 + ( c - '0' );
} //end if
c = getchar();
} //end while
return neg ? -number : number;
} //end a2i
11
Discuss Overflow in a2i
 The critical number = number * 10 + next digit is
performed only in safe state:
 For positive state, if the next digit after 3276 is ‘0’..’7’
one more iteration of the multiply is safe; yielding <=
32767
 For negative state, if the next digit after 3276 is
‘0’..’8’ one more iteration of the multiply is safe;
yielding >= -32768
 Similarly on a 32-bit or today’s 64-bit computer; the
scanner for integer literals needs to be safe, and
detect integer overflow before it happens
 Common to have computers ignore integer overflow,
so it may be safe to simply experience it, but the
numeric value has to be safely scanned
12
Maxint on 32-Bit
#include <iostream.h>
main()
{ // main
int expo;
// shift 1 32 times
unsigned long int pow = 1; // multiply repeatedly by 2
for ( expo = 1; expo <= 32; expo++ ) {
pow = pow * 2;
cout << " 2**" << expo << " = " << pow-1 << endl;
} // end for
cout << 0+4294967295 << endl;
cout << 0-4294967295 << endl;
} //end main
13
Maxint Output
2**1 = 1
2**2 = 3
2**3 = 7
. . .
2**14 = 16383
2**15 = 32767
2**16 = 65535
2**17 = 131071
2**18 = 262143
2**19 = 524287
2**20 = 1048575
2**21 = 2097151
2**22 = 4194303
2**23 = 8388607
2**24 = 16777215
2**25 = 33554431
2**26 = 67108863
2**27 = 134217727
2**28 = 268435455
2**29 = 536870911
2**30 = 1073741823
2**31 = 2147483647
2**32 = 4294967295
4294967295
1
14
Download