K&Rを読もう(37) 演習3-4 - 3-6 itoa
今回は数値を文字列に変換する問題。
演習 3-4
サンプルのitoaはINT_MINの値が正しく処理出来ない。何故か&修正せよ。
まず、INT_MAX,INT_MINの値を確認する。
INT_MAX 2147483647 01111111111111111111111111111111 INT_MIN -2147483648 10000000000000000000000000000000
すると、INT_MIN * -1をすると、数値がオーバーフローしてしまう事がわかる。知らなかった・・・。
正しく表示させるには、正の処理、負の処理は別々に処理する必要がある。
void itoa(int n, char s[], int size) { int i = 0; if (n >= 0) { do s[i++] = n % 10 + '0'; while ((n /= 10) > 0 && size - 1); } else { do s[i++] = -(n % 10) + '0'; while ((n /= 10) < 0 && size - 1); s[i++] = '-'; } s[i] = '\0'; reverse(s); }
演習 3-5
符号なし整数を任意の基数変換をする。36進数まで対応してみた。
void itob (unsigned int n, char s[], int size, int b) { int i = 0; int c; if (b > 'Z' - 'A' + 1 + 10) exit(EXIT_FAILURE); do { c = (n % b); s[i++] = c + ((c < 10) ? '0' : 'A' - 10); } while ((n /= b) > 0 && i < size - 1); s[i] = '\0'; reverse(s); }
演習 3-6
itoaを右詰めにする。
void itoa2(int n, char s[], int size, int field) { int i, len; itoa(n, s, size); len = strlen(s); if (len > field || field > size) exit(EXIT_FAILURE); s[field + 1] = '\0'; for (i = len; i >= 0; i--) s[field - len + i] = s[i]; for (i = 0; i < field - len; i++) s[i] = ' '; }
itoaを利用して文字列を作って、地道に右に詰めてみた。
フィールド幅が足りないときはエラーにした。