Number to English word converter
Switched

Let's start with the obvious things we can improve. A return statement terminates the current function. Therefore, all your

case XY: return AB; break;


can be rewritten as

case XY: return AB;


However, you don't have any default cases in both switch statements. What happens if you use conv0to19(100)? Well, it's not obvious, because it's undefined behaviour.

For the sake of simplicity, let's use an assert for unhandled cases. But before we do that, let's have a closer look at your switch:

    case 0:return "";
    case 1:return "one ";
    case 2:return "two ";
      ...
    case 18:return "eighteen ";
    case 19:return "nineteen ";


Hm. You have a continuous range of integer values. So let's use that to our advantage:

std::string conv0to19(uint64_t a) {
    static char const * const numbers[20] = 
      {"", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten",
      "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"
      };

    assert(0 &lt;= a &amp;&amp; a &lt; 20);

    return numbers[a];
}


You can do the same for conv_dec. Note that I've removed the suffix space from the string. More on that later.

While we're at it and using an array, your name should:


have a better name (especially not name, since it's a collection of several ones)
be const, so that you don't change it by accident:




const std::string numberNames[] = {"", "thousand", "million", "billion", "trillion", "quadrillion", "quintillion"};


By the way, did you notice that I've added whitespace to separate the arguments? Remember code is written for humans (and for machines). If you want to remove a word later, it should be easy to do so, and whitespace makes it a lot easier to mark text with Ctrl+Shift (or whatever your operating system/editor uses).

Back to the beginning

int container[7];                       /// every element contains a number between 0 and 999


That is a code smell. It's a global variable, which isn't constant. And the description is, well, no really helpful. Just remove it.

Also, the 7 seems like a magic number. Why is it 7? Why not 10?

Either way, you should include cstdint instead of stdint-gcc.h, or — if your compiler is too old — stdint.h. Also, I recommend you to typedef your used number type, e.g.:

typedef uint64_t number_type;


That way you can replace the type easily, if you want to support even larger numbers later.

And using namespace std… well, it's considered bad practice for large programs, especially in headers, but you're writing only a single file here. It's up to you, but I wouldn't use it.

Using logic to reduce if-complexity

Your convert1to999 is too complex. If we didn't enter the following block:

    if (a&gt;0&amp;&amp;a&lt;20)
        return conv0to19(a)+name[i];


we're guaranteed that a is larger then 20. Why? Because a isn't 0. Since it is a non-negative number, it must be then greater than zero, so a&gt;0 holds, so a &lt; 20 must not hold. We don't need to repeat that in the next condition:

    if(a&gt;20&amp;&amp;a&lt;100&amp;&amp;a%10!=0)
       ^^^^


And again, your code is neigh unreadable, since you don't use any whitespace. What is easier to read:

a&gt;=20&amp;&amp;a&amp;&amp;a&lt;100&amp;&amp;a%10==0


or

a &gt;= 20 &amp;&amp; a &amp;&amp; a &lt; 100 &amp;&amp; a % 10 == 0


I guess you now see the superfluous a in the condition, which will always be true at that point.

Next, this function should do one job. It should get a number from 0-999 and return its name, not add the suffix. So let's get rid of that and fix the if complexity. And while we're at it, let's add another function for 0-99:

std::string conv0to99(number_type a)
{
    assert(0 &lt;= a &amp;&amp; a &lt; 100);

    if(a == 0) {
        return "";
    } else if (a &lt;= 20) {
        return conv0to19(a);
    } else {
        return conv_dec(a / 10) + "-" + conv0to19(a % 10);
    }
}

std::string convert1to999(number_type a)
{
    assert(0 &lt;= a &amp;&amp; a &lt; 1000);

    if(a == 0) {
        return "";
    } else if (a &lt;= 100) {
        return conv0to99(a);
    } else {
        return conv0to19(a/100) + " hundred " + conv0to99(a % 100);
    }
}


Both functions are rather simple and easy to check. The hurdles of the &lt;=20 are now (almost) entirely hidden in conv0to99, which is still easy enough to understand quickly.

As I said, get rid of fillContainer. You use it only in convert, so let's only have it there. Also, handle the easy case first:

std::string convert(uint64_t a)
{
    if(a == 0) {
        return "zero";
    }

    std::string output;
    int container[7];

    for(int i = 0; i &lt; 7; ++i) {
        container[i] = a % 1000;
        a = a / 1000;
    }

    for(int i = 6; i&gt;=0; i--) {
        if(container[i] != 0) {
            // we add the name now here instead of in convert1to999
            output += convert1to999(container[i]) + " " + name[i] + " ";
        }
    }

    // if your compiler doesn't have `output.back()`, use your old check
    while(output.back() == ' ') {
        output.pop_back();
    }

    return output;
}


You can also get rid of container if you build the number from the back. 

Last words

Make sure to format your code. Either use an editor which supports automatic formatting, or use a program that formats your code, especially if you want to share your code.