Fizzbuzz but without if Code first, elaboration later:

// Fizzbuzz: 1..100, %3-&gt;fizz, %5-&gt;buzz, %15-&gt;fizzbuzz
// noif: do not use if/switch statements or ternary expressions
// LIMIT must be a power of 10
// WIDTH must be equal to log10(LIMIT)

#include &lt;stdio.h&gt;
#include &lt;string.h&gt;

#define LIMIT 100
#define WIDTH 2

char *
itoa(int n)
{
    static char out[WIDTH + 1];

    for(char *outp = out + WIDTH - 1; outp &gt;= out; --outp, n /= 10)
        *outp = '0' + n % 10;

    return out;
}

void
fizzbuzz(int n)
{
    static char *FBSTR[4] = {"", "Fizz", "Buzz"};

    FBSTR[3] = itoa(n);
    fputs(FBSTR[1 * (n%3 == 0)], stdout);
    fputs(FBSTR[2 * (n%5 == 0)], stdout);
    fputs(FBSTR[3 * (n%3 &gt; 0 &amp;&amp; n%5 &gt; 0)], stdout);
    putchar('\n');
}

int
main(void)
{
    for(int i = 1; i &lt;= LIMIT; ++i)
        fizzbuzz(i);

    return 0;
}


I've been reading a little bit about the anti-if campaign, and decided to try my hand at a challenge: Fizzbuzz but without if statements.

Because I'm not trying to be cheap, that also means no switch statements,

switch(n % 3){
    case 0: fputs("fizz", stdout); break;
}


no ternary expressions,

fputs((n % 3 == 0) ? ("fizz") : (""), stdout);


and no contrived while loops.

int lock = 0;

while(lock++ == 0 &amp;&amp; n % 3 == 0)
    fputs("fizz", stdout);
char *
itoa(int n)
{
    static char out[WIDTH + 1];

    for(char *outp = out + WIDTH - 1; outp &gt;= out; --outp, n /= 10)
        *outp = '0' + n % 10;


Nice bounds-check (outp &gt;= out). This ensures that you don't overrun your buffer when given a very large integer. However, since out-1 is not a valid pointer value, outp &gt;= out is an incorrect bounds-check for the same reason that

int decr(int x) {
    int y = x - 1;
    if (y &gt; x) return 0;  // oops, overflow happened
    return y;
}


is an incorrect overflow-check.

Your bounds-check code also has another similarity to the above overflow-check code: When overflow happens, you return an in-range value that the caller might reasonably confuse for a valid result of the function. When itoa(x) returns "42", does it mean that x was 42, or does it mean that x was 1042 and overflow happened? It would be much better to say, if overflow happens, we return NULL.

Of course you'll have to express that "if" without if. ;)



itoa returns char*, but you don't expect the caller to modify the pointed-to chars, so you should declare it as returning a pointer to non-modifiable chars: const char*. Const is a contract.

Similarly, static char *FBSTR[4] should be static const char *FBSTR[4].



static const char *FBSTR[4] = {"", "Fizz", "Buzz", NULL};


would be much clearer to the human reader; it shows that you didn't miscount the number of array elements. In fact, you might even write

static const char *FBSTR[] = {"", "Fizz", "Buzz", NULL};


although the downside of that is that the number of indices is actually really important to your algorithm, so I can see a valid argument for keeping the 4 in this case.



fputs(FBSTR[1 * (n%3 == 0)], stdout);
fputs(FBSTR[2 * (n%5 == 0)], stdout);
fputs(FBSTR[3 * (n%3 &gt; 0 &amp;&amp; n%5 &gt; 0)], stdout);
putchar('\n');


I did puzzle this out, but printing all those empty strings feels like a strange way to go about it. Why not simply

int idx = 1*(n%3 == 0)
        + 2*(n%5 == 0)
        + 3*(n%3 != 0 &amp;&amp; n%5 != 0);
fputs(FBSTR[idx], stdout);
putchar('\n');


In which case you can combine the fputs and putchar into

puts(FBSTR[idx]);




If you think it would be easier to understand, you could even rewrite the index computation using bitwise operations:

const char *FBSTR[] = {itoa(n), "Fizz", "Buzz", "FizzBuzz"};
int idx = (n%3 == 0) + 2*(n%5 == 0);
puts(FBSTR[idx]);




To avoid reinventing the wheel, you could replace itoa(n) with snprintf(somelocalbuffer, sizeof somelocalbuffer, "%d", n). However, for this toy example, itoa does have a more ergonomic interface; and reinventing the wheel isn't necessarily a bad thing.