As part of a (slightly) larger program, I needed to write a function that could take an arbitrarily large number and divide it by a small number. In this program, I will be dividing this number specifically by 2 or 5, but from my (rudimentary) testing, my function seems to work for larger divisors as well. All of the inputs in this function will be valid (they are checked before passed to this function in a different part of the program). A valid input is a non-negative, properly-represented number, things like: "123\0"
but not "-1000\0"
or "00100\0"
. So input validation is not necessarily to that extent.
#include <stdlib.h>
#include <string.h>
static inline int toNumber(char c) {
return c - '0';
}
static inline char toCharacter(int n) {
return n + '0';
}
char *divide(char *a, unsigned int divisor) {
int length = strlen(a);
char *quotient = malloc(length + 1);
if (quotient == NULL) {
return NULL;
}
int i, j;
int localDivident = 0;
for (i = 0, j = 0; i < length; i++) {
if (a[i] == '0' && localDivident == 0) {
quotient[j++] = '0';
} else {
if (localDivident != 0) {
localDivident = localDivident * 10 + toNumber(a[i]);
} else {
localDivident = toNumber(a[i]);
}
int localQuotient = localDivident / divisor;
if (localQuotient > 0) {
quotient[j++] = toCharacter(localQuotient);
localDivident -= localQuotient * divisor;
}
}
}
quotient[j++] = '\0';
char *resized = realloc(quotient, j);
return (resized == NULL) ? quotient : resized;
}
I have tested a variety of inputs and I have found that this function works surprisingly well, especially since I initially designed it with the intention of only handling single-digit divisors. However, I have found that it returns "\0"
when the divisor is greater than the numeric interpretation of the input string. For example, divide("8\0", 9)
returns "\0"
. One possible solution is adding a basic check like:
if (strtol(a, NULL, 10) < divisor) {
char *trivialQuotient = malloc(2);
if (trivialQuotient == NULL) {
return NULL;
}
trivialQuotient[0] = '0';
trivialQuotient[1] = '\0';
return trivialQuotient;
}
But I find this solution inelegant, especially since the added computation of strtol
will be pointless for the vast majority of executions, and I feel that there is a more elegant way for my algorithm to account for this scenario. I know that the line:
if (localQuotient > 0) {
is responsible for the result, but I could not think of a good way to modify it.
Also, I am torn between replacing the use of the static
inlined functions like toNumber
with a simple macro, like:
#define CTON(X) ((X) - '0')
I have read that the compiler may not always inline functions that are attributed with the inline
modifier, and I know that the function should be inlined, which is why I am considering just using the macro.
(Also, I am aware that this function returns memory allocated using malloc
which means that callers need to eventually free
it.)