Created
April 1, 2013 14:50
-
-
Save reagent/5285359 to your computer and use it in GitHub Desktop.
String Calculator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
calc | |
*.o | |
*.dSYM |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <string.h> | |
#include "calculator.h" | |
int is_numeric(char *n); | |
int | |
main(int argc, char *argv[]) | |
{ | |
if (argc != 3) { | |
fprintf(stderr, "Usage: calc <number> <number>\n"); | |
return 1; | |
} | |
if (!is_numeric(argv[1])) { | |
fprintf(stderr, "Error: First argument must be a number\n"); | |
return 1; | |
} | |
if (!is_numeric(argv[2])) { | |
fprintf(stderr, "Error: Second argument must be a number\n"); | |
return 1; | |
} | |
if (!add_print(argv[1], argv[2])) { | |
fprintf(stderr, "Error: could not add values\n"); | |
return 1; | |
} | |
return 0; | |
} | |
int | |
is_numeric(char *n) | |
{ | |
int i, | |
success = 1, | |
length = strlen(n); | |
success = success && (length > 0); | |
for (i = 0; i < length; i++) { | |
success = success && (n[i] >= '0' && n[i] <= '9'); | |
} | |
return success; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <strings.h> | |
#include <errno.h> | |
#include <stdarg.h> | |
#include "calculator.h" | |
#define check_mem(P) if (!P) { goto error; } | |
#define check(C) if (!(C)) { goto error; } | |
size_t max_length(char *first, ...); | |
int int_value(char n); | |
char add_digits(int a1, int a2, int *c); | |
char * pad(char *number, size_t width, char pad); | |
char * | |
add(char *n1, char *n2) | |
{ | |
int v1, v2, ri, | |
carry = 0, | |
done = 0, | |
i1 = strlen(n1) - 1, | |
i2 = strlen(n2) - 1; | |
size_t max = max_length(n1, n2, NULL); | |
char * result = pad(NULL, max + 1, ' '); | |
ri = max; // set index to space before terminating NUL | |
while (!done && ri > 0) { | |
v1 = v2 = 0; | |
if (i1 >= 0) { | |
v1 = int_value(n1[i1]); | |
check(v1 >= 0); | |
} | |
if (i2 >= 0) { | |
v2 = int_value(n2[i2]); | |
check(v2 >= 0); | |
} | |
result[ri] = add_digits(v1, v2, &carry); | |
ri--; | |
i1--; | |
i2--; | |
if (i1 < 0 && i2 < 0) { done = 1; } | |
} | |
if (carry > 0) { | |
result[ri] = ('0' + carry); | |
} | |
return result; | |
error: | |
free(result); | |
return NULL; | |
} | |
int | |
add_print(char *n1, char *n2) | |
{ | |
char *v1 = NULL, | |
*v2 = NULL, | |
*div = NULL, | |
*result = add(n1, n2); | |
check_mem(result); | |
size_t width = max_length(result, n1, n2, NULL); | |
v1 = pad(n1, width, ' '); | |
check_mem(v1); | |
v2 = pad(n2, width, ' '); | |
check_mem(v2); | |
div = pad(NULL, (width + 1), '-'); | |
check_mem(div); | |
printf(" %s\n+%s\n%s\n %s\n", v1, v2, div, result); | |
free(result); | |
free(v1); | |
free(v2); | |
free(div); | |
return 1; | |
error: | |
if (result) { free(result); } | |
if (v1) { free(v1); } | |
if (v2) { free(v2); } | |
if (div) { free(div); } | |
return 0; | |
} | |
size_t | |
max_length(char *first, ...) | |
{ | |
size_t max = strlen(first); | |
va_list ap; | |
char *next; | |
va_start(ap, first); | |
while ((next = va_arg(ap, char*)) != NULL) { | |
if (strlen(next) > max) { max = strlen(next); } | |
} | |
va_end(ap); | |
return max; | |
} | |
int | |
int_value(char n) | |
{ | |
int result; | |
errno = 0; | |
result = strtol(&n, NULL, 10); | |
if (result == 0 && errno != 0) { | |
result = -1; | |
} | |
return result; | |
} | |
char | |
add_digits(int a1, int a2, int *c) | |
{ | |
int sum = a1 + a2 + *c, | |
r = sum % 10; | |
*c = sum / 10; | |
return ('0' + r); | |
} | |
char * | |
pad(char *number, size_t width, char pad) | |
{ | |
char *out = calloc(width + 1, sizeof(char)); | |
int oi = width - 1, | |
ni = -1; | |
if (out == NULL) { goto error; } | |
memset(out, pad, width); | |
if (number) { ni = strlen(number) - 1; } | |
while (ni >= 0) { | |
out[oi] = number[ni]; | |
ni--; | |
oi--; | |
} | |
return out; | |
error: | |
return NULL; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef _CALCULATOR_H | |
#define _CALCULATOR_H | |
char * add(char *n1, char *n2); | |
int add_print(char *n1, char *n2); | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CFLAGS=-g -Wall -Wextra | |
all: calc | |
calc: calculator.o | |
clean: | |
rm -rf calc *.o *.dSYM |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment