Programa de Prática de Digitação Usando C

CBeginner
Pratique Agora

Introdução

Este projeto irá guiá-lo na criação de um programa de prática de digitação usando a linguagem de programação C. Você aprenderá como realizar vários exercícios de digitação, incluindo treinamento com strings únicas, múltiplas strings e digitação baseada no layout do teclado. Esses programas ajudarão a melhorar sua velocidade e precisão de digitação.

👀 Pré-visualização

Comece os exercícios de associação de digitação.
Por favor, insira o caractere oculto indicado por '?'.
Pressione a tecla espaço para começar.
AS?FG
?m,./\
67890-?\
?XCVB
zx?vb
!"?$%
ZXC?B
hjk?;:]
...(omit)...

🎯 Tarefas

Neste projeto, você aprenderá:

  • Como criar um programa de prática de digitação usando C.
  • Como implementar exercícios para digitação de strings únicas, múltiplas strings e associações de layout de teclado.
  • Como usar a biblioteca curses para operações de entrada e saída de tela.
  • Como embaralhar a ordem das perguntas para variedade na prática.

🏆 Conquistas

Após concluir este projeto, você será capaz de:

  • Criar um programa C para simular a prática de digitação.
  • Lidar com a entrada do usuário e validar a correção.
  • Gerar perguntas aleatórias e embaralhar a ordem das perguntas.
  • Utilizar a biblioteca curses para operações avançadas de entrada e saída de tela.

Ambiente do Projeto

O projeto requer o uso da biblioteca curses. Instale-a usando os seguintes comandos:

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

O objetivo do arquivo de cabeçalho getputch.h no código é fornecer uma biblioteca de funções de entrada e saída de tela multiplataforma, garantindo que o programa possa realizar corretamente operações de entrada e saída de tela em diferentes sistemas operacionais e ambientes de compilador, especialmente o tratamento da saída do caractere de nova linha.

Em seguida, apresentaremos exercícios básicos de digitação, que envolvem principalmente ponteiros, arrays de strings e estruturas de loop na linguagem C.

Demonstraremos a aplicação de arrays de strings, começando pela entrada básica de um único caractere até a prática com múltiplas palavras não ordenadas.

✨ Verificar Solução e Praticar

Inserir um Caractere

Navegue até o diretório ~/project e crie o arquivo do projeto typing1a.c:

cd ~/project
touch typing1a.c

Em seguida, precisamos escrever código C para criar um software de prática de digitação que permita a entrada de uma string. O programa é o seguinte:

#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;
}

O jogador é obrigado a inserir a string apontada pelo ponteiro str: How do you do?. Pela intercambialidade de ponteiros e arrays, os caracteres 'H', 'o', ..., '?' dentro da string podem ser representados sequencialmente como str[0], str[1], ..., str[13].

Além disso, a variável len representa o comprimento da string str e tem um valor inicial de 14. strlen() é usado para obter o comprimento da string.

O loop for incrementa o valor da variável i de 0, 1, 2, ... por len iterações para percorrer sequencialmente os caracteres dentro da string do início ao fim. Durante cada iteração, o caractere str[i] é 'H', 'o', ..., '?', que são os caracteres a serem inseridos. Esta prática de digitação não aceita caracteres incorretos (o programa não passará para o próximo caractere até que o jogador insira o caractere correto). Este controle é garantido pelo loop do, com as seguintes ações tomadas dentro do loop:

  • Atribuir o caractere de entrada (o valor de retorno da função getch) à variável ch.
  • Se o caractere ch for um caractere imprimível, exiba-o usando a função putch (excluindo caracteres não exibíveis, como nova linha e tabulação).
  • Se o caractere ch não for igual ao caractere a ser inserido str[i], emita o caractere de retrocesso '\b' para mover o cursor de volta uma casa. Isso garante que o próximo caractere de entrada seja exibido na mesma posição.

Após concluir as etapas mencionadas, a expressão de controle do loop do (ch != str[i]) é avaliada. Quando um caractere incorreto é inserido (quando ch não é igual a str[i]), o loop do começa novamente. Neste ponto, o programa não passa para o próximo caractere, mas executa a parte relevante dentro do loop do ... while novamente. Após inserir o caractere correto, o valor de i é incrementado pelo loop for, e o programa passa para o próximo caractere. Após inserir todos os caracteres, o programa exibirá o tempo gasto pelo jogador.

Compile e execute usando os seguintes comandos:

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

Você pode praticar várias vezes para melhorar sua velocidade. Se você achar How do you do? chato de praticar, você também pode escolher outra string para praticar.

✨ Verificar Solução e Praticar

Eliminando Caracteres Inseridos

Navegue até o diretório ~/project e crie o arquivo do projeto typing1b.c:

cd ~/project
touch typing1b.c

Agora, vamos dar uma olhada no programa. O código é o seguinte:

#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;
}

Este programa é ligeiramente diferente do anterior. Cada vez que o caractere correto é inserido, um caractere desaparecerá e os caracteres seguintes avançarão. Da mesma forma, o programa não passará para o próximo caractere, a menos que o jogador insira a tecla correta. Quando o jogador inserir corretamente todos os caracteres, todos os caracteres desaparecerão e o programa terminará.

Embora a operação realizada aqui seja mais "avançada" do que o programa anterior, o programa é, na verdade, mais curto. O corpo da instrução for consiste em apenas duas instruções curtas.

  • O &str[i] passado para a função printf na instrução printf("%s \r", &str[i]); é um ponteiro para str[i]. Como o valor da variável i é 0, o ponteiro &str[i] apontará para o caractere 'H', fazendo com que a tela exiba a string How do you do? começando com str[0], como mostrado na figura acima. O programa então emitirá caracteres de espaço em branco e um retorno de carro \r imediatamente após esta string, e retornará o cursor para a posição do 'H' no início da linha.
  • Se o caractere inserido (o valor de retorno da função getch) não for igual a str[i], ou seja, o caractere de entrada não for 'H', a instrução while fará um loop continuamente até que o jogador insira o caractere correto, momento em que a instrução while terminará.
  • O valor da variável i então se tornará 1 através da influência da instrução for. Como mostrado na figura acima, a instrução printf("%s \r", &str[i]); emitirá a string ow do you do? começando com str[1], depois emitirá caracteres de espaço em branco e um retorno de carro, e retornará o cursor para a posição do 'o' no início. Depois disso, com o efeito da instrução while subsequente, ele espera que o jogador insira corretamente 'o'.

Compile e execute usando os seguintes comandos:

cd ~/project
gcc -o typing1b typing1b.c -lcurses
./typing1a
Typing Practice
✨ Verificar Solução e Praticar

Inserir Múltiplas Strings

Em seguida, vamos estender o programa anterior para permitir que o jogador pratique a inserção de múltiplas strings.

Navegue até o diretório ~/project e crie um arquivo de projeto chamado typing2a.c:

cd ~/project
touch typing2a.c

Agora, vamos dar uma olhada no programa. O código é o seguinte:

#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;
}

Neste programa, após inserir uma string, a próxima string será exibida na mesma linha para o jogador inserir. Há um total de 12 strings disponíveis para prática.

Este programa é baseado principalmente no programa anterior, mas há algumas diferenças:

  1. A instrução for foi aninhada.
  • Como o número de palavras na questão mudou de 1 para 12, uma instrução for externa foi adicionada. Esta instrução for itera QNO vezes, começando de 0, para a variável stage. O loop for interno após strlen(str[stage]) é equivalente ao loop for no programa anterior.
  • A string a ser inserida para cada iteração é str[stage] (equivalente a str no programa anterior). O número de caracteres a serem inseridos varia dependendo da string, então a instrução strlen(str[stage]) calcula o comprimento da string str[stage] usada para a questão e a armazena na variável len.
  1. O caractere a ser inserido não é mais str[i], mas str[stage][i].

No loop for interno, o caractere a ser inserido é str[stage][i], que é equivalente a str[i] no programa anterior.

Compile e execute usando os seguintes comandos:

cd ~/project
gcc -o typing2a typing2a.c -lcurses
./typing2a
Typing Practice
✨ Verificar Solução e Praticar

Embaralhar a Ordem das Perguntas (Método 1)

Depois de praticar várias vezes com o programa anterior, a próxima string que aparece na pergunta virá automaticamente à mente, enfraquecendo o efeito do treinamento. Agora, vamos embaralhar a ordem das perguntas.

Navegue até o diretório ~/project e crie o arquivo do projeto typing2b.c:

cd ~/project
touch typing2b.c

Agora, vamos dar uma olhada no programa. O código é o seguinte:

#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;
}

Para embaralhar a ordem das perguntas, o programa introduz um novo array chamado qno com tipo de elemento int e tamanho QNO (que é o número de strings nas perguntas, ou seja, 12).

Antes de iniciar a prática de digitação, os dois primeiros loops for são usados para atribuir valores a cada elemento do array qno na ordem de 0, 1, 2, ..., 11.

Semelhante ao programa anterior, todas as ocorrências de str[stage] foram substituídas por str[qno[stage]], porque em cada loop deste programa, a pergunta a ser feita é baseada em str[qno[stage]].

  • Quando stage é 0; como o valor de qno[0] é 2, a pergunta mostrada pelo programa será str[2], que é default.
  • Quando stage é 1; como o valor de qno[1] é 1, a pergunta mostrada pelo programa será str[1], que é computer.

E assim por diante. Depois de praticar com as 12 strings, o programa terminará.

Compile e execute usando os seguintes comandos:

cd ~/project
gcc -o typing2b typing2b.c -lcurses
./typing2b
Typing Practice
✨ Verificar Solução e Praticar

Embaralhar a Ordem das Perguntas (Método 2)

O programa a seguir embaralha a ordem das perguntas usando um método diferente, sem usar um array. Este programa requer menos variáveis e é mais conciso em comparação com o programa anterior.

Navegue até o diretório ~/project e crie o arquivo do projeto typing2c.c:

cd ~/project
touch typing2c.c

Agora, vamos dar uma olhada no programa. O código é o seguinte:

#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;
}

Cada elemento do array str aponta para as strings book, computer, default, .... Após trocar os valores de str[0] e str[2], str[0] aponta para default e str[2] aponta para book.

O primeiro loop for no programa (código acima) é responsável por reorganizar os ponteiros, que são os valores dos elementos no array str, embaralhando assim os elementos. Como os objetos que estão sendo trocados são ponteiros, o primeiro argumento atribuído à função macro swap é char *.

No segundo loop for na parte principal do programa, cada estágio das perguntas é retornado para str[stage] (que é str[qno[stage]] na Listagem 8-4, que é mais complexa). Isso ocorre porque o array str foi reorganizado aleatoriamente e, ao exibir str[0], str[1], ..., str[QNO-1] em ordem, uma ordem de perguntas aleatória é obtida.

Uma desvantagem deste método é que uma vez que a ordem das palavras é embaralhada, ela não pode ser restaurada. Esteja ciente disso.

Compile e execute usando os seguintes comandos:

cd ~/project
gcc -o typing2c typing2c.c -lcurses
./typing2c
Typing Practice
✨ Verificar Solução e Praticar

Digitação Associativa de Layout do Teclado

Em seguida, vamos desenvolver um software que permite aos jogadores praticar a digitação enquanto recordam a posição de cada tecla no teclado. Ao contrário dos exercícios de digitação regulares, os jogadores precisarão inserir caracteres sem nenhum aviso. Além disso, diferentes teclados têm layouts diferentes, e aqui usaremos o layout do teclado mostrado no diagrama abaixo como referência.

Typing Practice
Typing Practice

No layout do teclado mostrado no diagrama, mesmo quando a tecla [Shift] é mantida pressionada ao pressionar a tecla [0], nenhuma informação será inserida.

Em relação ao layout deste teclado, podemos observar os seguintes pontos.

  • Consiste em 4 camadas de teclas.
  • Cada camada é dividida em teclas de ataque da mão esquerda e teclas de ataque da mão direita, com a mão esquerda atacando as teclas pretas e a mão direita atacando as teclas azuis.
  • Existem teclas que não exigem que a tecla [Shift] seja mantida pressionada quando pressionadas, e existem teclas que exigem que a tecla [Shift] seja mantida pressionada quando pressionadas.

Referimo-nos aos vários conjuntos classificados por camada/mãos/se a tecla [Shift] é pressionada como "blocos", e o teclado inteiro consiste em 4 × 2 × 2 = 16 blocos no total.

Por exemplo, o bloco de teclas de ataque da mão esquerda com a tecla [Shift] pressionada na 3ª camada é [A], [S], [D], [F], [G] (manuseadas respectivamente pelo dedo mínimo, dedo anelar, dedo médio, dedo indicador, dedo indicador).

Neste software de treinamento, um bloco é apresentado como uma pergunta, mas o software usará "?" para ocultar um caractere dentro deste bloco. Por exemplo, para a seguinte pergunta, o jogador precisa associar o "?" oculto com a letra maiúscula D e, em seguida, inserir a letra.

A S ? F G
✨ Verificar Solução e Praticar

Código e Resultado da Execução

Navegue até o diretório ~/project e crie um arquivo de projeto chamado typing3.c:

cd ~/project
touch typing3.c

O programa escrito de acordo com as diretrizes acima é mostrado abaixo:

#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;
}

A macro KTYPE representa o número de blocos, que é 16, e o array kstr é usado para armazenar as strings consistindo em caracteres de cada bloco, organizados da esquerda para a direita.

Em termos de propósitos de treinamento, a pergunta não conterá o caractere ?, então a última string para o bloco declarado é NM<> _ em vez de NM<>?_ (já que o programa não usa a tecla de espaço para gerar perguntas, ele não produzirá um erro).

Se o layout do seu teclado for diferente do mostrado neste exemplo, modifique a declaração do array kstr de acordo.

O primeiro loop do while é responsável por gerar a pergunta.

  • A variável k indica de qual bloco gerar a pergunta. Como este valor corresponde ao índice do array kstr, ele é definido como um número aleatório maior ou igual a 0 e menor que KTYPE.

    Como o número de blocos KTYPE é 16, o número aleatório gerado variará de 0 a 15.

  • A variável p indica qual caractere dentro do bloco deve ser ocultado para gerar a pergunta. Como este valor corresponde ao índice da string usada para gerar a pergunta dentro do bloco, ele é definido como um número aleatório maior ou igual a 0 e menor que o número de caracteres dentro do bloco.

    Assumindo que k é 0, o bloco consiste em 5 caracteres, '12345', então p é definido como um número aleatório variando de 0 a 4. Além disso, se k é 3, o bloco consiste em 8 caracteres, '&'()=~|', então p é definido como um número aleatório variando de 0 a 7.

  • A variável key representa o caractere oculto.

Por exemplo, se k é 0 e p é 2, o caractere '3' no bloco '12345' é a key. Como o programa já atribuiu o caractere espaço '' a caracteres que não devem ser usados para gerar perguntas, o loop do-while é usado para regenerar a pergunta se o caractere oculto key for um caractere espaço.

Em seguida, a função strcpy copia kstr[k] para temp e atribui '?' a temp[p]. Isso gera a string 12?45 para ser exibida na tela.

Se o programa for capaz de exibir a string temp e ler o caractere key inserido do teclado, ele estará correto. Como os programas de exercícios de digitação anteriores, este programa não aceita caracteres digitados incorretamente. Após 30 rodadas de treinamento, o programa encerrará a execução.

Compile e execute usando os seguintes comandos:

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)…
✨ Verificar Solução e Praticar

Resumo

Neste projeto, você aprendeu como criar um programa de prática de digitação usando a linguagem de programação C. Este programa de prática de digitação oferece aos usuários uma plataforma interativa versátil para aprimorar suas habilidades de digitação, seja para codificação ou comunicação geral. Ele fornece uma ferramenta valiosa para melhorar a velocidade e a precisão da digitação.