Browse Source

Initial commit

main
human.equivalent 4 years ago
parent
commit
7dcf978b8c
  1. 2
      Makefile
  2. 260
      hexcalc.c

2
Makefile

@ -0,0 +1,2 @@
build:
gcc -Wall -pedantic hexcalc.c

260
hexcalc.c

@ -0,0 +1,260 @@
#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;
}
Loading…
Cancel
Save