Visit the raindrops exercise on Exercism to read the full instructions and download the exercise files.
Dig Deeper
if Statements
if Statements
raindrops.h
#ifndef RAINDROPS_H
#define RAINDROPS_H
void convert(char result[], int drops);
#endif
raindrops.c
#include "raindrops.h"
#include <stdio.h>
#include <string.h>
void convert(char result[], int drops)
{
if (drops % 3 == 0)
strcat(result, "Pling");
if (drops % 5 == 0)
strcat(result, "Plang");
if (drops % 7 == 0)
strcat(result, "Plong");
if (strlen(result) == 0)
sprintf(result, "%d", drops);
}
- The first
if statement checks if drops is a multiple of 3.
If so, "Pling" is concatenated to result using the strcat function.
- The second
if statement checks if drops is a multiple of 5.
If so, "Plang" is concatenated to result using the strcat function.
- The thrd
if statement checks if drops is a multiple of 7.
If so, "Plong" is concatenated to result using the strcat function.
Finally, the [strlen function] checks if result is empty: if so, the [sprintf function] formats drops as string into result.
sprintf Function
sprintf Function
raindrops.h
#ifndef RAINDROPS_H
#define RAINDROPS_H
void convert(char result[], int drops);
#endif
raindrops.c
#include "raindrops.h"
#include <stdio.h>
#include <string.h>
void convert(char result[], int drops)
{
sprintf(result, "%s%s%s", drops % 3 == 0 ? "Pling" : "",
drops % 5 == 0 ? "Plang" : "", drops % 7 == 0 ? "Plong" : "");
if (strlen(result) == 0)
sprintf(result, "%d", drops);
}
This approach allows for very concise, if not a bit obfuscated, code.
A series of ternary conditional operators check if drops is a multiple of 3, 5, or 7 respectively.
If it is, the expression returns the appropriate raindrop sound (either "Pling", "Plang" or "Plong"); otherwise, the result is the empty string ("").
Then, in the same statement, a single call to the sprintf function concatenates all the above three strings.
Finally, the strlen function checks if result is empty: if so, sprintf is used again to format drops as string into result.
Data-Driven Programming
Data-Driven Programming
raindrops.h
#ifndef RAINDROPS_H
#define RAINDROPS_H
void convert(char result[], int drops);
#endif
raindrops.c
#include "raindrops.h"
#include <stdio.h>
#include <string.h>
typedef struct {
int factor;
const char *sound;
} sound_t;
static const sound_t SOUNDS[] = {
{ 3, "Pling" },
{ 5, "Plang" },
{ 7, "Plong" },
};
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
void convert(char result[], int drops)
{
for (size_t i = 0; i < ARRAY_SIZE(SOUNDS); i++) {
if (drops % SOUNDS[i].factor == 0) {
strcat(result, SOUNDS[i].sound);
}
}
if (strlen(result) == 0) {
sprintf(result, "%d", drops);
}
}
First, the program defines a structure data type to hold together two pieces of information: a factor and its corresponding sound.
Then, an array is created to hold all the necessary data, which is used to drive the logc of the program.
The body of the function does not have any knowledge of the actual data, becoming simple and flexible:
- For each element of the
SOUNDS array
— If the given number is a multiple of the current factor
--- Then concatenate the current sound to the result string using the strcat function.
This approach allows for extensible code: for example, new sounds could be added (or removed) without modifying the convert function.
Finally, the [strlen function] checks if result is empty: if so, the [sprintf function] formats drops as string into result.
Source: Exercism c/raindrops