Laborarory: Functions and some flow control statements

Gábor Horváth / Zsolt Kohári · 2020.10.07.

Creation and use of functions. Multiple choice and post-test loop.

Preparation for lab:

Review lecture topics on
  • switch() statement,
  • functions.

1. Functions — the basics

  -1.0000  -1.0000   1.0000  -0.8415
  -0.9000  -0.7290   0.9000  -0.7833
  -0.8000  -0.5120   0.8000  -0.7174
 . . .
   0.9000   0.7290   0.9000   0.7833
   1.0000   1.0000   1.0000   0.8415

Write functions that receive a real number parameter, and return:

  • cube() – its third power,
  • absolute() – its absolute value (there is a fabs() library function but do not use it this time)!

Write a program that tabulates the values of a, a3, |a| and sin(a) using 4 decimal digits after the decimal point from a = −1 to +1, stepping by 0.1! Include math.h to use sin.

Solution

#include <stdio.h>
#include <math.h>

double cube(double x) {
    return x*x*x;
    /* or: return pow(x, 3); */
}

double absolute(double x) {
    if (x < 0)
        return -x;
    else
        return x;
    /* or: return x < 0 ? -x : x; */
}

int main() {
    for (double a = -1; a <= +1; a += 0.1)
        printf("%10.4f %10.4f %10.4f %10.4f\n", a, cube(a), absolute(a), sin(a));

    return 0;
}

2. Stammering

Stammering (or stuttering) is a speech disorder when syllables (usually the first one in the words) are unintentionally repeated. Look at the following ahartihifihicihiahal stahammehereher cohodehe (artificial stammerer code)

Ctrl+Z/Ctrl+D to stop
#include <stdio.h>

int main(void) {
    char c;
    while (scanf("%c", &c) == 1) {
        if (c=='a' || c=='e' || c=='i' || c=='o' || c=='u')
            printf("%ch%c", c, c);
        else
            printf("%c", c);
    }

    return 0;
}

Write a function to distinguish vowels from other letters (the function receives a character, and returns whether it is a vovel or not). Modify the program above to use this function in main().

Solution

#include <stdio.h>
#include <stdbool.h>

/* Returns true if the function parameter is a vowel. */
bool vowel(char c) {
    return c=='a' || c=='e' || c=='i' || c=='o' || c=='u';
}

int main() {
    char c;
    while (scanf("%c", &c) != EOF)
        if (vowel(c))
            printf("%ch%c", c, c);
        else
            printf("%c", c);

    return 0;
}

How to make it work for words starting with a capital? Like, for the word „Apart” „Ahapahart” should be printed. To accomplish this the program must be able to identify uppercase vowels, too. The original character should be printed before h, and the lowercase counterpart after it. You can use your existing vowel() function for deciding but always pass the lowercase letter to it.

Hint

There are character handling library functions in #include <ctype.h>. One of them is tolower(). The tolower(c) expression is the lowercase counterpart of c if it is an uppercase letter, for any other character it returns the original character.

Solution

Let us send to the vowel function the lowercase variant of the character: vowel(tolower(c)). However, when printing to the screen, first the original character c needs to be displayed, then the lowercase variant of the character tolower(c). You can use the built-in tolower() function (#include <ctype.h>), or your own one.

while (scanf("%c", &c)==1)
    if (vowel(tolower(c)))
        printf("%cv%c", c, tolower(c));
    else
        printf("%c", c);

3. Twin primes

A twin prime is a prime number that is either 2 less or 2 more than another prime number - for example, either member of the twin prime pair (41, 43). In other words, a twin prime is a prime that has a prime gap of two.

The first couple of twin primes are (3, 5), (5, 7) and (11, 13). Write a C program to find the 60th twin prime! Extend the program to check whether the number between the twin primes has any digit equal to 5. Avoid code duplication, use functions wherever reasonable! Follow the top-down design methodology.

Hint

First, write a function that receives an integer number, and returns whether the number is prime. Then, an other function is needed to determine if a number contains a certain digit. The main should be as small and compact as possible, it should make use of the two functions.

Solution

The principle of the solution

The next twin prime can be found by the following algorithm:

while (!(prime(number) && prime(number + 2)))
    number += 2;

For detecting digit 5 we need to consider each digit of the number one by one: the value of number % 10 gives the last digit.

#include <stdio.h>
#include <stdbool.h>

/* decides whether the number is a prime or not */
int prime(int number) {
    for (int divisor = 2; divisor < number; divisor++)
        if (number % divisor == 0)
            return 0;
    return 1;
}

/* decides whether the number has a specific digit included or not */
int contains(int number, int digit) {
    while (number > 0) {
        if (number % 10 == digit)
            return 1;
        number /= 10;
    }
    return 0;
}

int main(void) {
    int number, i;

    /* initialization */
    number = 1;
    i = 0;
    while (i < 60) {
        /* find next twin primes */
        number += 2;
        while (!(prime(number) && prime(number + 2)))
            number += 2;
        ++i;
    }
    printf("%dth twin prime: %d %d\n", 60, number, number+2);

    /* second part: check if the number inbetween contains digit 5 */
    printf("The number inbetween %s digit 5.\n", contains(number + 1, 5) ? "does contain":"does not contain");

    return 0;
}

4. Menu controlled program

Create a simple menu controlled program! The program stores a number with an initial value of n = 1. Then the program should print the actual value of n and the menu below. After the user selects a menu item (scanf()) the program should do whatever the user requested and print the value of n and the menu! These must be repeated as long as the user chooses anything but the Exit menu option! Use switch() and post-testing do ... while() loop.

printf("0. Restore the initial value (n = 1)\n"
       "1. Add 1\n"
       "2. Negate the number (+/-)\n"
       "3. Multiple by 2\n"
       "9. Exit\n");

Realize each operation in a (tiny) function that receives the value of n as a parameter and returns the modified value! Your main() can only call these functions to change the value of n.

Why is this task so important?

Note that the main function controls the calling of the other functions. It will call the appropriate subprogram according to the choice of the user, and when they return main gets back the control. The main program and the subprograms communicate via function parameters and return values.

Solution

To select the proper action it is recommended to use a switch() instruction. In this way, we can list the corresponding function calls one-by-one, below each other. Care has to be taken to not to forget the break. The menu can be put into the body of a loop. This can be a bottom-test loop, since we have to execute the body at least once, to print the options and let the user select one.

#include <stdio.h>

int reset() {
    return 1;
}

int increment(int a) {
    return a+1;
}

int invert(int a) {
    return -a;
}

int duplicate(int a) {
    return 2*a;
}

int main() {
    int menuselection;
    int a = reset();
    do {
        printf("a = %d\n\n", a);
        printf(
            "0. Re-setting the variable (a = 1)\n"
            "1. Increment by 1\n"
            "2. Invert the sign\n"
            "3. Multiply by 2\n"
            "9. Exit\n"
            "? ");
        scanf("%d", &menuselection);
        switch (menuselection) {
            case 0: a = reset(); break;
            case 1: a = increment(a); break;
            case 2: a = invert(a); break;
            case 3: a = duplicate(a); break;
            case 9: /* nothing, we are going to exit */ break;
            default: printf("HEY!\n"); break;
        }
        printf("\n");          /* cosmetic line break */
    } while (menuselection != 9);

    return 0;
}