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.
Obs.: Executar e Corrigir enviam seu código ao Wandbox, um serviço externo e gratuito de compilação, que o executa com gcc.
strlen; conte você mesmo."Executar" roda seu código com a entrada acima. "Corrigir" testa com 4 entradas preparadas.
'\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; }
'\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.caractere: código", um por linha. O código do caractere deve ser mostrado em decimal."Executar" roda seu código com a entrada acima. "Corrigir" testa com 4 entradas preparadas.
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; }
'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."Executar" roda seu código com a entrada acima. "Corrigir" testa com 4 entradas preparadas.
'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; }
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])."Executar" roda seu código com a entrada acima. "Corrigir" testa com 5 entradas preparadas.
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; }
==, 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).printf("%s\n", s)."Executar" roda seu código com a entrada acima. "Corrigir" testa com 5 entradas preparadas.
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; }
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.É 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."Executar" roda seu código com a entrada acima. "Corrigir" testa com 6 entradas preparadas.
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; }
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.letra: vezes", uma por linha, na ordem de a até z. Letras que não aparecem nenhuma vez não são mostradas."Executar" roda seu código com a entrada acima. "Corrigir" testa com 4 entradas preparadas.
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; }
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.As strings são iguais". Use strcmp para comparar."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; }
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.fgets (a entrada pode não terminar com quebra de linha)."Executar" roda seu código com a entrada acima. "Corrigir" testa com 5 entradas preparadas.
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; }
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."Executar" roda seu código com a entrada acima. "Corrigir" testa com 5 entradas preparadas.
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; }
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).<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."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; }
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".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."Executar" roda seu código com a entrada acima. "Corrigir" testa com 6 entradas preparadas.
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; }
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.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."Executar" roda seu código com a entrada acima. "Corrigir" testa com 6 entradas preparadas.
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; }
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).