I created this program to print the number of vowels of a given text in C; it is only a small exercise. I consider a vowel only the letters "aeiou", both in upper case and lower case.
I provided a small command line interface: if you give -h
or --help
you get the help message, if you give the text (e.g. vowel "This is a text"
) it directly prints the number of vowels. If you run the program without any argument or text, it reads from the stdin until the user types CTRL-D two times.
Examples:
user@computer:$ ./vowels
This is
a
text
4
user@computer:$ ./vowels "This is a text"
4
The source code is organized in a main.c
and a Makefile
.
Makefile
.PHONY = clean all
PROGNAME = vowels
CC ?= gcc
CFLAGS = -Wall -Wextra
all : $(PROGNAME)
$(PROGNAME) : main.o
$(CC) -o $(PROGNAME) $^
clean :
$(RM) *.o $(PROGNAME)
main.c
#include <stdio.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h> /* For tolower(). */
#define BUFFER_SIZE 1024
/* It returns true if the given character is a vowel.
*
* Arguments:
* - chr : the character to check.
*
* Return value:
* True if 'chr' is a vowel, otherwise false.
*
* Notes:
* The vowels considered are English vowels (a, e, i, o, u), both in
* upper case and lower case.
*/
bool is_vowel(char chr)
{
static const char VOWELS[] = "aeiou";
chr = tolower(chr);
char *result = strchr(VOWELS, chr);
return (!result) ? false : true;
}
/* It returns the number of vowels found in a null terminated byte string.
*
* Arguments:
* - str : the null terminated byte string.
*
* Return value:
* It returns the number of vowels found in the string.
*
* Warning:
* The behavior is undefined if str is not a pointer to a null-terminated
* byte string.
*/
int vowels_in(char *str)
{
int vowels = 0;
while (*str) {
if (is_vowel(*str))
vowels++;
str++;
}
return vowels;
}
/* It prints the help message.
*/
void print_help(void)
{
static const char message[] =
"usage: vowels [-h|--help] <text>\n\n"
"It shows the number of vowels (aeiou) found in a given text. If you don't\n"
"specify text in the command line, the program reads text from stdin.\n\n"
;
printf("%s", message);
}
int main(int argc, char *argv[])
{
char buffer[BUFFER_SIZE];
int vowels = 0;
if (argc == 2) {
if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
print_help();
return 0;
} else {
vowels = vowels_in(argv[1]);
printf("%d\n", vowels);
}
} else if (argc == 1) {
size_t chars;
/* Repat until the user type CTRL-D or there is an error. */
do {
chars = fread(buffer, sizeof(char), BUFFER_SIZE, stdin);
vowels += vowels_in(buffer);
} while (chars == BUFFER_SIZE);
printf("\n%d\n", vowels);
} else {
fprintf(stderr, "Invalid options; see 'vowels --help'.\n");
return -1;
}
return 0;
}
sizeof(char)
is guaranteed to always be 1 from the standard, 6.5.3.4:When sizeof is applied to an operand that has type char, unsigned char, or signed char, (or a qualified version thereof) the result is 1.
\$\endgroup\$sizeof(char)
with1
? \$\endgroup\$sizeof(char)
due to habit or because they feel it documents the purpose better. \$\endgroup\$chars = fread(buffer, sizeof *buffer, BUFFER_SIZE, stdin);
and remove need to match the type. \$\endgroup\$