First commit

This commit is contained in:
Juhani Krekelä 2022-11-20 06:52:54 +02:00
commit 12f8b73077
5 changed files with 113 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.o
baseconv_example

16
Makefile Normal file
View 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
View 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
View File

@ -0,0 +1 @@
bool baseconv(char outbuf[], size_t bufsize, unsigned base, uintmax_t num);

47
main.c Normal file
View 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);
}