Typing Practice Program Using C

CCBeginner
Practice Now

Introduction

This project will guide you in creating a typing practice program using the C programming language. You will learn how to perform various typing exercises, including training with single strings, multiple strings, and keyboard layout-based typing. These programs will help improve your typing speed and accuracy.

šŸ‘€ Preview

Start typing association exercises.
Please enter the hidden character indicated by '?'.
Press the space key to start.
AS?FG
?m,./\
67890-?\
?XCVB
zx?vb
!"?$%
ZXC?B
hjk?;:]
...(omit)...

šŸŽÆ Tasks

In this project, you will learn:

  • How to create a typing practice program using C.
  • How to implement exercises for typing single strings, multiple strings, and keyboard layout associations.
  • How to use the curses library for screen input and output operations.
  • How to shuffle the order of questions for variety in practice.

šŸ† Achievements

After completing this project, you will be able to:

  • Create a C program to simulate typing practice.
  • Handle user input and validate correctness.
  • Generate random questions and shuffle question order.
  • Utilize the curses library for advanced screen input and output operations.

Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL c(("`C`")) -.-> c/UserInteractionGroup(["`User Interaction`"]) c(("`C`")) -.-> c/BasicsGroup(["`Basics`"]) c(("`C`")) -.-> c/ControlFlowGroup(["`Control Flow`"]) c(("`C`")) -.-> c/CompoundTypesGroup(["`Compound Types`"]) c(("`C`")) -.-> c/PointersandMemoryGroup(["`Pointers and Memory`"]) c(("`C`")) -.-> c/FunctionsGroup(["`Functions`"]) c/UserInteractionGroup -.-> c/output("`Output`") c/BasicsGroup -.-> c/comments("`Comments`") c/BasicsGroup -.-> c/variables("`Variables`") c/BasicsGroup -.-> c/data_types("`Data Types`") c/BasicsGroup -.-> c/operators("`Operators`") c/ControlFlowGroup -.-> c/if_else("`If...Else`") c/ControlFlowGroup -.-> c/while_loop("`While Loop`") c/ControlFlowGroup -.-> c/for_loop("`For Loop`") c/CompoundTypesGroup -.-> c/arrays("`Arrays`") c/CompoundTypesGroup -.-> c/strings("`Strings`") c/PointersandMemoryGroup -.-> c/memory_address("`Memory Address`") c/PointersandMemoryGroup -.-> c/pointers("`Pointers`") c/FunctionsGroup -.-> c/function_parameters("`Function Parameters`") c/FunctionsGroup -.-> c/function_declaration("`Function Declaration`") c/FunctionsGroup -.-> c/recursion("`Recursion`") subgraph Lab Skills c/output -.-> lab-298834{{"`Typing Practice Program Using C`"}} c/comments -.-> lab-298834{{"`Typing Practice Program Using C`"}} c/variables -.-> lab-298834{{"`Typing Practice Program Using C`"}} c/data_types -.-> lab-298834{{"`Typing Practice Program Using C`"}} c/operators -.-> lab-298834{{"`Typing Practice Program Using C`"}} c/if_else -.-> lab-298834{{"`Typing Practice Program Using C`"}} c/while_loop -.-> lab-298834{{"`Typing Practice Program Using C`"}} c/for_loop -.-> lab-298834{{"`Typing Practice Program Using C`"}} c/arrays -.-> lab-298834{{"`Typing Practice Program Using C`"}} c/strings -.-> lab-298834{{"`Typing Practice Program Using C`"}} c/memory_address -.-> lab-298834{{"`Typing Practice Program Using C`"}} c/pointers -.-> lab-298834{{"`Typing Practice Program Using C`"}} c/function_parameters -.-> lab-298834{{"`Typing Practice Program Using C`"}} c/function_declaration -.-> lab-298834{{"`Typing Practice Program Using C`"}} c/recursion -.-> lab-298834{{"`Typing Practice Program Using C`"}} end

Project Environment

The project requires the use of the curses library. Install it using the following commands:

sudo apt-get update
sudo apt-get install libncurses5-dev

The purpose of the getputch.h header file in the code is to provide a cross-platform screen input and output function library, ensuring that the program can correctly perform screen input and output operations in different operating systems and compiler environments, especially the handling of newline character output.

Next, we will introduce basic typing exercises, which mainly involve pointers, string arrays, and loop structures in the C language.

We will demonstrate the application of string arrays, starting from the basic input of a single character to practicing with multiple unordered words.

Enter a Character

Navigate to the ~/project directory and create the project file typing1a.c:

cd ~/project
touch typing1a.c

Next, we need to write C code to create a typing practice software that allows input of a string. The program is as follows:

#include <time.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include "getputch.h"

int main(void)
{
    int    i;
    char   *str = "How do you do?";     /* The string to be input */
    int    len = strlen(str);           /* Number of characters in the string */

    init_getputch();
    printf("Please type as shown.\n");
    printf("%s\n", str);                /* Display the string to be input */
    fflush(stdout);

    for (i = 0; i < len; i++) {
        int ch;
        do {
            ch = getch();                 /* Read input from the keyboard */
            if (isprint(ch)) {
                putch(ch);                /* Display the pressed key */
                if (ch != str[i])         /* If a wrong key is pressed */
                    putch('\b');          /* Move the cursor back one space */
            }
        } while (ch != str[i]);
    }

    term_getputch();
    return 0;
}

The player is required to input the string pointed to by the str pointer: How do you do?. By the interchangeability of pointers and arrays, the characters 'H', 'o', ..., '?' within the string can be represented sequentially as str[0], str[1], ..., str[13].

Additionally, the variable len represents the length of the string str and has an initial value of 14. strlen() is used to obtain the length of the string.

The for loop increments the value of the variable i from 0, 1, 2, ... for len iterations to sequentially traverse the characters within the string from start to finish. During each iteration, the character str[i] is 'H', 'o', ..., '?', which are the characters to be input. This typing practice does not accept incorrect characters (the program will not move to the next character until the player inputs the correct character). This control is ensured by the do loop, with the following actions taken inside the loop:

  • Assign the input character (the return value of the getch function) to the variable ch.
  • If the character ch is a printable character, display it using the putch function (excluding non-displayable characters such as newline and tab).
  • If the character ch is not equal to the character to be input str[i], output the backspace character '\b' to move the cursor back one space. This ensures that the next input character is displayed in the same position.

After completing the aforementioned steps, the control expression of the do loop (ch != str[i]) is evaluated. When an incorrect character is input (when ch is not equal to str[i]), the do loop starts again. At this point, the program does not move to the next character but runs the relevant part within the do ... while loop again. After inputting the correct character, the value of i is incremented by the for loop, and the program moves to the next character. After inputting all the characters, the program will display the time taken by the player.

Compile and run using the following commands:

cd ~/project
gcc -o typing1a typing1a.c -lcurses
./typing1a
Typing Practice

You can practice multiple times to improve your speed. If you find How do you do? boring to practice, you can also choose another string to practice.

Eliminating Entered Characters

Navigate to the ~/project directory and create the project file typing1b.c:

cd ~/project
touch typing1b.c

Now let's take a look at the program. The code is as follows:

#include <time.h>
#include <stdio.h>
#include <string.h>
#include "getputch.h"

int main(void)
{
    int     i;
    char    *str = "How do you do?";    /* The string to be entered */
    int     len = strlen(str);          /* The number of characters in the string str */

    init_getputch();
    printf("Please type as shown.\n");

    for (i = 0; i < len; i++) {
        /* Display the characters after str[i] and return the cursor to the beginning */
        printf("%s \r", &str[i]);
        fflush(stdout);
        while (getch() != str[i])
            ;
    }

    term_getputch();
    return 0;
}

This program is slightly different from the previous one. Each time the correct character is entered, a character will disappear and the following characters will move forward. Similarly, the program will not move to the next character unless the player enters the correct key. When the player correctly enters all the characters, all the characters will disappear and the program will end.

Although the operation performed here is more "advanced" than the previous program, the program is actually shorter. The body of the for statement consists of only two short statements.

  • The &str[i] passed to the printf function in the statement printf("%s \r", &str[i]); is a pointer to str[i]. Since the value of the variable i is 0, the pointer &str[i] will point to the character 'H', causing the screen to display the string How do you do? starting with str[0], as shown in the figure above. The program will then output whitespace characters and a carriage return \r immediately after this string, and return the cursor to the position of the 'H' at the beginning of the line.
  • If the entered character (the return value of the getch function) is not equal to str[i], that is, the input character is not 'H', the while statement will loop continuously until the player enters the correct character, at which point the while statement will end.
  • The value of the variable i will then become 1 through the influence of the for statement. As shown in the figure above, the statement printf("%s \r", &str[i]); will output the string ow do you do? starting with str[1], then output whitespace characters and a carriage return, and return the cursor to the position of the 'o' at the beginning. After that, with the effect of the subsequent while statement, it waits for the player to correctly enter 'o'.

Compile and run using the following commands:

cd ~/project
gcc -o typing1b typing1b.c -lcurses
./typing1a
Typing Practice

Input Multiple Strings

Next, let's extend the previous program to allow the player to practice inputting multiple strings.

Navigate to the ~/project directory and create a project file called typing2a.c:

cd ~/project
touch typing2a.c

Now let's take a look at the program. The code is as follows:

#include <time.h>
#include <stdio.h>
#include <string.h>
#include "getputch.h"

#define QNO	    12      /* Number of questions */

int main(void)
{
    char *str[QNO] = {"book",   "computer", "default",  "comfort",
                      "monday", "power",    "light",    "music",
                      "programming", "dog", "video",    "include"};
    int i, stage;

    init_getputch();
    printf("Start typing practice.\n");
    printf("Press the spacebar to begin.\n");
    while (getch() != ' ')          /* Wait until */
        ;                           /* the player presses the spacebar */

    for (stage = 0; stage < QNO; stage++) {
        int len = strlen(str[stage]);   /* Number of characters in string str[stage] */
        for (i = 0; i < len; i++) {
            /* Display the characters after str[stage][i] and return the cursor to the beginning */
            printf("%s \r", &str[stage][i]);

            fflush(stdout);
            while (getch() != str[stage][i])
                ;
        }
    }

    term_getputch();

    return 0;
}

In this program, after inputting a string, the next string will be displayed on the same line for the player to input. There are a total of 12 strings available for practice.

This program is mostly based on the previous program, but there are a few differences:

  1. The for statement has been nested.
  • Since the number of words in the question has changed from 1 to 12, an outer for statement has been added. This for statement iterates QNO times, starting from 0, for the variable stage. The inner for loop after strlen(str[stage]) is equivalent to the for loop in the previous program.
  • The string to be inputted for each iteration is str[stage] (equivalent to str in the previous program). The number of characters to input varies depending on the string, so the strlen(str[stage]) statement calculates the length of the string str[stage] used for the question and stores it in the variable len.
  1. The character to be inputted is no longer str[i], but str[stage][i].

In the inner for loop, the character to be inputted is str[stage][i], which is equivalent to str[i] in the previous program.

Compile and run using the following commands:

cd ~/project
gcc -o typing2a typing2a.c -lcurses
./typing2a
Typing Practice

Shuffle the Order of the Questions (Method 1)

After practicing several times with the previous program, the next string that appears in the question will automatically come to mind, weakening the training effect. Now let's shuffle the order of the questions.

Navigate to the ~/project directory and create the project file typing2b.c:

cd ~/project
touch typing2b.c

Now let's take a look at the program. The code is as follows:

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "getputch.h"

#define QNO     12      /* Number of questions */

#define swap(type, x, y)    do { type t = x; x = y; y = t; } while (0)

int main(void)
{
    char *str[QNO] = {"book",   "computer", "default",  "comfort",
                      "monday", "power",    "light",    "music",
                      "programming", "dog", "video",    "include"};
    int i, stage;
    int qno[QNO];                   /* Order of questions */

    init_getputch();
    srand(time(NULL));              /* Set the seed for random numbers */
    for (i = 0; i < QNO; i++)
        qno[i] = i;
    for (i = QNO - 1; i > 0; i--) {
        int j = rand() % (i + 1);
        if (i != j)
            swap(int, qno[i], qno[j]);
	}
    printf("Start typing practice.\n");
    printf("Press the spacebar to begin.\n");
    while (getch() != ' ')          /* Wait until */
        ;                           /* the player presses the spacebar */

    for (stage = 0; stage < QNO; stage++) {
        int len = strlen(str[qno[stage]]); /* Number of characters in the string str[qno[stage]] */
        for (i = 0; i < len; i++) {
            /* Display the characters after str[qno[stage]][i] and return the cursor to the beginning */
            printf("%s \r", &str[qno[stage]][i]);
            fflush(stdout);
            while (getch() != str[qno[stage]][i])
                ;
        }
    }

    term_getputch();
    return 0;
}

In order to shuffle the order of the questions, the program introduces a new array named qno with element type int and size QNO (which is the number of strings in the questions, i.e. 12).

Before starting the typing practice, the first two for loops are used to assign values to each element of the array qno in the order of 0, 1, 2, ..., 11.

Similar to the previous program, all occurrences of str[stage] have been replaced with str[qno[stage]], because in each loop of this program, the question to be asked is based on str[qno[stage]].

  • When stage is 0; since the value of qno[0] is 2, the question shown by the program will be str[2], which is default.
  • When stage is 1; since the value of qno[1] is 1, the question shown by the program will be str[1], which is computer.

And so on. After practicing with the 12 strings, the program will end.

Compile and run using the following commands:

cd ~/project
gcc -o typing2b typing2b.c -lcurses
./typing2b
Typing Practice

Shuffle Question Order (Method 2)

The following program shuffles the order of the questions using a different method without using an array. This program requires fewer variables and is more concise compared to the previous program.

Navigate to the ~/project directory and create the project file typing2c.c:

cd ~/project
touch typing2c.c

Now let's take a look at the program. The code is as follows:

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "getputch.h"

#define QNO 12   /* Number of Questions */

#define swap(type, x, y)    do { type t = x; x = y; y = t; } while (0)

int main(void)
{
    char *str[QNO] = {"book",   "computer", "default",  "comfort",
                      "monday", "power",    "light",    "music",
                      "programming", "dog", "video",    "include"};
    int i, stage;

    init_getputch();
    srand(time(NULL));              /* Set random seed */

    for (i = QNO - 1; i > 0; i--) {  /* Shuffle the array str */
        int j = rand() % (i + 1);
        if (i != j)
            swap(char *, str[i], str[j]);
    }

    printf("Start Typing Practice.\n");
    printf("Press the spacebar to begin.\n");
    while (getch() != ' ')          /* Wait until */
        ;                           /* the player presses the spacebar */

    for (stage = 0; stage < QNO; stage++) {
        int len = strlen(str[stage]);	/* Number of characters in the string str[stage] */
        for (i = 0; i < len; i++) {
            /* Display the characters after str[stage][i] and return the cursor to the beginning */
            printf("%s \r", &str[stage][i]);
            fflush(stdout);
            while (getch() != str[stage][i])
                ;
        }
    }

    term_getputch();
    return 0;
}

Each element of the array str points to the strings book, computer, default, .... After swapping the values of str[0] and str[2], str[0] points to default and str[2] points to book.

The first for loop in the program (above code) is responsible for rearranging the pointers, which are the values of the elements in the array str, thus shuffling the elements. Since the objects being swapped are pointers, the first argument assigned to the function macro swap is char *.

In the second for loop in the main part of the program, each stage of the questions is returned to str[stage] (which is str[qno[stage]] in Listing 8-4, which is more complex). This is because the array str has been randomly rearranged, and by outputting str[0], str[1], ..., str[QNO-1] in order, a random question order is obtained.

One drawback of this method is that once the order of the words is shuffled, it cannot be restored. Please be aware of this.

Compile and run using the following commands:

cd ~/project
gcc -o typing2c typing2c.c -lcurses
./typing2c
Typing Practice

Keyboard Layout Associative Typing

Next, we are going to develop a software that allows players to practice typing while recalling the position of each key on the keyboard. Unlike regular typing exercises, players will need to input characters without any prompts. Additionally, different keyboards have different layouts, and here we will use the keyboard layout shown in the diagram below as the reference.

Typing Practice
Typing Practice

In the keyboard layout shown in the diagram, even when the [Shift] key is held down while pressing the [0] key, no information will be inputted.

Regarding the layout of this keyboard, we can observe the following points.

  • It consists of 4 layers of keys.
  • Each layer is divided into left-hand strike keys and right-hand strike keys, with left-hand striking the black keys and right-hand striking the blue keys.
  • There are keys that do not require the [Shift] key to be held down when struck, and there are keys that require the [Shift] key to be held down when struck.

We refer to the various sets classified by layer/hands/whether the [Shift] key is pressed as "blocks," and the entire keyboard consists of 4 Ɨ 2 Ɨ 2 = 16 blocks in total.

For example, the block of left-hand striking keys with the [Shift] key held down in the 3rd layer is [A], [S], [D], [F], [G] (handled respectively by the little finger, ring finger, middle finger, index finger, index finger).

In this training software, a block is presented as a question, but the software will use "?" to hide one character within this block. For example, for the following question, the player needs to associate the hidden "?" with the capital letter D and then input the letter.

A S ? F G

Code and Running Result

Navigate to the ~/project directory and create a project file named typing3.c:

cd ~/project
touch typing3.c

The program written according to the above guidelines is shown below:

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "getputch.h"

#define	NO			30			/* Number of exercises */
#define	KTYPE		16			/* Number of blocks */

int main(void)
{
    char *kstr[] = {"12345",  "67890-^\\",  /* Layer 1         */
                    "!\"#$%", "&'() =~|",   /* Layer 1 [Shift] */
                    "qwert",  "yuiop@[",    /* Layer 2         */
                    "QWERT",  "YUIOP`{",    /* Layer 2 [Shift] */
                    "asdfg",  "hjkl;:]",    /* Layer 3         */
                    "ASDFG",  "HJKL+*}",    /* Layer 3 [Shift] */
                    "zxcvb",  "nm,./\\",    /* Layer 4         */
                    "ZXCVB",  "NM<> _",	    /* Layer 4 [Shift] */
                    };
    int i, stage;
    clock_t	start, end;         /* Start and end times */

    init_getputch();
    srand(time(NULL));          /* Set the seed for random number generation */

    printf("Start typing association exercises.\n");
    printf("Please enter the hidden character indicated by '?'.\n");
    printf("Press the space key to start.\n");
    fflush(stdout);
    while (getch() != ' ')
        ;

    start = clock();            /* Start time */

    for (stage = 0; stage < NO; stage++) {
        int  k, p, key;
        char temp[10];

        do {
            k = rand() % KTYPE;
            p = rand() % strlen(kstr[k]);
            key = kstr[k][p];
        } while (key == ' ');

        strcpy(temp, kstr[k]);
        temp[p] = '?';
        printf("%s", temp);
        fflush(stdout);
        while (getch() != key)
            ;
        putchar('\n');
    }

    end = clock();              /* End time */
    printf("Time taken: %.1f seconds.\n", (double)(end - start) / CLOCKS_PER_SEC);

    term_getputch();
    return 0;
}

The macro KTYPE represents the number of blocks, which is 16, and the array kstr is used to store the strings consisting of characters from each block arranged from left to right.

In terms of training purposes, the question will not contain the character ?, so the last string for the block declared is NM<> _ instead of NM<>?_ (since the program does not use the space key to generate questions, it will not produce an error).

If your keyboard layout is different from the one shown in this example, please modify the declaration of the kstr array accordingly.

The first do while loop is responsible for generating the question.

  • The variable k indicates which block to generate the question from. Since this value corresponds to the index of the kstr array, it is set as a random number greater than or equal to 0 and less than KTYPE.

    Since the number of blocks KTYPE is 16, the generated random number will range from 0 to 15.

  • The variable p indicates which character within the block should be hidden to generate the question. Since this value corresponds to the index of the string used for generating the question within the block, it is set as a random number greater than or equal to 0 and less than the number of characters within the block.

    Assuming k is 0, the block consists of 5 characters, '12345', so p is set as a random number ranging from 0 to 4. Additionally, if k is 3, the block consists of 8 characters, '&'()=~|', so p is set as a random number ranging from 0 to 7.

  • The variable key represents the hidden character.

For example, if k is 0 and p is 2, the character '3' in the block '12345' is the key. Since the program has already assigned the space character '' to characters that should not be used for generating questions, the do-while loop is used to regenerate the question if the hidden character key is a space character.

Next, the strcpy function copies kstr[k] to temp, and assigns '?' to temp[p]. This generates the string 12?45 to be displayed on the screen.

If the program is able to display the string temp and read the character key input from the keyboard, it is correct. Like the previous typing exercise programs, this program does not accept incorrectly typed characters. After 30 training rounds, the program will end execution.

Compile and run using the following commands:

cd ~/project
gcc -o typing3 typing3.c -lcurses
./typing3
Start typing association exercises.
Please enter the hidden character indicated by '?'.
Press the space key to start.
AS?FG
?m,./\
67890-?\
?XCVB
zx?vb
!"?$%
ZXC?B
hjk?;:]
ā€¦(omit)ā€¦

Summary

In this project, you have learned how to create a typing practice program using the C programming language. This typing practice program provides users with a versatile interactive platform to enhance their typing skills, whether it's for coding or general communication. It provides a valuable tool for improving typing speed and accuracy.

Other C Tutorials you may like