FizzBuzz: Variations on a Theme in C
C Shell
Latest commit b6f5122 Feb 20, 2017 @Keith-S-Thompson fizzbuzz86.c
Permalink
Failed to load latest commit information.
README.md fizzbuzz86.c Feb 20, 2017
expected-output.txt Initial checkin Apr 5, 2012
fizzbuzz01.c
fizzbuzz02.c Delete "return 0;" from main (since I'm compiling in C99 mode). Nov 6, 2013
fizzbuzz03.c Delete "return 0;" from main (since I'm compiling in C99 mode). Nov 6, 2013
fizzbuzz04.c Delete "return 0;" from main (since I'm compiling in C99 mode). Nov 6, 2013
fizzbuzz05.c Delete "return 0;" from main (since I'm compiling in C99 mode). Nov 6, 2013
fizzbuzz06.c
fizzbuzz07.c Delete "return 0;" from main (since I'm compiling in C99 mode). Nov 6, 2013
fizzbuzz08.c Delete "return 0;" from main (since I'm compiling in C99 mode). Nov 6, 2013
fizzbuzz09.c Delete "return 0;" from main (since I'm compiling in C99 mode). Nov 6, 2013
fizzbuzz10.c Use `static` where appropriate, make some objects local Feb 19, 2016
fizzbuzz11.c fizzbuzz11.c: Make func() static Jun 10, 2016
fizzbuzz12.c Use `static` where appropriate, make some objects local Feb 19, 2016
fizzbuzz13.c Use `static` where appropriate, make some objects local Feb 19, 2016
fizzbuzz14.c Delete "return 0;" from main (since I'm compiling in C99 mode). Nov 6, 2013
fizzbuzz15.c
fizzbuzz16.c
fizzbuzz17.c Use `static` where appropriate, make some objects local Feb 19, 2016
fizzbuzz18.c Delete "return 0;" from main (since I'm compiling in C99 mode). Nov 6, 2013
fizzbuzz19.c
fizzbuzz20.c Delete "return 0;" from main (since I'm compiling in C99 mode). Nov 6, 2013
fizzbuzz21.c Use `static` where appropriate, make some objects local Feb 19, 2016
fizzbuzz22.c Use `static` where appropriate, make some objects local Feb 19, 2016
fizzbuzz23.c fizzbuzz23.c: Remove some unneeded code Dec 23, 2015
fizzbuzz24.c Delete "return 0;" from main (since I'm compiling in C99 mode). Nov 6, 2013
fizzbuzz25.c Delete "return 0;" from main (since I'm compiling in C99 mode). Nov 6, 2013
fizzbuzz26.c Delete "return 0;" from main (since I'm compiling in C99 mode). Nov 6, 2013
fizzbuzz27.c Use `static` where appropriate, make some objects local Feb 19, 2016
fizzbuzz28.c Delete "return 0;" from main (since I'm compiling in C99 mode). Nov 6, 2013
fizzbuzz29.c
fizzbuzz30.c Delete "return 0;" from main (since I'm compiling in C99 mode). Nov 6, 2013
fizzbuzz31.c Delete "return 0;" from main (since I'm compiling in C99 mode). Nov 6, 2013
fizzbuzz32.c Delete "return 0;" from main (since I'm compiling in C99 mode). Nov 6, 2013
fizzbuzz33.c Delete "return 0;" from main (since I'm compiling in C99 mode). Nov 6, 2013
fizzbuzz34.c Use `static` where appropriate, make some objects local Feb 19, 2016
fizzbuzz35.c Use `static` where appropriate, make some objects local Feb 19, 2016
fizzbuzz36.c Delete "return 0;" from main (since I'm compiling in C99 mode). Nov 6, 2013
fizzbuzz37.c Use `static` where appropriate, make some objects local Feb 19, 2016
fizzbuzz38.c Delete "return 0;" from main (since I'm compiling in C99 mode). Nov 6, 2013
fizzbuzz39.c Use `static` where appropriate, make some objects local Feb 19, 2016
fizzbuzz40.c Use `static` where appropriate, make some objects local Feb 19, 2016
fizzbuzz41.c Delete "return 0;" from main (since I'm compiling in C99 mode). Nov 6, 2013
fizzbuzz42.c Delete "return 0;" from main (since I'm compiling in C99 mode). Nov 6, 2013
fizzbuzz43.c
fizzbuzz44.c Fix buffer overflow Jan 5, 2015
fizzbuzz45.c fizzbuzz45.c doesn't need <string.h> Jan 25, 2016
fizzbuzz46.c Add fizzbuzz46.c Jan 2, 2015
fizzbuzz47.c Add fizzbuzz47.c Jan 2, 2015
fizzbuzz48.c Add fizzbuzz48.c Jan 2, 2015
fizzbuzz49.c Add fizzbuzz49.c Jan 5, 2015
fizzbuzz50.c Add fizzbuzz50.c Jan 16, 2015
fizzbuzz51.c Add fizzbuzz51.c Jan 16, 2015
fizzbuzz52.c Add fizzbuzz52.c Jan 16, 2015
fizzbuzz53.c Add fizzbuzz53.c Feb 6, 2015
fizzbuzz54.c fizzbuzz54.c wasn't explicit enough Feb 20, 2015
fizzbuzz55.c Add fizzbuzz55.c (finite state machine) Feb 10, 2015
fizzbuzz56.c Add fizzbuzz56.c (old-fashioned finite state machine) Feb 14, 2015
fizzbuzz57.c Add fizzbuzz57.c (Finite state machine, now even more obfuscated) Feb 14, 2015
fizzbuzz58.c Add fizzbuzz58.c, fizzbuzz59.c Feb 15, 2015
fizzbuzz59.c Add fizzbuzz58.c, fizzbuzz59.c Feb 15, 2015
fizzbuzz60.c Add fizzbuzz60.c Feb 16, 2015
fizzbuzz61.c Use `static` where appropriate, make some objects local Feb 19, 2016
fizzbuzz62.c
fizzbuzz63.c Add fizzbuzz63.c. This works only if identical string literals share … Jul 25, 2015
fizzbuzz64.c Add fizzbuzz64.c Sep 3, 2015
fizzbuzz65.c Minor tweaks Dec 19, 2015
fizzbuzz66.c
fizzbuzz67.c
fizzbuzz68.c fizzbuzz68.c: sched_yield() Dec 8, 2015
fizzbuzz69.c Add fizzbuzz69.c Dec 6, 2015
fizzbuzz70.c
fizzbuzz71.c fizzbuzz71.c: Add a macro for <stdio.h> Jan 22, 2016
fizzbuzz72.c Add fizzbuzz72.c Dec 22, 2015
fizzbuzz73.c Add fizzbuzz73.c Dec 23, 2015
fizzbuzz74.c Use `static` where appropriate, make some objects local Feb 19, 2016
fizzbuzz75.c Use `static` where appropriate, make some objects local Feb 19, 2016
fizzbuzz76.c
fizzbuzz77.c
fizzbuzz78.c fizzbuzz78.c was too legible Jan 31, 2016
fizzbuzz79.c Add fizzbuzz79.c: Brute force with printf May 25, 2016
fizzbuzz80.c
fizzbuzz81.c Add fizzbuzz81.c Dec 19, 2016
fizzbuzz82.c Add fizzbuzz82.c, minor fixes in README.md Feb 15, 2017
fizzbuzz83.c Add fizzbuzz83.c Feb 15, 2017
fizzbuzz84.c fizzbuzz84.c Feb 19, 2017
fizzbuzz85.c fizzbuzz85.c Feb 19, 2017
fizzbuzz86.c fizzbuzz86.c Feb 20, 2017
verify Strict mode uses -pedantic-errors Dec 4, 2016

README.md

FizzBuzz is a nearly trivial programming exercise, sometimes used in job interviews to weed out candidates who say they can program but really can't.

References:

The requirements are simple:

Write a program that prints the numbers from 1 to 100. But for multiples of three print "Fizz" instead of the number and for the multiples of five print "Buzz". For numbers which are multiples of both three and five print "FizzBuzz".

Here's a straightforward implementation in C, similar to one I wrote (on paper!) in a job interview of my own a few years ago. (The problem statement didn't explicitly say what to print for numbers that are multiples of both three and five, so I stated the assumption explicitly as part of my solution.)

#include <stdio.h>
int main(void) {
    for (int i = 1; i <= 100; i ++) {
        if (i % 15 == 0) {
            puts("FizzBuzz");
        }
        else if (i % 3 == 0) {
            puts("Fizz");
        }
        else if (i % 5 == 0) {
            puts("Buzz");
        }
        else {
            printf("%d\n", i);
        }
    }
    return 0;
}

Some notes on this solution:

It requires a C compiler that accepts C99 or C11, or at least permits declarations in for loop headers. If you don't have such a compiler (gcc -std=c99 works), you can change this:

    for (int i = 1; i <= 100; i ++) {

to this:

    int i;
    for (i = 1; i <= 100; i ++) {

It takes advantage of a small piece of mathematics that's not stated in the problem, namely that a number is a multiple of both 3 and 5 if and only if it's a multiple of 15 -- and of course that you can test whether a number is a multiple of some N using the % operator.

Some important pieces of information are stated twice. In particular:

  • The string "Fizz" appears twice, once by itself and once as part of "FizzBuzz".
  • Likewise for the string "Buzz".
  • The test for i being a multiple of 3 is effectively performed twice, once in the test i % 3, and once, indirectly, in the test i % 15.
  • Likewise for the test for i being a multiple of 5.

These are violations of the DRY ("Don't Repeat Yourself") principle. For example, if I wanted to change the program to print "Bizz" and "Buzz", as in the drinking game that inspired the problem, I'd have to change "Fizz" to "Bizz" in two different places; similarly if I wanted to check for multiples of 3 and 7 rather than 3 and 5.

For a problem of this trivial size, none of these problems are worth solving. The entire program is only 18 lines (given the way I place my curly braces), and nobody who knows C should have any difficulty understanding what it does or modifying it correctly in the unlikely event that maintenance is called for.

Still, it can be instructive to see how the program might be modified to avoid the duplication.

It's easy enough to test whether i is a multiple of 3 just once, and if so, print "Fizz", and then to test whether it's a multiple of 5, and if so, print "Buzz". But then you have to remember whether you printed anything, and print the number itself only if you haven't printed either "Fizz" or "Buzz" or both (and then unconditionally print a new-line character).

And there are a number of other ways to solve the problem.

This project contains, so far, 86 different C implementations of FizzBuzz, most of them deliberately silly, using various combinations of the ?: conditional operator, short-circuit && and ||, function pointers, arrays of function pointers, arrays of arrays of function pointers, gratuitous recursion, gratuitous divide-and-conquer, Duff's Device, and outright deliberate obfuscation. One of them works only if the program's output is redirected to a seekable file; it dies with an error message if stdout is sent to a terminal. Another works only on implementations that support Pthreads. (The 2011 ISO C standard adds threads as an optional feature; I haven't yet written a version that takes advantage of that.) Yet another depends on undefined behavior and a certain amount of blind luck.

Please do not use these programs as examples of good programming style.

  • fizzbuzz01.c Straightforward solution.
  • fizzbuzz02.c Don't Repeat Yourself, remember whether we printed anything.
  • fizzbuzz03.c Similar to fizzbuzz02, but uses ftell() to detect whether anything was printed. This version fails if stdout is not seekable.
  • fizzbuzz04.c Brute force.
  • fizzbuzz05.c Use the value returned by printf to detect whether anything was printed.
  • fizzbuzz06.c Index into a two-dimensional array of pointers to strings.
  • fizzbuzz07.c Reduce the body of the loop to a single convoluted expression statement using short-circuit && and ||.
  • fizzbuzz08.c Abuse of the ?: conditional operator.
  • fizzbuzz09.c Similar, but using variables to remember whether i is a multiple of 3 and/or 5.
  • fizzbuzz10.c Build an array of 100 function pointers, then traverse it (does not scale well).
  • fizzbuzz11.c Use a function that returns a pointer to the appropriate function.
  • fizzbuzz12.c Similar, but use two functions returning function pointers.
  • fizzbuzz13.c Another array of function pointers, but only 4 this time, indexed by a number computed from i.
  • fizzbuzz14.c Similar to fizzbuzz05, but adding abuse of short-circuit ||.
  • fizzbuzz15.c Use a switch statement.
  • fizzbuzz16.c Replace the outer loop by gratuitous use of recursion.
  • fizzbuzz17.c Replace the outer loop by gratuitous use of recursion with divide-and-conquer.
  • fizzbuzz18.c Twist the logic around a bit and obfuscate.
  • fizzbuzz19.c Loop unrolling.
  • fizzbuzz20.c Duff's device (no, really!).
  • fizzbuzz21.c Duff's device and an array of pointers to format strings.
  • fizzbuzz22.c Use an array of 15 function pointers.
  • fizzbuzz23.c Use a two-dimensional array of characters.
  • fizzbuzz24.c Simple string processing.
  • fizzbuzz25.c Use printf's "%n" conversion specifier and a little tricky logic.
  • fizzbuzz26.c Manipulate the tens and units digits separately.
  • fizzbuzz27.c Gratuitous use of pthreads.
  • fizzbuzz28.c Another tricky way to determine what to print.
  • fizzbuzz29.c Based on fizzbuzz29, but taking advantage of the fact that excess arguments to printf are ignored.
  • fizzbuzz30.c Based on fizzbuzz30, but more terse, using a compound literal.
  • fizzbuzz31.c More abuse of operators.
  • fizzbuzz32.c Use a fixed-size one-dimensional char array.
  • fizzbuzz33.c Track i%3 and i%5 in separate variables without using division.
  • fizzbuzz34.c Use a wrapper function to perform the loop.
  • fizzbuzz35.c Like fizzbuzz34, but recursive.
  • fizzbuzz36.c Another brute-force approach, similar to fizzbuzz04.c but using a lookup table.
  • fizzbuzz37.c A variant of fizzbuzz36.c, encoding the lookup table in white space.
  • fizzbuzz39.c Call main() recursively.
  • fizzbuzz40.c Call main() recursively with a single argument string representing the range.
  • fizzbuzz41.c Control the output via the printf format string.
  • fizzbuzz42.c Use the result of an inner printf to control an outer printf; abuse of conditional operator.
  • fizzbuzz43.c Print 15 lines at a time, modifying the format string for the final iteration.
  • fizzbuzz44.c Ugly games with printf format string.
  • fizzbuzz45.c Even uglier games with printf format string.
  • fizzbuzz46.c A terser version of fizzbuzz24.c.
  • fizzbuzz47.c Build each line a character at a time.
  • fizzbuzz48.c Build each line a character at a time using obfuscated arithmetic.
  • fizzbuzz49.c Print each line a character at a time.
  • fizzbuzz50.c Like fizzbuzz36.c, but more obfuscated.
  • fizzbuzz51.c Like fizzbuzz50.c, but with a smaller lookup table.
  • fizzbuzz52.c Math.
  • fizzbuzz53.c Based on fizzbuzz04.c; so obvious I should have done it sooner.
  • fizzbuzz54.c Just in case fizzbuzz53.c wasn't verbose enough.
  • fizzbuzz55.c Finite state machine.
  • fizzbuzz56.c Finite state machine, done the old fashioned way.
  • fizzbuzz57.c Finite state machine, now even more obfuscated.
  • fizzbuzz58.c Linked list of format structures.
  • fizzbuzz59.c fizzbuzz58.c was too legible.
  • fizzbuzz60.c Like fizzbuzz59.c, but relative offsets avoid the need for a pointer to the first element.
  • fizzbuzz61.c Scramble and unscramble.
  • fizzbuzz62.c Relatively straightforward use of ?: operator.
  • fizzbuzz63.c This one works only if identical string literals occupy the same storage (it fails with tcc).
  • fizzbuzz64.c Abuse of multi-character constants (works only if they have distinct values, which is not guaranteed) (it fails with tcc).
  • fizzbuzz65.c You can write BASIC in any language.
  • fizzbuzz66.c A few macros can make the code much clearer.
  • fizzbuzz67.c Compound literal.
  • fizzbuzz68.c Threads.
  • fizzbuzz69.c Cheat. Fails if expected-output.txt is not available.
  • fizzbuzz70.c Based on fizzbuzz20.c, using Duff's Device. Use printf for all lines, and shuffle the case labels.
  • fizzbuzz71.c Based on fizzbuzz66.c but with more macros.
  • fizzbuzz72.c More straightforward loop unrolling inspired by Duff's Device, with macros for brevity.
  • fizzbuzz73.c Based on fizzbuzz23.c, using a two-dimensional array of characters.
  • fizzbuzz74.c Inspired by fizzbuzz54.c, but print a bit at a time (assumes an ASCII-based character set).
  • fizzbuzz75.c Like fizzbuzz74.c, but using 4 bits per character with a lookup table.
  • fizzbuzz76.c Encode the data as a large integer, use GMP to extract it.
  • fizzbuzz77.c Don't divide, just count.
  • fizzbuzz78.c Like fizzbuzz77.c, but just use one 16-bit variable.
  • fizzbuzz79.c Brute force with printf.
  • fizzbuzz80.c Iterate over an array of lines.
  • fizzbuzz81.c Search for the message in memory; depends on undefined behavior and luck.
  • fizzbuzz82.c Some arithmetic and bit twiddling.
  • fizzbuzz83.c Based on fizzbuzz82.c with an array of function pointers and backwards indexing.
  • fizzbuzz84.c Based on fizzbuzz21.c, Duff's device with partial loop re-rolling of the unrolled loop.
  • fizzbuzz85.c Simple yet convoluted logic.
  • fizzbuzz86.c Print unconditionally to file handles that may or may not be open, ignoring errors.