You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
260 lines
5.9 KiB
260 lines
5.9 KiB
#include <stdio.h> |
|
#include <string.h> |
|
#include <stdlib.h> |
|
#include <ctype.h> |
|
|
|
/* THIS IS A WORK IN PROGRESS. |
|
* |
|
* This is my first program in C and I look forward to learning more and making |
|
* those changes as I go along. Feedback is appreciated, for example -Wall and |
|
* -pedantic (see Makefile) were very appreciated. |
|
* |
|
* I'm not looking for perfection. |
|
* |
|
* The goal is to later maybe putting this into an ATTiny or Atmega328 and put |
|
* it into some hardware. Just for fun with a display and inputs and stuff. |
|
* |
|
* What I learned writing this: |
|
* - Internet searches return pretty unhelpful stuff |
|
* - ... but I found out that there is something called ispunct, isupp, isalnum |
|
* and a lot of other helpful functions that are part of the C standard |
|
* library. If the validation thing even is something I want. |
|
* - but trying to find out what I wanted about these were harder, |
|
* then I remember I have manpages installed - but how do I find them? man |
|
* stdlib.h, stdio.h and string.h didn't have anything, but man ispunct lead |
|
* me to man ctype.h where I found everything I needed. |
|
* |
|
* TODO/Need to look into: |
|
* - Freeing memory after use |
|
* - Use valgrind |
|
* - Look for null pointers and stuff |
|
* - Read about pointers |
|
* - Padding for binary number output |
|
* - Padding for decimal output |
|
* - Decimal to hex converter |
|
* - Other things mentioned in the code |
|
*/ |
|
|
|
#define LINE 20 |
|
|
|
// declare functions - guess these should go into a header file? |
|
// the error messages I got before putting this here were not helpful. |
|
char* validate_input(char*); |
|
char* to_hex(char*); |
|
int hex_to_decimal(char*, char*, int); |
|
char* to_binary(unsigned int, char*); |
|
char* binary_string(char*, char*); |
|
int binary_to_decimal(char*, char*); |
|
|
|
char hex[4]; // 4 characters (ff ff) |
|
int bin[8]; // 8 digits (1111 1111) |
|
int dec[5]; // 5 digits (65 535) |
|
|
|
int main() { |
|
char* buffer = malloc(LINE+1); |
|
char buf2[17]; |
|
char buf3[LINE+1]; |
|
int i; |
|
int ch; |
|
|
|
printf("Enter a number and this program will convert the number to decimal, hexadecimal \n"); |
|
printf("and binary.\n"); |
|
|
|
while (1) { |
|
printf("\n> "); |
|
|
|
for (i = 0; (i < LINE) && (( ch = getchar()) != EOF) && (ch !='\n'); i++) |
|
buffer[i] = ch; |
|
|
|
buffer[i] = '\0'; |
|
int size = i; |
|
|
|
if (buffer[0] == '\0') |
|
break; |
|
|
|
//printf("Given string was: '%c'\n", *test); |
|
|
|
char *test = validate_input(buffer); |
|
int in_decimal; |
|
char *in_binary; |
|
|
|
in_decimal = hex_to_decimal(buffer, buf2, size); |
|
in_binary = to_binary(in_decimal, buf2); |
|
printf("%s as hex:\n", buffer); |
|
printf("decimal> %i\n", in_decimal); |
|
printf("binary> %s\n", binary_string(in_binary, buf3)); |
|
printf("\n"); |
|
|
|
if (*test == 'd') { |
|
printf("%s as decimal:\n", buffer); |
|
in_binary = to_binary(atoi(buffer), buf2); |
|
printf("hex> \n"); |
|
printf("binary> %s\n", binary_string(in_binary, buf3)); |
|
} |
|
|
|
if (*test == 'b') { |
|
printf("%s as binary:\n", buffer); |
|
int binary_in_decimal = binary_to_decimal(buffer, buf2); |
|
printf("hex> \n"); // TODO: Convert binary to hex |
|
printf("decimal> %i\n", binary_in_decimal); |
|
} |
|
|
|
free(test); |
|
} |
|
|
|
printf("Exiting program.\n"); |
|
|
|
return 0; |
|
} |
|
|
|
char* binary_string(char* in_binary, char* buffer) { |
|
int j = 0; // for padding |
|
for (int i = 0; i < 16; i++) { |
|
buffer[i] = (int) in_binary[i]; |
|
} |
|
buffer[17] = '\0'; |
|
|
|
return buffer; |
|
} |
|
|
|
// TODO: |
|
//char* to_hex(char* input) { |
|
//} |
|
|
|
int hex_to_decimal(char* input, char *buff, int size) { |
|
char *pbuff = buff; |
|
int newbuff[8]; |
|
int newbuff_used; |
|
|
|
char *ch = input; |
|
ch += size; |
|
|
|
*pbuff = 1; |
|
|
|
// TODO: Shouldn't have to do this. Look into atoi()? |
|
// 0=48 |
|
// a=97 |
|
for (int i = 0; i < LINE; i++) { |
|
*ch--; |
|
if (*ch == '\0') { |
|
break; |
|
} |
|
if (*ch >= 97) { |
|
int tmp = *ch - 87; |
|
newbuff[i] = tmp; |
|
} else { |
|
newbuff[i] = *ch - 48; |
|
} |
|
newbuff_used = i+1; |
|
} |
|
|
|
int result = 0; |
|
int exp; |
|
for (int i = 0; i < newbuff_used; i++) { |
|
exp = i; |
|
|
|
while (exp > 0) { |
|
newbuff[i] *= 16; |
|
--exp; |
|
} |
|
|
|
result += newbuff[i]; |
|
} |
|
|
|
return result; |
|
} |
|
|
|
char* to_binary(unsigned int input, char *buff) { |
|
char *pbuff = buff; |
|
|
|
int size = 16; |
|
|
|
pbuff += size; |
|
*pbuff-- = '\0'; |
|
|
|
for (int i = 0; i < size; i++) { |
|
*pbuff-- = ((input & 1) == 1) ? '1' : '0'; |
|
|
|
input >>= 1; |
|
|
|
} |
|
return pbuff+1; |
|
} |
|
|
|
int binary_to_decimal(char* input, char *buff) { |
|
char *pbuff = input; |
|
|
|
int size = strlen(input); |
|
printf("size: %i\n", size); |
|
int result = 0; |
|
|
|
pbuff += size; |
|
int exp = 1; |
|
|
|
for (int i = 0; i < size; i++) { |
|
*pbuff--; |
|
|
|
int val = (int) *pbuff; |
|
val -= 48; // TODO: Shouldn't have to do this. Look into atoi()? |
|
|
|
result += val * exp; |
|
|
|
exp *= 2; |
|
} |
|
|
|
return result; |
|
} |
|
|
|
// returns b for binary, h for hex, d for decimal or e for error |
|
char* validate_input(char* input) { |
|
int b_count = 0; // binary |
|
int h_count = 0; // hex (hexadecimal) |
|
int d_count = 0; // decimal (alphanumerical) |
|
int a_count = 0; // letters (alpha) |
|
int length = 0; |
|
|
|
int i; |
|
char *ret = malloc(1); |
|
|
|
for (i = 0; i < 8; i++) { |
|
if (input[i] == '\0') { |
|
printf("\n"); |
|
break; |
|
} |
|
|
|
if (input[i] == '0' || input[i] == '1') |
|
b_count++; |
|
|
|
if (isdigit(input[i])) |
|
d_count++; |
|
|
|
if (isalpha(input[i])) |
|
a_count++; |
|
|
|
if (isxdigit(input[i])) { |
|
h_count++; |
|
} else { |
|
printf("%c error\n", input[i]); |
|
ret[0] = 'e'; |
|
return ret; |
|
} |
|
|
|
length++; |
|
} |
|
|
|
// if it contains letters it's not binary and not a decimal |
|
if (a_count == 0) |
|
ret[0] = 'd'; |
|
|
|
// Hex is written in groups of 2, like ff or 0afe, not fad. |
|
if (a_count != 0 && length == h_count && (h_count == 2 || h_count == 4)) |
|
ret[0] = 'h'; |
|
|
|
// Binary is written in groups of 2 (or 4), like 10, 11, 1011 and 0100, not 1 or 101. |
|
if (a_count == 0 && length == b_count && (b_count % 2 == 0)) |
|
ret[0] = 'b'; |
|
|
|
//printf("%-1c: %d d, %d h, %d b, %d length\n\n", ret[0], d_count, h_count, b_count, length); |
|
|
|
return ret; |
|
}
|
|
|