Code:
/* convert_binary.c
* Sat Aug 20 17:23:52 EDT 2005
*
* A program which accepts an unsigned
* long integer input from the user
* and then 'converts' the number
* to a binary output.
* The default mode is to display
* the binary number with the least
* amount of bits necessary to represent
* the number. For example, assuming 8 bit
* chars, the number 8 given as input would
* be displayed as 00001000
* Optionally, the user can choose to display
* the same number in 16 bit, 32 bit, or 64 bit
* (provided the machine is a 64 bit architecture).
* As an example, the number 8 displayed as a 16 bit
* number would be 0000000000001000
* The extra bits are 'padding' bits.
* For the default mode, the user can also choose
* to display only the relevant bits, and not the
* padding bits. For example, the number 8 would
* be displayed as
* 1000
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
static unsigned int getint(void);
static unsigned long int get_long_int(void);
static int *char_to_bin(int output[], unsigned long int input);
static int *short_to_bin(int output[], unsigned long int input);
static int *int_to_bin(int output[], unsigned long int input);
static int *long_to_bin(int output[], unsigned long int input);
static void fflush_stdin(void);
int main(void)
{
enum {
ARR_MAX = 100
};
int bin_arr[ARR_MAX] = { 2 };
int i;
long int number;
int num_display_bits;
int chg_default_mode;
int display_padding_bits;
int *p_no_padding; /* The *_to_bin functions return a pointer to the first
* '1' in the array 'bin_arr' - store that return value
* into *p_no_padding
*/
printf("\n\t\tDecimal to Binary\n");
printf("\t\t-----------------\n\n");
printf("\tThis program accepts an unsigned value\n");
printf("\tfrom the user, and converts it to either a 8,\n");
printf("\t16, 32, or 64 bit value (for those who have a 64 \n");
printf("\tbit machine.)\n\n");
printf
("\tThe default mode is to display the minimum amount of \n");
printf
("\tbits necessary to represent the number. You may choose \n");
printf
("\tto display the binary output in a different manner.\n\n");
printf("\tEnter a number to convert to binary output: ");
(void) fflush(stdout);
number = get_long_int();
printf("\tChange from the default mode (Y or N)?: ");
(void) fflush(stdout);
chg_default_mode = getchar();
fflush_stdin();
if (chg_default_mode == 'Y' || chg_default_mode == 'y') {
printf
("\n\tselect the number of bits you wish to display: ");
(void) fflush(stdout);
do {
(void) puts("\n\n\t1. Display 8 bits (char)");
(void) puts("\t2. Display 16 bits (short)");
(void) puts("\t3. Display 32 bits (int)");
(void) puts("\t4. Display 64 bits (long)");
printf("\n\tEnter your selection (1-4) <ENTER>: ");
(void) fflush(stdout);
} while ((num_display_bits = getint()) < 0 && number > 4);
switch (num_display_bits) {
case 1:
char_to_bin(bin_arr, number);
break;
case 2:
short_to_bin(bin_arr, number);
break;
case 3:
int_to_bin(bin_arr, number);
break;
case 4:
long_to_bin(bin_arr, number);
break;
default:
(void) puts("You have problems....");
break;
}
/* The following code is used only if the user chooses not to use the
* default and display all of the bits, i.e., the user chooses to
* use a 8, 16, 32 or 64 bit mode - we obviously will display all
* of the padding bits if the user chooses not to go with the default
* mode.
*/
printf
("\n\tYou entered %ld which would be displayed in binary as: \n\n",
number);
printf("\t");
(void) fflush(stdout);
for (i = 0; bin_arr[i] >= 0; i++) {
printf("%d", bin_arr[i]);
}
(void) puts("\n\n");
return 0;
} else {
/* The following deals with 'default mode', i.e., the user chose
* not to deviate from the default. What happens then is that the
* number the user entered is tested agains the various macros from
* limits.h, and then the appropriate function is called accordingly.
*/
if (number < UCHAR_MAX) {
p_no_padding = char_to_bin(bin_arr, number);
} else if (number < USHRT_MAX) {
p_no_padding = short_to_bin(bin_arr, number);
} else if (number < UINT_MAX) {
p_no_padding = int_to_bin(bin_arr, number);
} else {
p_no_padding = long_to_bin(bin_arr, number);
}
}
/* Assuming the user decides not to deviate from the default, we then
* offer the choice to display all of the bits, or only the bits necessary
* to properly represent the number entered
*/
if (chg_default_mode == 'N' || chg_default_mode == 'n') {
printf
("\tWould you like to display all of the available bits\n");
printf
("\t(i.e., leading 0's, or 'padding' bits) (Y or N)?: ");
fflush(stdout);
display_padding_bits = getchar();
fflush_stdin();
if (display_padding_bits == 'N'
|| display_padding_bits == 'n') {
printf
("\n\tYou entered %ld which would be displayed in binary as: \n\n",
number);
printf("\t");
(void) fflush(stdout);
while (*p_no_padding != -1) {
printf("%d", *p_no_padding);
p_no_padding++;
}
(void) puts("\n\n");
} else {
printf
("\n\tYou entered %ld which would be displayed in binary as: \n\n",
number);
printf("\t");
(void) fflush(stdout);
for (i = 0; bin_arr[i] >= 0; i++) {
printf("%d", bin_arr[i]);
}
(void) puts("\n\n");
}
}
return 0;
}
static unsigned int getint(void)
{
enum {
BUF_MAX = 15
};
char buffer[BUF_MAX] = { (char) 0 };
char *p;
int number = 0;
if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
perror("fgets()");
exit(EXIT_FAILURE);
}
if ((p = strchr(buffer, '\n')) != NULL) {
*p = '\0';
}
if ((sscanf(buffer, "%d", &number)) != 1) {
(void) puts("Error: call to sscanf() failed");
exit(EXIT_FAILURE);
}
return number;
}
static unsigned long int get_long_int(void)
{
enum {
BUF_MAX = 15
};
char buffer[BUF_MAX] = { (char) 0 };
char *p;
long int number = 0;
if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
perror("fgets()");
exit(EXIT_FAILURE);
}
if ((p = strchr(buffer, '\n')) != NULL) {
*p = '\0';
}
if ((sscanf(buffer, "%ld", &number)) != 1) {
(void) puts("Error: call to sscanf() failed");
exit(EXIT_FAILURE);
}
return number;
}
/* The *_to_bin functions, as the names suggest, perform
* the work of 'converting' an unsigned integer into a
* binary format. All four of the functions are identical
* except for the types, which are unsigned char, unsigned
* short, unsigned int, and unsigned long respectively. The
* comments which document the char_to_bin function will serve
* equally well for the others. Basically the number the user
* entered is sent to one of the functions, where it is converted
* using bitmasks - the resulting 1's and 0's are stored into the array
* 'output[]' which is also passed to the functions.
*/
static int *char_to_bin(int output[], unsigned long int input)
{
typedef unsigned char unsigned_char_t;
unsigned_char_t mask;
int i = 0;
int *p;
enum {
SET = 1,
NOT_SET = 2
};
int flag = NOT_SET; /* The 'flag' variable is used to set a switch
* so we can find the first '1' in the 'output[]'
* array. The reason for the 'flag' is that we
* need to know the position of the first one, so
* so we can assign it to 'p' and then return it
* to the calling function, which will use it to
* print out the binary number with no padding
* bits.
*/
mask = -1; /* all 1 bits : 1......1 */
mask /= 2; /* leading 0 : 01.....1 */
mask++; /* high bit only : 10.....0 */
while (mask != 0) {
output[i] = 0 + !!(input & mask);
if (flag == NOT_SET && output[i] == 1) { /* If its the first time we have
* seen a '1', take note, and then
* set the flag
*/
p = &output[i];
flag = SET;
}
mask >>= 1;
i++;
}
output[i] = -1;
return p;
}
static int *short_to_bin(int output[], unsigned long int input)
{
typedef unsigned short int unsigned_short_integer_t;
unsigned_short_integer_t mask;
int i = 0;
int *p;
enum {
SET = 1,
NOT_SET = 2
};
int flag = NOT_SET;
mask = -1;
mask /= 2;
mask++;
while (mask != 0) {
output[i] = 0 + !!(input & mask);
if (flag == NOT_SET && output[i] == 1) {
p = &output[i];
flag = SET;
}
mask >>= 1;
i++;
}
output[i] = -1;
return p;
}
static int *int_to_bin(int output[], unsigned long int input)
{
typedef unsigned int unsigned_integer_t;
unsigned_integer_t mask;
int i = 0;
int *p;
enum {
SET = 1,
NOT_SET = 2
};
int flag = NOT_SET;
mask = -1;
mask /= 2;
mask++;
while (mask != 0) {
output[i] = 0 + !!(input & mask);
if (flag == NOT_SET && output[i] == 1) {
p = &output[i];
flag = SET;
}
mask >>= 1;
i++;
}
output[i] = -1;
return p;
}
static int *long_to_bin(int output[], unsigned long int input)
{
typedef unsigned long int unsigned_long_integer_t;
unsigned_long_integer_t mask;
int i = 0;
int *p;
enum {
SET = 1,
NOT_SET = 2
};
int flag = NOT_SET;
mask = -1;
mask /= 2;
mask++;
while (mask != 0) {
output[i] = 0 + !!(input & mask);
if (flag == NOT_SET && output[i] == 1) {
p = &output[i];
flag = SET;
}
mask >>= 1;
i++;
}
output[i] = -1;
return p;
}
static void fflush_stdin(void)
{
char junk[80];
fgets(junk, 80, stdin);
}
I never did have the knack for elegant code.