|
| 1 | +/* |
| 2 | + * Exercise 3-4. In a two's complement number representation, our version of |
| 3 | + * itoa does not handle the largest negative number, that is, the value of n |
| 4 | + * equal to -(2^wordsize-1). Explain why not. Modify it to print that value |
| 5 | + * correctly, regardless of the machine on which it runs. |
| 6 | + * |
| 7 | + * By Faisal Saadatmand |
| 8 | + */ |
| 9 | + |
| 10 | +/* |
| 11 | + * ANSWER: |
| 12 | + * In two's complement number representation, the range of values an int can |
| 13 | + * hold is from -(2^wordsize-1) to (2^wordsize-1)-1. The most significant bit |
| 14 | + * is the sign bit; however, it also holds a value for negative numbers; thus, |
| 15 | + * making the negative limit larger than the positive limit by a value of 1. |
| 16 | + * When we negate the largest negative number, -(2^wordsize-1), we get a number |
| 17 | + * that is equal to 2^wordsize-1, which is larger than the largest positive |
| 18 | + * number, (2^wordsize-1)-1. This will overflow a signed int and cause |
| 19 | + * unexpected results. To overcome this, we can use an unsigned int for n. The |
| 20 | + * check for whether n is negative or not is taking care of with the assigned |
| 21 | + * of n to the int variable sign, in which n is convert to a signed int. |
| 22 | + * |
| 23 | + * Alternatively, we could avoid negating n altogether and use the abs function |
| 24 | + * from stdlib.h to extract the digits. See 3-4a.c. |
| 25 | + */ |
| 26 | + |
| 27 | +#include <stdio.h> |
| 28 | +#include <stdlib.h> |
| 29 | +#include <string.h> |
| 30 | +#include <limits.h> |
| 31 | + |
| 32 | +#define MAXLEN 1000 |
| 33 | + |
| 34 | +void itoa(int, char []); |
| 35 | +void reverse(char []); |
| 36 | + |
| 37 | +/* itoa: convert n to characters in s--abs version */ |
| 38 | +void itoa(int n, char s[]) |
| 39 | +{ |
| 40 | + int i, sign; |
| 41 | + |
| 42 | + sign = n; |
| 43 | + i = 0; |
| 44 | + do { /* generate digits in revered order */ |
| 45 | + s[i++] = abs(n % 10) + '0'; /* get next digit */ |
| 46 | + } while ((n /= 10) != 0); |
| 47 | + if (sign < 0) |
| 48 | + s[i++] = '-'; |
| 49 | + s[i] = '\0'; |
| 50 | + reverse(s); |
| 51 | +} |
| 52 | + |
| 53 | +/* reverse: reverse the order of the characters in the string s */ |
| 54 | +void reverse(char s[]) |
| 55 | +{ |
| 56 | + int c, i, j; |
| 57 | + |
| 58 | + for (i = 0, j = strlen(s) - 1; i < j; ++i, --j) { |
| 59 | + c = s[i]; |
| 60 | + s[i] = s[j]; |
| 61 | + s[j] = c; |
| 62 | + } |
| 63 | +} |
| 64 | + |
| 65 | +int main(void) |
| 66 | +{ |
| 67 | + char str[MAXLEN]; |
| 68 | + |
| 69 | + itoa(0, str); /* do-while loop is necessary for 0 */ |
| 70 | + printf("%i -> %s\n", 0, str); |
| 71 | + itoa(INT_MAX, str); |
| 72 | + printf("%i -> %s\n", INT_MAX, str); |
| 73 | + itoa(INT_MIN, str); |
| 74 | + printf("%i -> %s\n", INT_MIN, str); |
| 75 | + return 0; |
| 76 | +} |
0 commit comments