Strings — Básico

Uma string em C é como um colar terminado com uma conta transparente — cada conta é um caractere, e a última é o terminador invisível \0 que sinaliza "o colar termina aqui".

Vetores de caracteres e strings

C não tem um tipo string dedicado. Uma string é essencialmente um vetor de caracteres terminado por \0 (o caractere nulo). O valor ASCII de \0 é 0, e ele marca o fim da string.

c char str[6] = {'H', 'e', 'l', 'l', 'o', '\0'};

Este vetor tem 6 elementos: 5 caracteres visíveis mais 1 \0. Sem \0, é apenas um vetor de caracteres comum e não pode ser usado como string.

Literais de string (aspas duplas) adicionam \0 automaticamente no final:

c char str[] = "Hello";

O comprimento do vetor é 6 (5 caracteres + 1 \0); o compilador calcula automaticamente. Você também pode especificar um comprimento maior; as posições extras são preenchidas com \0:

c char str[10] = "Hello";

str[5] até str[9] são todos \0.

💡 Dica: Aspas simples 'H' denotam um caractere (1 byte); aspas duplas "Hello" denotam uma string (com um \0 implícito). Eles não são a mesma coisa.

Declaração e inicialização de strings

Estilo de vetor de caracteres

c char s1[] = "abc"; char s2[10] = "abc"; char s3[] = {'a', 'b', 'c', '\0'};

Todos os três são equivalentes à string "abc". Note que s3 requer um \0 adicionado manualmente.

Estilo de ponteiro de caractere

c const char *s4 = "abc";

s4 aponta para o primeiro caractere de um literal de string. Literais de string são armazenados em uma região somente leitura; tentar modificá-los é comportamento indefinido:

c s4[0] = 'A';

Isso é errado. Vetores de caracteres, no entanto, são modificáveis:

c s1[0] = 'A';

Legal — o conteúdo de s1 torna-se "Abc".

⚠️ Atenção: Use const ao apontar um ponteiro para um literal de string; o compilador avisará se você tentar modificá-lo.

Ponteiros vs vetores

c char arr[] = "hello"; const char *ptr = "hello";

Entrada e saída de strings

printf e scanf

Use o especificador de formato %s para entrada e saída de strings:

c char name[20]; scanf("%s", name); printf("Hello, %s!\n", name);

scanf para de ler ao encontrar espaços em branco (espaço, nova linha, tabulação), então não consegue ler uma linha inteira contendo espaços.

scanf não verifica o tamanho do buffer; entrada que excede o comprimento do vetor causa estouro. Você pode limitar o comprimento de leitura:

c scanf("%19s", name);

Isso lê no máximo 19 caracteres, deixando 1 posição para \0.

puts e gets

puts imprime uma string e adiciona automaticamente uma nova linha:

c char msg[] = "Hello"; puts(msg);

Isso é equivalente a printf("%s\n", msg);.

gets lê uma linha inteira (incluindo espaços) até uma nova linha:

c char line[100]; gets(line);

🔥 Erro Comum: Nunca use gets! Ele não verifica o tamanho do buffer — se a entrada exceder a capacidade do vetor, ele escreve fora dos limites. É uma das funções C mais perigosas e foi completamente removida em C11.

fgets

gets é a substituição segura para gets:

c char line[100]; fgets(line, sizeof(line), stdin);

Os parâmetros são: o buffer de armazenamento, o número máximo de bytes a ler (incluindo \0), e o fluxo de entrada. gets retém a nova linha no final da string (se uma nova linha foi lida e ainda há espaço).

Padrão comum para remover a nova linha final:

`c #include <stdio.h> #include <string.h>

int main(void) { char line[100]; fgets(line, sizeof(line), stdin);

int len = strlen(line);
if (len > 0 && line[len - 1] == '\n') {
    line[len - 1] = '\0';
}

printf("[%s]\n", line);
return 0;

} `

Exemplo

Leia o nome do usuário e uma linha de autoapresentação:

`c #include <stdio.h> #include <string.h>

void trim_newline(char *s) { int len = strlen(s); if (len > 0 && s[len - 1] == '\n') { s[len - 1] = '\0'; } }

int main(void) { char name[30]; char intro[200];

printf("Enter your name: ");
fgets(name, sizeof(name), stdin);
trim_newline(name);

printf("Introduce yourself: ");
fgets(intro, sizeof(intro), stdin);
trim_newline(intro);

printf("\n--- Personal Info ---\n");
printf("Name: %s\n", name);
printf("Intro: %s\n", intro);

return 0;
▶ Experimente

} `

` ext Enter your name: Alice Introduce yourself: I am a C beginner

--- Personal Info --- Name: Alice Intro: I am a C beginner `

A função strlen

strlen é declarada em <string.h> e retorna o comprimento da string (não incluindo \0):

`c #include <string.h>

char s[] = "Hello"; printf("%zu\n", strlen(s)); `

Saída: 5. Note que sizeof(s) é 6 (incluindo \0), enquanto strlen(s) é 5 (excluindo \0).

Como strlen funciona: conta caracteres do início até encontrar \0:

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

Se um vetor de caracteres não termina com \0, strlen continuará lendo até encontrar acidentalmente um byte zero, o que é muito perigoso.

Introdução a ponteiros de caracteres

Um ponteiro de caractere pode apontar tanto para um vetor de caracteres quanto para um literal de string:

`c char arr[] = "world"; const char *ptr = "world";

ptr = arr; printf("%s\n", ptr); `

Um ponteiro pode ser reatribuído para apontar para uma string diferente, mas um nome de vetor é uma constante e não pode ser modificado:

c ptr = "another string";

Legal. Mas:

c arr = "another string";

Ilegal — um nome de vetor não pode ser atribuído.

Percorrendo uma string com ponteiro:

c const char *p = "Hello"; while (*p != '\0') { printf("%c", *p); p++; } printf("\n");

*p desreferencia para obter o caractere atual; p++ move para a próxima posição de caractere. O passo do ponteiro é determinado pelo tipo apontado; char * move 1 byte por passo.

Exemplo

Imprima uma string de trás para frente usando um ponteiro de caractere:

`c #include <stdio.h> #include <string.h>

void print_reverse(const char *s) { const char *p = s + strlen(s) - 1; while (p >= s) { putchar(*p); p--; } putchar('\n'); }

int main(void) { print_reverse("Hello"); print_reverse("ABCDEF"); return 0; } `

ext olleH FEDCBA

Primeiro, mova o ponteiro p para o último caractere da string (uma posição antes de \0), depois imprima os caracteres de trás para frente.

❓ Perguntas Frequentes

P: Qual a diferença entre 'a' e "a"? R: 'a' é uma constante de caractere ocupando 1 byte; "a" é uma constante de string ocupando 2 bytes ('a' mais '\0'), e seu tipo é char[].

P: Por que sizeof e strlen dão resultados diferentes para strings? R: sizeof retorna a memória total ocupada pelo vetor (incluindo \0); strlen retorna o número de caracteres antes de \0.

P: O que acontece quando gets lê uma nova linha? R: gets armazena a nova linha no buffer. Tipicamente você precisa verificá-la manualmente e substituí-la por \0 para removê-la.

P: Posso modificar o conteúdo de um literal de string através de um ponteiro de caractere? R: Não. Literais de string são armazenados em um segmento somente leitura; modificação é comportamento indefinido. Use um vetor de caracteres se precisar modificar o conteúdo.

📖 Resumo

📝 Exercícios

  1. Escreva um programa que use gets para ler uma linha de texto e conte o número de letras, dígitos e outros caracteres.
  2. Escreva uma função oid str_replace_char(char *s, char old, char new_ch) que substitua todas as ocorrências de old na string s por ew_ch.
  3. Escreva uma função que calcule o comprimento de uma string usando ponteiros de caracteres, sem usar strlen.
100%