From 8131295c044eae68de2eb7465384edd56838dc4a Mon Sep 17 00:00:00 2001 From: tomsmeding Date: Sun, 5 Jun 2016 23:36:35 +0200 Subject: First --- Makefile | 15 +++++ number | Bin 0 -> 13512 bytes number.c | 189 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 204 insertions(+) create mode 100644 Makefile create mode 100755 number create mode 100644 number.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..2b814d4 --- /dev/null +++ b/Makefile @@ -0,0 +1,15 @@ +CC = gcc +CFLAGS = -Wall -Wextra -O2 -std=c11 -fwrapv +BIN = number + +.PHONY: all clean remake + +all: $(BIN) + +clean: + rm -f $(BIN) + +remake: clean all + +$(BIN): $(wildcard *.c *.h) + $(CC) $(CFLAGS) -o $@ $(filter %.c,$^) diff --git a/number b/number new file mode 100755 index 0000000..ee06277 Binary files /dev/null and b/number differ diff --git a/number.c b/number.c new file mode 100644 index 0000000..27df086 --- /dev/null +++ b/number.c @@ -0,0 +1,189 @@ +#include +#include +#include +#include +#include + +__attribute__((noreturn)) void usage(int argc,char **argv){ + (void)argc; + fprintf(stderr, + "Usage: %s [-co] \n" + "Converts a number to (British) English word form.\n" + "Currently supports only integers.\n" + " -c Capitalise the first output letter\n" + " -o Write as ordinal (first) instead of cardinal number (one)\n", + argv[0]); + exit(1); +} + +char *thousands[6]={"thousand","million","billion","trillion","quadrillion","quintillion"}; +char *twenty[20]={ + "zero","one","two","three","four","five","six","seven","eight","nine","ten", + "eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen" +}; +char *tens[10]={ + "zero","ten","twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety" +}; + +char *ordtwenty[20]={ + "zeroth","first","second","third","fourth","fifth","sixth","seventh","eighth","ninth","tenth", + "eleventh","twelfth","thirteenth","fourteenth","fifteenth","sixteenth","seventeenth","eighteenth","nineteenth" +}; +char *ordtens[10]={ + "zeroth","tenth","twentieth","thirtieth","fortieth","fiftieth","sixtieth","seventieth","eightieth","ninetieth" +}; + +void addtobuf(char *text,char **buf){ + int len=strlen(text); + strcpy(*buf,text); + *buf=*buf+len; +} + +char* printnumber(intmax_t num,char *buf){ + if(num<0){ + addtobuf("minus ",&buf); + num=-num; + } + + bool hadth=false; + if(num>=1000){ + hadth=true; + intmax_t th[6],nth=0,rest; + rest=num%1000; + num/=1000; + while(num){ + th[nth++]=num%1000; + num/=1000; + } + bool first=true; + while(nth-->0){ + if(th[nth]==0)continue; + if(!first)addtobuf(" ",&buf); + buf=printnumber(th[nth],buf); + addtobuf(" ",&buf); + addtobuf(thousands[nth],&buf); + first=false; + } + num=rest; + if(num==0)return buf; + addtobuf(" ",&buf); + } + + bool and=(num>=100||hadth)&&num%100!=0; + if(num>=100){ + buf=printnumber(num/100,buf); + addtobuf(" ",&buf); + addtobuf("hundred",&buf); + num%=100; + if(num)addtobuf(" ",&buf); + else return buf; + } + + if(and)addtobuf("and ",&buf); + + if(num%10==0)addtobuf(tens[num/10],&buf); + else if(num<20)addtobuf(twenty[num],&buf); + else { + addtobuf(tens[num/10],&buf); + addtobuf("-",&buf); + addtobuf(twenty[num%10],&buf); + } + return buf; +} + +char* printordinal(intmax_t num,char *buf){ + if(num<0){ + addtobuf("minus ",&buf); + num=-num; + } + + bool hadth=false; + if(num>=1000){ + hadth=true; + buf=printnumber(num/1000*1000,buf); + num%=1000; + if(num==0){ + addtobuf("th",&buf); + return buf; + } + addtobuf(" ",&buf); + } + + if(hadth&&num/100==0&&num%100!=0)addtobuf("and ",&buf); + + if(num<20){ + addtobuf(ordtwenty[num],&buf); + return buf; + } + + if(num<100){ + if(num%10==0)addtobuf(ordtens[num/10],&buf); + else { + addtobuf(tens[num/10],&buf); + addtobuf("-",&buf); + addtobuf(ordtwenty[num%10],&buf); + } + return buf; + } + + buf=printnumber(num/100*100,buf); + if(num%100==0){ + addtobuf("th",&buf); + return buf; + } + addtobuf(" and ",&buf); + return printordinal(num%100,buf); +} + +int main(int argc,char **argv){ + char *numstr=NULL; + bool ordinal=false,capfirst=false; + for(int i=1;i