/* intbase.c Inputs and displays integer values in selected bases. - input bases are decimal, octal, hexadecimal. - display bases are decimal, octal, hexadecimal, and binary. A solution to CS 12 assignment 1, fall 2008 cmc, updated 9/24/08 */ /* include allowable libraries */ #include #include /* declare allowable functions from stdio.h */ int getchar(void); int puts(char[]); int putchar(int); /* NO OTHER #include OR LIBRARY FUNCTION DECLARATIONS ARE ALLOWED */ #define MAXCHARS 34 /* maximum length of value string, in chars */ /* enumeration constants to identify menu choices */ enum choice { enter, decimal, octal, hex, binary, quit }; /* prototypes for required functions */ enum choice menu(void); int getInteger(void); void putDecimal(int value); void putOctal(int value); void putHex(int value); void putBinary(int value); /* optional: any other function prototypes */ void putValue(int value, int base, char baseName[]); void putString(char s[]); void itob(int value, char s[], int base); void reverse(char s[]); /* implement main, followed by the other functions */ int main(void) { int value = 0; enum choice selection = menu(); while (selection != quit) { switch (selection) { case enter: value = getInteger(); break; case decimal: putDecimal(value); break; case octal: putOctal(value); break; case hex: putHex(value); break; case binary: putBinary(value); break; default: puts("invalid choice - menu function needs fixing"); return 1; } selection = menu(); } puts("\nBye!"); return 0; } /* gets choice from user */ enum choice menu(void) { int selection = 0; while (selection < 1 || selection > 6) { int c; puts("\nChoices are:"); puts(" 1 - Enter a new integer"); puts(" 2 - Display decimal value"); puts(" 3 - Display octal value"); puts(" 4 - Display hexadecimal value"); puts(" 5 - Display binary value"); puts(" 6 - Quit"); puts("\nEnter choice (1-6)"); selection = getchar() - '0'; for (c = selection; c != '\n'; c = getchar()) ; /* flush rest of line from input */ if (selection < 1 || selection > 6) puts("\ninvalid choice"); } if (selection == 1) return enter; if (selection == 2) return decimal; if (selection == 3) return octal; if (selection == 4) return hex; if (selection == 5) return binary; return quit; } /* gets an integer from user - can be entered as decimal, octal, or hexadecimal constant - octal starts with '0' then this subset of digits: [0-7] - hexadecimal starts with '0x' or '0X' then any digits or [A-F,a-f] - skips leading white space, then reads to end of number - result is 0 if number is not the first thing entered - much of the algorithm is from K&R atoi function, p. 61 */ int getInteger(void) { int result = 0, sign; char c; puts("\nEnter an integer constant"); c = getchar(); while (c != '\n' && isspace(c)) /* skip white space */ c = getchar(); if ( !(isdigit(c) || c == '-' || c == '+') ) { puts("integer not entered correctly - value set to 0"); while (c != '\n') c = getchar(); /* flush rest of input line */ return 0; } sign = (c == '-') ? -1 : 1; if (c == '-' || c == '+') /* skip sign */ c = getchar(); if (c == '0') { c = getchar(); if (c == 'x' || c == 'X') { /* entering hexadecimal constant */ c = getchar(); while (isxdigit(c)) { result *= 16; if (isdigit(c)) result += c - '0'; else result += 10 + toupper(c) - 'A'; c = getchar(); } result = sign * result; putHex(result); } else { /* entering octal constant */ while (isdigit(c) && c != '8' && c != '9') { result = 8 * result + c - '0'; c = getchar(); } result = sign * result; putOctal(result); } } else { /* entering decimal constant */ while (isdigit(c)) { result = 10 * result + c - '0'; c = getchar(); } result = sign * result; putDecimal(result); } while (c != '\n') c = getchar(); /* flush rest of input line */ return result; } /* print decimal value of parameter */ void putDecimal(int x) { putValue(x, 10, "decimal"); } /* print octal value of parameter */ void putOctal(int x) { putValue(x, 8, "octal"); } /* print hexadecimal value of parameter */ void putHex(int x) { putValue(x, 16, "hexadecimal"); } /* print binary value of parameter */ void putBinary(int x) { putValue(x, 2, "binary"); } /* prints the value of x in the specified base */ void putValue(int x, int base, char baseName[]) { char s[MAXCHARS]; itob (x, s, base); putString(baseName); putString(" value is "); putString(s); putchar('\n'); } /* prints the string one char at a time, without a newline */ void putString(char s[]) { int i; for (i = 0; s[i] != '\0'; i++) putchar(s[i]); } /* converts n to characters in s, conforming to base b slight variation of K&R itoa function, p. 64 */ void itob(int n, char s[], int b) { int i, j, sign; void reverse(char s[]); if ((sign = n) < 0) /* record sign */ n = -n; /* make n positive */ i = 0; do { /* generate digits in reverse order */ j = n % b; /* get next digit */ s[i++] = (j <= 9) ? j + '0' : j + 'a' - 10; } while ((n /= b) > 0); /* delete it */ if (sign < 0) s[i++] = '-'; s[i] = '\0'; reverse(s); } /* reverse string s in place (used by itob) verbatim from K&R, p. 62 */ void reverse(char s[]) { int c, i, j; for (i = 0, j = strlen(s)-1; i < j; i++, j--) { c = s[i]; s[i] = s[j]; s[j] = c; } }