First commit
This commit is contained in:
commit
12f8b73077
5 changed files with 113 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
*.o
|
||||
baseconv_example
|
16
Makefile
Normal file
16
Makefile
Normal file
|
@ -0,0 +1,16 @@
|
|||
BIN = baseconv_example
|
||||
OBJS = baseconv.o main.o
|
||||
|
||||
all: $(BIN)
|
||||
|
||||
$(BIN): $(OBJS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS)
|
||||
|
||||
main.o: baseconv.h
|
||||
|
||||
clean:
|
||||
rm -f $(BIN) $(OBJS)
|
||||
|
||||
distclean: clean
|
||||
|
||||
.PHONY: all clean distclean
|
47
baseconv.c
Normal file
47
baseconv.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
static const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
bool baseconv(char outbuf[], size_t bufsize, unsigned base, uintmax_t num) {
|
||||
// Supported bases are 2 to 36 inclusive (though it could be higher
|
||||
// if our digits string was longer
|
||||
if (base < 2 || base > 36)
|
||||
return false;
|
||||
|
||||
// Longest possible converted string is base-2, where we produce one
|
||||
// character per bit of input, so if we size the buffer to fit it we
|
||||
// can fit any converted string
|
||||
char buf[sizeof(uintmax_t) * CHAR_BIT];
|
||||
|
||||
// Place the digits in the buffer in a little-endian order
|
||||
size_t len = 0;
|
||||
while (num) {
|
||||
char digit = digits[num % base];
|
||||
buf[len++] = digit;
|
||||
num /= base;
|
||||
}
|
||||
|
||||
// Special case: if the original input was zero, previous loop ran
|
||||
// zero times, and there is nothing in the buffer. Place a single
|
||||
// zero there.
|
||||
if (!len)
|
||||
buf[len++] = digits[0];
|
||||
|
||||
// Can the output buffer hold the converted string as well as the
|
||||
// null terminator?
|
||||
if (!bufsize || bufsize - 1 < len)
|
||||
return false;
|
||||
|
||||
// Copy the digits to the output buffer, reversing the order
|
||||
for (size_t i = 0; i < len; i++)
|
||||
outbuf[i] = buf[len - 1 - i];
|
||||
|
||||
// Null-terminate
|
||||
outbuf[len] = '\0';
|
||||
|
||||
return true;
|
||||
}
|
1
baseconv.h
Normal file
1
baseconv.h
Normal file
|
@ -0,0 +1 @@
|
|||
bool baseconv(char outbuf[], size_t bufsize, unsigned base, uintmax_t num);
|
47
main.c
Normal file
47
main.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "baseconv.h"
|
||||
|
||||
int main(void) {
|
||||
uintmax_t num;
|
||||
printf("Number? ");
|
||||
if (scanf("%ju", &num) != 1) {
|
||||
fprintf(stderr, "Invalid input\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned base;
|
||||
printf("Base? ");
|
||||
if (scanf("%u", &base) != 1) {
|
||||
fprintf(stderr, "Invalid input\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t bufsize;
|
||||
printf("Buffer size? ");
|
||||
if (scanf("%zu", &bufsize) != 1) {
|
||||
fprintf(stderr, "Invalid input\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *buf = malloc(bufsize);
|
||||
if (!buf) {
|
||||
fprintf(stderr, "Failed to allocate %zu bytes\n", bufsize);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!baseconv(buf, bufsize, base, num)) {
|
||||
fprintf(stderr, "Conversion error\n");
|
||||
free(buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("%s\n", buf);
|
||||
|
||||
free(buf);
|
||||
}
|
Loading…
Reference in a new issue