Exercícios de caracteres e strings em C

Reunimos 13 exercícios, do iniciante ao avançado, que usam o tipo char e strings (arrays de caracteres). Em todos eles, a chave é ficar atento ao '\0', que marca o fim da string. Escreva seu código no navegador e clique em "Corrigir": ele é executado com gcc de verdade em várias entradas e a saída é verificada.

Como usar estes exercícios
  1. Leia o enunciado e o exemplo de execução e escreva seu código no campo abaixo
  2. Clique em "▶ Executar" para testar com a sua própria entrada
  3. Clique em "✔ Corrigir" para verificar a saída com várias entradas preparadas
  4. Travou? Abra a "Dica". Resolveu? Compare com "Solução e explicação"
Regras da correção
  • Imprima a saída exatamente como no exemplo. Não imprima mensagens pedindo a entrada, como "Digite um número"
  • Espaços no fim das linhas e linhas em branco no final são ignorados
  • Seu código é salvo automaticamente neste navegador

Obs.: Executar e Corrigir enviam seu código ao Wandbox, um serviço externo e gratuito de compilação, que o executa com gcc.

13 exercícios (Iniciante 4 · Intermediário 5 · Avançado 4)

Strings (13 exercícios)

S01 Iniciante

Exercício 1. Contar o tamanho de uma string

Leia uma string sem espaços (de 1 a 99 caracteres, só letras, dígitos e símbolos) e mostre o seu tamanho (número de caracteres). Não use strlen; conte você mesmo.
Exemplo de execução (a entrada está sublinhada)
hello Tamanho: 5
Seu código
"Executar" roda seu código com a entrada acima. "Corrigir" testa com 4 entradas preparadas.
Em C, logo depois do último caractere de uma string há o caractere nulo '\0'. Aumente o índice len a partir de 0 e pare quando s[len] for '\0': o valor de len nesse momento é o tamanho.
#include <stdio.h>

int main(void) {
    char s[100];
    scanf("%99s", s);

    int len = 0;
    while (s[len] != '\0') {
        len++;
    }
    printf("Tamanho: %d\n", len);
    return 0;
}
Explicação: O tamanho do array (100) e o tamanho da string são coisas diferentes. O tamanho da string é determinado pela posição do '\0', e o próprio '\0' não entra na contagem. O 99 em scanf("%99s", s) significa "ler no máximo 99 caracteres": assim sobra uma posição para o '\0' e o array não transborda.
S02 Iniciante

Exercício 2. Mostrar os códigos dos caracteres

Leia uma string sem espaços (de 1 a 99 caracteres, só letras, dígitos e símbolos) e mostre cada caractere no formato "caractere: código", um por linha. O código do caractere deve ser mostrado em decimal.
Exemplo de execução (a entrada está sublinhada)
ABC A: 65 B: 66 C: 67
Seu código
"Executar" roda seu código com a entrada acima. "Corrigir" testa com 4 entradas preparadas.
Por dentro, um valor do tipo char é um código de caractere (um inteiro). O mesmo s[i], mostrado com %c, vira o caractere, e mostrado com %d, vira um número.
#include <stdio.h>

int main(void) {
    char s[100];
    scanf("%99s", s);

    for (int i = 0; s[i] != '\0'; i++) {
        printf("%c: %d\n", s[i], s[i]);
    }
    return 0;
}
Explicação: O código do caractere '0' é 48, que é diferente do número 0. Usando o fato de que "'0' a '9' têm códigos consecutivos" (garantido pelo padrão C) e de que "'A' a 'Z' e 'a' a 'z' também são consecutivos" (propriedade do ASCII), dá para fazer conversões como a do próximo exercício. Com a condição do laço s[i] != '\0', você percorre até o fim sem precisar calcular o tamanho antes.
S03 Iniciante

Exercício 3. Trocar maiúsculas e minúsculas

Leia uma string sem espaços (de 1 a 99 caracteres, só letras, dígitos e símbolos) e mostre-a trocando as letras maiúsculas por minúsculas e as minúsculas por maiúsculas. Os demais caracteres são mostrados como estão.
Exemplo de execução (a entrada está sublinhada)
Hello123 hELLO123
Seu código
"Executar" roda seu código com a entrada acima. "Corrigir" testa com 4 entradas preparadas.
Se 'a' <= c && c <= 'z', é minúscula. Em ASCII, a diferença entre os códigos de minúsculas e maiúsculas é constante, então c - 'a' + 'A' dá a maiúscula.
#include <stdio.h>

int main(void) {
    char s[100];
    scanf("%99s", s);

    for (int i = 0; s[i] != '\0'; i++) {
        if ('a' <= s[i] && s[i] <= 'z') {
            s[i] = s[i] - 'a' + 'A';
        } else if ('A' <= s[i] && s[i] <= 'Z') {
            s[i] = s[i] - 'A' + 'a';
        }
    }
    printf("%s\n", s);
    return 0;
}
Explicação: Se o else if virar if, depois de converter minúscula → maiúscula, o mesmo caractere é imediatamente convertido de volta de maiúscula → minúscula. Também dá para escrever com toupper / tolower de <ctype.h> (é mais seguro passar o argumento com o cast (unsigned char)s[i]).
S04 Iniciante

Exercício 4. Ocorrências de um caractere

Leia uma string sem espaços (de 1 a 99 caracteres) e um caractere c, separados por espaço, e mostre quantas vezes c aparece na string. Maiúsculas e minúsculas são diferentes.
Exemplo de execução (a entrada está sublinhada)
banana a Quantidade: 3
Seu código
"Executar" roda seu código com a entrada acima. "Corrigir" testa com 5 entradas preparadas.
Repita enquanto s[i] != '\0' e conte quando s[i] == c. Para comparar um único caractere, dá para usar ==.
#include <stdio.h>

int main(void) {
    char s[100];
    char c;
    scanf("%99s %c", s, &c);

    int count = 0;
    for (int i = 0; s[i] != '\0'; i++) {
        if (s[i] == c) count++;
    }
    printf("Quantidade: %d\n", count);
    return 0;
}
Explicação: Um único caractere (char) pode ser comparado com ==, mas duas strings não podem ser comparadas com == (isso compararia os endereços iniciais dos arrays). Para comparar strings, use strcmp. O espaço antes de %c no formato "%99s %c" serve para pular o espaço depois da string (porque %c leria o espaço também como um caractere).
S05 Intermediário

Exercício 5. Inverter uma string

Leia uma string sem espaços (de 1 a 99 caracteres) e mostre-a com os caracteres em ordem inversa. Não basta mostrar: inverta o próprio conteúdo do array e depois mostre com printf("%s\n", s).
Exemplo de execução (a entrada está sublinhada)
hello olleh
Seu código
"Executar" roda seu código com a entrada acima. "Corrigir" testa com 5 entradas preparadas.
Sendo len o tamanho, troque a partir das duas pontas: s[0] com s[len - 1], s[1] com s[len - 2], … As trocas terminam depois de len / 2 vezes.
#include <stdio.h>
#include <string.h>

int main(void) {
    char s[100];
    scanf("%99s", s);

    size_t len = strlen(s);
    for (size_t i = 0; i < len / 2; i++) {
        char tmp = s[i];
        s[i] = s[len - 1 - i];
        s[len - 1 - i] = tmp;
    }
    printf("%s\n", s);
    return 0;
}
Explicação: Se você continuar trocando até len vezes, a partir da metade os caracteres são trocados de novo e voltam ao lugar original. A posição do par é len - 1 - i, e não len - i (s[len] é o '\0'; trazê-lo para o início deixa a string vazia). O retorno de strlen é do tipo size_t, então usar size_t também no índice evita avisos de mistura de sinais.
S06 Intermediário

Exercício 6. Palíndromo

Leia uma string sem espaços (de 1 a 99 caracteres) e mostre "É palíndromo" se ela for igual lida de frente para trás e de trás para frente (um palíndromo), ou "Não é palíndromo" caso contrário. Maiúsculas e minúsculas são diferentes.
Exemplo de execução (a entrada está sublinhada)
level É palíndromo
Seu código
"Executar" roda seu código com a entrada acima. "Corrigir" testa com 6 entradas preparadas.
Como no exercício anterior, vá das duas pontas para o meio comparando s[i] com s[len - 1 - i]. Se houver diferença em uma única posição, não é palíndromo: coloque a flag em 0 e use break.
#include <stdio.h>
#include <string.h>

int main(void) {
    char s[100];
    scanf("%99s", s);

    size_t len = strlen(s);
    int is_pal = 1;
    for (size_t i = 0; i < len / 2; i++) {
        if (s[i] != s[len - 1 - i]) {
            is_pal = 0;
            break;
        }
    }

    if (is_pal) {
        printf("É palíndromo\n");
    } else {
        printf("Não é palíndromo\n");
    }
    return 0;
}
Explicação: Para "é palíndromo se tudo coincidir", é errado mostrar a resposta dentro do laço, como if (coincide) É palíndromo. O padrão "uma única diferença já reprova, e se não houver diferença até o fim, aprova" é escrito tipicamente com uma variável flag. Quando o tamanho é ímpar, o caractere do meio só seria comparado consigo mesmo, então não precisa ser verificado.
S07 Intermediário

Exercício 7. Ocorrências de cada letra

Leia uma string formada só por letras minúsculas (de 1 a 99 caracteres) e, para cada letra que aparece na string, mostre "letra: vezes", uma por linha, na ordem de a até z. Letras que não aparecem nenhuma vez não são mostradas.
Exemplo de execução (a entrada está sublinhada)
banana a: 3 b: 1 n: 2
Seu código
"Executar" roda seu código com a entrada acima. "Corrigir" testa com 4 entradas preparadas.
Prepare um array int cnt[26] = {0}; para contar 26 valores. Um caractere c vira um número de 0 a 25 com c - 'a', então dá para contar com cnt[s[i] - 'a']++;.
#include <stdio.h>

int main(void) {
    char s[100];
    scanf("%99s", s);

    int cnt[26] = {0};
    for (int i = 0; s[i] != '\0'; i++) {
        cnt[s[i] - 'a']++;
    }

    for (int k = 0; k < 26; k++) {
        if (cnt[k] > 0) {
            printf("%c: %d\n", 'a' + k, cnt[k]);
        }
    }
    return 0;
}
Explicação: O ponto-chave é combinar a conversão "caractere → índice" (s[i] - 'a') com a conversão "índice → caractere" ('a' + k). Se a entrada tiver algo que não seja letra minúscula, o índice sai do intervalo 0 a 25 e o programa escreve fora dos limites; por isso, na prática, verifique 'a' <= s[i] && s[i] <= 'z' antes de contar.
S08 Intermediário

Exercício 8. Ordem alfabética

Leia duas strings sem espaços (cada uma de 1 a 99 caracteres, só letras e dígitos) separadas por espaço e mostre na 1ª linha a que vem antes na ordem lexicográfica (ordem dos códigos de caracteres) e na 2ª linha a que vem depois. Se as duas forem iguais, mostre "As strings são iguais". Use strcmp para comparar.
Exemplo de execução (a entrada está sublinhada)
banana apple apple banana
Seu código
"Executar" roda seu código com a entrada acima. "Corrigir" testa com 5 entradas preparadas.
strcmp(a, b) devolve um valor negativo se a vier antes, 0 se forem iguais e um valor positivo se a vier depois. Se a vier depois, troque o conteúdo de a e b usando um array auxiliar e strcpy, e depois mostre.
#include <stdio.h>
#include <string.h>

int main(void) {
    char a[100], b[100];
    scanf("%99s %99s", a, b);

    int r = strcmp(a, b);
    if (r == 0) {
        printf("As strings são iguais\n");
        return 0;
    }
    if (r > 0) {
        char tmp[100];
        strcpy(tmp, a);
        strcpy(a, b);
        strcpy(b, tmp);
    }
    printf("%s\n%s\n", a, b);
    return 0;
}
Explicação: O retorno de strcmp não é necessariamente −1 ou 1, então teste com > 0 e < 0, e não com == 1. Arrays não podem ser atribuídos, como em a = b;, então use strcpy para copiar o conteúdo. Como a comparação segue a ordem dos códigos de caracteres, as maiúsculas (65 a 90) vêm antes das minúsculas (97 a 122) (Zoo vem antes de apple). E como app é o início de apple, a mais curta vem antes.
S09 Intermediário

Exercício 9. Contar palavras

Leia uma linha de texto formada por letras, dígitos e espaços (até 200 caracteres) e mostre o número de palavras. Uma palavra é uma sequência de caracteres separada por espaços, e os espaços podem ser consecutivos e também aparecer no início ou no fim da linha. Se a linha tiver só espaços, o número de palavras é 0. Leia a linha com fgets (a entrada pode não terminar com quebra de linha).
Exemplo de execução (a entrada está sublinhada)
I have a pen Palavras: 4
Seu código
"Executar" roda seu código com a entrada acima. "Corrigir" testa com 5 entradas preparadas.
Use uma flag in_word que indica "estou dentro de uma palavra agora". Em um espaço (ou quebra de linha), in_word = 0; em qualquer outro caractere, se in_word for 0, é o início de uma palavra: some 1 à contagem e faça in_word = 1.
#include <stdio.h>

int main(void) {
    char s[256];
    if (fgets(s, sizeof s, stdin) == NULL) {
        s[0] = '\0';
    }

    int count = 0, in_word = 0;
    for (int i = 0; s[i] != '\0'; i++) {
        if (s[i] == ' ' || s[i] == '\n') {
            in_word = 0;
        } else if (!in_word) {
            in_word = 1;
            count++;
        }
    }
    printf("Palavras: %d\n", count);
    return 0;
}
Explicação: Contando "número de espaços + 1", o resultado não bate quando há espaços consecutivos ou no início/fim. Contar quantos inícios de palavra existem é o jeito seguro. fgets também coloca no array a quebra de linha '\n' do fim da linha lida (se a entrada não terminar com quebra de linha, ela não aparece), por isso aqui a quebra de linha também é tratada como separador. scanf("%s") para de ler no espaço, então não consegue ler linhas com espaços.
S10 Avançado

Exercício 10. Cifra de César

Leia um inteiro K (0 ≤ K ≤ 25) e uma string sem espaços (de 1 a 99 caracteres, só letras, dígitos e símbolos), separados por espaço. Mostre a string deslocando cada letra K posições para a frente no alfabeto (depois do z volta para o a). Maiúsculas continuam maiúsculas e minúsculas continuam minúsculas; caracteres que não são letras são mostrados como estão.
Exemplo de execução (a entrada está sublinhada)
3 abcxyz defabc
Seu código
"Executar" roda seu código com a entrada acima. "Corrigir" testa com 5 entradas preparadas.
Para uma minúscula, primeiro transforme-a em um número de 0 a 25 com s[i] - 'a', some K, pegue o resto da divisão por 26 e some 'a' para voltar a ser caractere. Para maiúsculas, a ideia é a mesma, usando 'A' como base.
#include <stdio.h>

int main(void) {
    int k;
    char s[100];
    scanf("%d %99s", &k, s);

    for (int i = 0; s[i] != '\0'; i++) {
        if ('a' <= s[i] && s[i] <= 'z') {
            s[i] = 'a' + (s[i] - 'a' + k) % 26;
        } else if ('A' <= s[i] && s[i] <= 'Z') {
            s[i] = 'A' + (s[i] - 'A' + k) % 26;
        }
    }
    printf("%s\n", s);
    return 0;
}
Explicação: Só com s[i] + k, ao passar de 'z' o caractere vira um símbolo como {. Converter primeiro para um número de 0 a 25 e depois aplicar % 26 é a técnica padrão para cálculos que dão a volta, como em um círculo. Cifrando duas vezes com K=13, você volta ao texto original (ROT13).
S11 Avançado

Exercício 11. Escrever o próprio strlen e strcat

Complete, sem usar <string.h>, a função my_strlen, que devolve o tamanho de uma string, e a função my_strcat, que junta src ao final da string dst. Use o main exatamente como está no modelo. A entrada são duas strings sem espaços (cada uma de 1 a 49 caracteres), e o programa mostra a string concatenada e o seu tamanho.
Exemplo de execução (a entrada está sublinhada)
abc def abcdef Tamanho: 6
Seu código
"Executar" roda seu código com a entrada acima. "Corrigir" testa com 4 entradas preparadas.
my_strcat tem duas etapas. (1) Encontrar a posição do '\0' de dst (é ali que a escrita começa). (2) A partir dali, copiar src caractere por caractere e, no final, escrever também o '\0'.
#include <stdio.h>

int my_strlen(const char *s) {
    int len = 0;
    while (s[len] != '\0') {
        len++;
    }
    return len;
}

void my_strcat(char *dst, const char *src) {
    int i = my_strlen(dst);
    int j = 0;
    while (src[j] != '\0') {
        dst[i] = src[j];
        i++;
        j++;
    }
    dst[i] = '\0';
}

int main(void) {
    char a[100], b[50];
    scanf("%49s %49s", a, b);
    my_strcat(a, b);
    printf("%s\n", a);
    printf("Tamanho: %d\n", my_strlen(a));
    return 0;
}
Explicação: Se você esquecer o dst[i] = '\0'; do final, não se sabe o que vem depois da string concatenada, e o printf pode mostrar lixo ou ler além do fim do array. Além disso, o array a, que recebe a concatenação, precisa ter tamanho para os dois comprimentos + 1 caractere (aqui, 49 + 49 + 1 ≤ 100). O strcat padrão também não verifica o tamanho, então a responsabilidade é de quem chama. O const nos parâmetros é a promessa de que "esta função não altera o conteúdo".
S12 Avançado

Exercício 12. Anagramas

Leia duas strings formadas só por letras minúsculas (cada uma de 1 a 99 caracteres) separadas por espaço e mostre "São anagramas" se, reordenando os caracteres de uma, for possível obter a outra (anagramas), ou "Não são anagramas" caso contrário. Strings iguais também contam como anagramas.
Exemplo de execução (a entrada está sublinhada)
listen silent São anagramas
Seu código
"Executar" roda seu código com a entrada acima. "Corrigir" testa com 6 entradas preparadas.
Se a quantidade de ocorrências de cada letra for igual, são anagramas. Em int cnt[26] = {0};, faça +1 para cada letra da primeira string e −1 para cada letra da segunda; no final, verifique se os 26 valores são todos 0.
#include <stdio.h>

int main(void) {
    char a[100], b[100];
    scanf("%99s %99s", a, b);

    int cnt[26] = {0};
    for (int i = 0; a[i] != '\0'; i++) {
        cnt[a[i] - 'a']++;
    }
    for (int i = 0; b[i] != '\0'; i++) {
        cnt[b[i] - 'a']--;
    }

    int ok = 1;
    for (int k = 0; k < 26; k++) {
        if (cnt[k] != 0) {
            ok = 0;
            break;
        }
    }

    if (ok) {
        printf("São anagramas\n");
    } else {
        printf("Não são anagramas\n");
    }
    return 0;
}
Explicação: Verificando só "se todas as letras de a estão em b", você deixa passar casos em que as quantidades são diferentes, como aab e abb. Comparando as quantidades de ocorrências, até strings de tamanhos diferentes (abc e ab) são naturalmente consideradas "diferentes". Outra forma é ordenar cada uma das strings e comparar com strcmp.
S13 Avançado

Exercício 13. Compressão por run-length

Leia uma string formada só por letras (de 1 a 99 caracteres) e mostre-a substituindo cada trecho de caracteres iguais seguidos por "o caractere e quantas vezes ele se repete". Por exemplo, aaabccdddd vira a3b1c2d4. Trechos de um só caractere também levam a contagem 1. Maiúsculas e minúsculas são tratadas como caracteres diferentes.
Exemplo de execução (a entrada está sublinhada)
aaabccdddd a3b1c2d4
Seu código
"Executar" roda seu código com a entrada acima. "Corrigir" testa com 6 entradas preparadas.
Guarde o caractere c do índice i e, enquanto s[i] == c, aumente i e a contagem. Ao chegar a um caractere diferente (ou ao '\0'), mostre "c e a contagem" e comece a contar o próximo bloco a partir dali.
#include <stdio.h>

int main(void) {
    char s[100];
    scanf("%99s", s);

    int i = 0;
    while (s[i] != '\0') {
        char c = s[i];
        int count = 0;
        while (s[i] == c) {
            count++;
            i++;
        }
        printf("%c%d", c, count);
    }
    printf("\n");
    return 0;
}
Explicação: Como c é uma letra, o while (s[i] == c) interno sempre para ao chegar no '\0' e nunca sai do array. Também dá para escrever comparando s[i] == s[i + 1], mas assim é fácil esquecer de mostrar o último bloco. A contagem pode ter 2 dígitos ou mais, então mostre com %d (com '0' + count, quebra a partir de 10).

Revise estas aulas

← Voltar para todos os exercícios