nazerke
11/29/2019 - 7:00 AM

numbers to words program


// numword.h by Bill Weinman <http://bw.org/>
// version as of 2018-10-05
#ifndef _NUMWORD_H
#define _NUMWORD_H

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdint>
#include <cmath>
#include <new>

namespace bw {
    
    constexpr const char * _version = "2018.10.05";
    typedef uint64_t numnum;    // yummy numbers
    
    // _maxstr is max size of string
    constexpr size_t _maxstr = 1024;
    
    // _maxnum is nine hundred ninty-nine quadrillion nine hundred ninty-nine trillion nine hundred ninty-nine billion nine hundred ninty-nine million nine hundred ninty-nine thousand nine hundred ninty-nine
    constexpr numnum _maxnum = 999999999999999999;
    
    static const char * errnum = "error";
    
    static const char * _singles[] = {
        "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"
    };
    
    static const char * _teens[] = {
        "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"
    };
    
    static const char * _tens[] = {
        errnum, errnum, "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninty",
    };
    
    static const char * _hundred = "hundred";
    
    static const char * _powers[] = {
        errnum, "thousand", "million", "billion", "trillion", "quadrillion"
    };
    
    static const char * _hyphen = "-";
    static const char * _space = " ";
    
    class numword {
        numnum _num = 0;
        char * _buf = nullptr;
        size_t _buflen = 0;
        bool hyphen_flag = false;
        
        void clearbuf();
        void initbuf();
        void appendspace();
        void appendbuf(const char * s);
        
    public:
        numword() : _num(0) {}
        numword(const numnum & num) : _num(num) {}
        ~numword();
        const char * version() const { return _version; }
        void setnum(const numnum & num) { _num = num; }
        numnum getnum() const { return _num; }
        numnum operator = ( const numnum & num );
        const char * words();
        const char * words( const numnum & num );
        const char * operator () ( const numnum & num ) { return words(num); };
    };
    
}

#endif /* _NUMWORD_H */
// numword.cpp by Bill Weinman <http://bw.org/>
// version as of 2018-10-05
#include "numword.h"
using namespace bw;

// destructor
numword::~numword() {
    clearbuf();
}

// assignment operator
numnum numword::operator = ( const numnum & num ) {
    setnum(num);
    return getnum();
}

const char * numword::words() {
    return words(_num);
}

// convert to words
const char * numword::words( const numnum & num ) {
    if (num > _maxnum) {
        return errnum;
    }
    initbuf();
    numnum n = num;
    if (n == 0) {
        appendbuf(_singles[n]);
        return _buf;
    }
    
    // powers of 1000
    if (n >= 1000) {
        for(int i = 5; i > 0; --i) {
            numnum power = (numnum) pow(1000.0, i);
            numnum _n = ( n - ( n % power ) ) / power;
            if (_n) {
                int index = i;
                numword _nw(_n);
                appendspace();
                appendbuf(_nw.words());
                appendspace();
                appendbuf(_powers[index]);
                n -= _n * power;
            }
        }
    }
    // hundreds
    if (n >= 100 && n < 1000) {
        numnum _n = ( n - ( n % 100 ) ) / 100;
        numword _nw(_n);
        appendspace();
        appendbuf(_nw.words());
        appendspace();
        appendbuf(_hundred);
        n -= _n * 100;
    }
    // tens
    if (n >= 20 && n < 100) {
        numnum _n = ( n - ( n % 10 ) ) / 10;
        appendspace();
        appendbuf(_tens[_n]);
        n -= _n * 10;
        hyphen_flag = true;
    }
    // teens
    if (n >= 10 && n < 20) {
        appendspace();
        appendbuf(_teens[n - 10]);
        n = 0;
    }
    // singles
    if (n > 0 && n < 10) {
        appendspace();
        appendbuf(_singles[n]);
    }
    return _buf;
}

// MARK: - private methods

// reset the buffer
void numword::clearbuf() {
    if (_buf != nullptr) {
        delete [] _buf;
        _buf = nullptr;
    }
    _buflen = 0;
}

// initialize the buffer
void numword::initbuf() {
    clearbuf();
    try {
        _buf = new char[_maxstr];
        *_buf = 0;
        hyphen_flag = false;
    } catch (std::bad_alloc e) {
        printf("numword: cannot allocate buffer: %s\n", e.what());
    }
}

// append space (or hyphen)
void numword::appendspace() {
    if (_buflen) {
        appendbuf( hyphen_flag ? _hyphen : _space);
        hyphen_flag = false;
    }
}

// append text to the string buffer
void numword::appendbuf(const char * s) {
    if(!s) return;
    size_t slen = strnlen(s, _maxstr);
    if (slen < 1) {
        return;
    }
    if ((slen + _buflen + 1) >= _maxstr) {
        return;
    }
    memcpy(_buf + _buflen, s, slen);
    _buflen += slen;
    _buf[_buflen] = 0;
}
// numword-test.cpp by Bill Weinman <http://bw.org/>
// updated 2018-10-04
#include <cstdio>
#include "numword.h"
using namespace std;

int main() {
    bw::numword nw;
    uint64_t n;
    
    n = 3; printf("n is %lld, %s\n", n, nw.words(n));
    n = 47; printf("n is %lld, %s\n", n, nw.words(n));
    n = 73; printf("n is %lld, %s\n", n, nw.words(n));
    n = 1492; printf("n is %lld, %s\n", n, nw.words(n));
    n = 10012; printf("n is %lld, %s\n", n, nw.words(n));
    n = 100073; printf("n is %lld, %s\n", n, nw.words(n));
    n = 1000000; printf("n is %lld, %s\n", n, nw.words(n));
    n = 1000000001; printf("n is %lld, %s\n", n, nw.words(n));
    n = 123000000000; printf("n is %lld, %s\n", n, nw.words(n));
    n = 474142398123; printf("n is %lld, %s\n", n, nw.words(n));
    n = 1474142398007; printf("n is %lld, %s\n", n, nw.words(n));
    n = 999000000000000; printf("n is %lld, %s\n", n, nw.words(n));
    n = 999999999999999999; printf("n is %lld, %s\n", n, nw.words(n));
    n = 1000000000000000000; printf("n is %lld, %s\n", n, nw.words(n));
    
    return 0;
}