C string.h
Esta é a página de consulta rápida do <string.h>, a biblioteca de funções para texto (as str…) e para blocos de memória (as mem…). Aqui estão todas, em tabelas: o que cada uma faz, o que devolve, um exemplo com a saída real e a aula onde ela é explicada. Para aprender com calma, veja as aulas Strings, Funções de String e Ponteiros e Strings.
Todas as saídas foram produzidas de verdade: no gcc 15.2 da máquina da Ana (Linux de 64 bits, pasta ~/c/ref, comando gcc -std=c23 -Wall -Wextra) e no editor do guia (Clang em WebAssembly). Quando os dois diferem, a tabela diz.
Atalhos: Antes de tudo · Tamanho, cópia e junção · Comparar · Procurar e dividir · Blocos de memória · strerror · Qual usar · Editor × gcc · Erros comuns · Experimente
Antes de tudo: três regras
- Uma string é um array de
charque termina em'\0' - Toda função
str…anda pelo texto até achar o'\0'(o caractere de código zero). Sem ele, a função continua lendo a memória que vem depois. Aula: Strings. - Nenhuma função sabe o tamanho do seu array
- Elas recebem só um ponteiro para o primeiro caractere (aula Ponteiros e Strings). Quem garante que cabe é você. Um
strcpyque não cabe escreve além do fim do array, sem erro nenhum na hora. size_t- É o tipo dos tamanhos (um inteiro sem sinal). Mostre com
%zu:printf("%zu", strlen(nome)). Aula: sizeof.
Nas tabelas, d é o destino (onde a função escreve), o é a origem (de onde ela lê), s é uma string e n é um número de bytes.
Tamanho, cópia e junção
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void) {
char nome[20] = "Ana";
printf("strlen=%zu sizeof=%zu\n", strlen(nome), sizeof nome);
char copia[20];
strcpy(copia, nome);
printf("strcpy: [%s]\n", copia);
strcat(copia, " Souza");
printf("strcat: [%s]\n", copia);
char curto[5];
strncpy(curto, "Banana", sizeof curto - 1);
curto[sizeof curto - 1] = '\0';
printf("strncpy: [%s]\n", curto);
char frase[20] = "Oi";
strncat(frase, ", Ana Souza", 5);
printf("strncat: [%s]\n", frase);
char *dup = strdup("Caderno");
char *pedaco = strndup("Caderno", 4);
printf("strdup: [%s] strndup: [%s]\n", dup, pedaco);
free(dup);
free(pedaco);
char destino[20] = "";
char *fim = memccpy(destino, "maçã;pera", ';', sizeof destino);
printf("memccpy: [%.*s] copiou %td bytes\n", (int)(fim - destino), destino, fim - destino);
return 0;
}
$ gcc -std=c23 -Wall -Wextra copiar.c -o copiar $ ./copiar strlen=3 sizeof=20 strcpy: [Ana] strcat: [Ana Souza] strncpy: [Bana] strncat: [Oi, Ana] strdup: [Caderno] strndup: [Cade] memccpy: [maçã;] copiou 7 bytes
No editor, este programa não compila: a biblioteca C do editor só mostra o strndup e o memccpy com um #define _DEFAULT_SOURCE antes dos #include (veja Editor × gcc). Com essa linha, a saída é idêntica.
| Função | O que faz | Devolve | Exemplo → resultado | Aula |
|---|---|---|---|---|
strlen(s)"string length" | Conta os bytes até o '\0' (sem contar o '\0'). | size_t | strlen("Ana") → 3; strlen("maçã") → 6 (o ç e o ã têm 2 bytes cada) | Funções de String |
strcpy(d, o)"string copy" | Copia o para d, com o '\0'. Não confere se cabe. | d | strcpy(copia, "Ana") → [Ana] | Funções de String |
strncpy(d, o, n) | Copia no máximo n bytes. Se o é mais curta, completa com '\0' até n; se é mais longa, não põe o '\0'. | d | strncpy(curto, "Banana", 4) + curto[4] = '\0' → [Bana] | Segurança |
strcat(d, o)"concatenate", juntar | Acrescenta o no fim de d. d já tem de ser uma string (com '\0') e ter espaço. | d | "Ana" + " Souza" → [Ana Souza] | Funções de String |
strncat(d, o, n) | Acrescenta no máximo n bytes de o e sempre põe o '\0' (por isso d precisa de strlen(d) + n + 1 bytes). | d | strncat(frase, ", Ana Souza", 5) → [Oi, Ana] | Funções de String |
strdup(s) C23 | Faz uma cópia de s numa memória nova, reservada com malloc. Você dá o free. | a cópia, ou NULL se faltou memória | strdup("Caderno") → [Caderno] | Strings Dinâmicas |
strndup(s, n) C23 | Como strdup, mas copia no máximo n bytes e sempre põe o '\0'. | a cópia, ou NULL | strndup("Caderno", 4) → [Cade] | Strings Dinâmicas |
memccpy(d, o, c, n) C23 | Copia bytes de o até copiar o caractere c (inclusive) ou até n bytes. | o ponteiro logo depois do c em d, ou NULL se não achou c | memccpy(d, "maçã;pera", ';', 20) → copia maçã; (7 bytes) | Funções de String |
strlen×sizeof:strlen(nome)é o tamanho do texto (3);sizeof nomeé o tamanho do array (20). Dentro de uma função que recebeuchar *s,sizeof sé o tamanho do ponteiro (8 no gcc, 4 no editor), não do array. Aula: sizeof.strlenconta bytes, não letras. Em UTF-8, cada letra acentuada ocupa 2 bytes. Aula: Acentos e UTF-8.strdupestrndupexistem há décadas no Linux (POSIX), mas só entraram no C padrão no C23.
Comparar
#include <stdio.h>
#include <string.h>
int main(void) {
printf("strcmp(\"Ana\", \"Bia\") = %d\n", strcmp("Ana", "Bia"));
printf("strcmp(\"Bia\", \"Ana\") = %d\n", strcmp("Bia", "Ana"));
printf("strcmp(\"Ana\", \"Ana\") = %d\n", strcmp("Ana", "Ana"));
printf("strcmp(\"ana\", \"Ana\") = %d\n", strcmp("ana", "Ana"));
printf("strcmp(\"Ana\", \"Ana Souza\") = %d\n", strcmp("Ana", "Ana Souza"));
printf("strncmp(\"Banana\", \"Bando\", 3) = %d\n", strncmp("Banana", "Bando", 3));
printf("strncmp(\"Banana\", \"Bando\", 4) = %d\n", strncmp("Banana", "Bando", 4));
int a[3] = {1, 2, 3}, b[3] = {1, 2, 4};
printf("memcmp(a, b, sizeof a) = %d\n", memcmp(a, b, sizeof a));
printf("strcoll(\"abacate\", \"Banana\") = %d\n", strcoll("abacate", "Banana"));
return 0;
}
$ gcc -std=c23 -Wall -Wextra comparar.c -o comparar
$ ./comparar
strcmp("Ana", "Bia") = -1
strcmp("Bia", "Ana") = 1
strcmp("Ana", "Ana") = 0
strcmp("ana", "Ana") = 1
strcmp("Ana", "Ana Souza") = -1
strncmp("Banana", "Bando", 3) = 0
strncmp("Banana", "Bando", 4) = -3 « no editor: -1
memcmp(a, b, sizeof a) = -1
strcoll("abacate", "Banana") = 31
| Função | O que faz | Devolve | Exemplo → resultado | Aula |
|---|---|---|---|---|
strcmp(a, b)"string compare" | Compara as duas strings, letra por letra, pelo código de cada byte (tabela ASCII). | 0 se iguais; negativo se a vem antes; positivo se vem depois | strcmp("Ana", "Bia") → negativo; strcmp("ana", "Ana") → positivo ('a' = 97 vem depois de 'A' = 65) | Funções de String |
strncmp(a, b, n) | Como strcmp, mas olha só os n primeiros bytes. | idem | strncmp("Banana", "Bando", 3) → 0 (Ban = Ban) | Funções de String |
memcmp(a, b, n) | Compara n bytes de dois blocos quaisquer (não para no '\0'). | idem | dois arrays {1,2,3} e {1,2,4} → negativo | Arrays |
strcoll(a, b)"collate", ordenar | Compara seguindo as regras do idioma escolhido com setlocale. Sem setlocale, é igual ao strcmp. | idem | strcoll("abacate", "Banana") → positivo (sem setlocale, minúscula vem depois) | Acentos e UTF-8 |
strxfrm(d, o, n) | Transforma o numa string que, comparada com strcmp, dá o mesmo resultado do strcoll. Raro. | o tamanho que a transformação precisa | (útil para ordenar muitas vezes a mesma lista) | Ordenação |
O C só garante o sinal do resultado. O número em si muda de biblioteca para biblioteca: strncmp("Banana", "Bando", 4) deu -3 no gcc ('a' − 'd') e -1 no editor. Escreva if (strcmp(a, b) < 0), nunca if (strcmp(a, b) == -1). E, para saber se são iguais, strcmp(a, b) == 0; o == entre duas strings compara endereços (veja Erros comuns).
Procurar e dividir
#include <stdio.h>
#include <string.h>
int main(void) {
const char *email = "ana.souza@exemplo.com";
const char *arroba = strchr(email, '@');
printf("strchr: [%s] posição %td\n", arroba, arroba - email);
printf("strrchr: [%s]\n", strrchr(email, '.'));
printf("strstr: [%s]\n", strstr(email, "souza"));
printf("strchr não achou: %s\n", strchr(email, '#') == NULL ? "NULL" : "achou");
printf("strpbrk: [%s]\n", strpbrk("R$ 12,90", "0123456789"));
printf("strspn: %zu\n", strspn("2026-10-17", "0123456789"));
printf("strcspn: %zu\n", strcspn("Ana\n", "\n"));
char linha[] = "Ana\n";
linha[strcspn(linha, "\n")] = '\0';
printf("sem Enter: [%s]\n", linha);
char *p = memchr("abc\0def", 'e', 7);
printf("memchr: [%s]\n", p);
char lista[] = "arroz,feijão,,café";
for (char *item = strtok(lista, ","); item != NULL; item = strtok(NULL, ",")) {
printf("strtok: [%s]\n", item);
}
printf("depois do strtok: [%s]\n", lista);
return 0;
}
$ gcc -std=c23 -Wall -Wextra procurar.c -o procurar $ ./procurar strchr: [@exemplo.com] posição 9 strrchr: [.com] strstr: [souza@exemplo.com] strchr não achou: NULL strpbrk: [12,90] strspn: 4 strcspn: 3 sem Enter: [Ana] memchr: [ef] strtok: [arroz] strtok: [feijão] strtok: [café] depois do strtok: [arroz]
A saída do editor é idêntica.
| Função | O que faz | Devolve | Exemplo → resultado | Aula |
|---|---|---|---|---|
strchr(s, c)"string character" | Procura a primeira vez que o caractere c aparece. | ponteiro para ele, ou NULL | strchr(email, '@') → @exemplo.com; a posição é p - email = 9 | Ponteiros e Strings |
strrchr(s, c)"reverse" | Procura a última vez. | ponteiro, ou NULL | strrchr(email, '.') → .com | Ponteiros e Strings |
strstr(s, t)"string in string" | Procura o texto t dentro de s. | ponteiro para o começo do achado, ou NULL | strstr(email, "souza") → souza@exemplo.com | Funções de String |
strpbrk(s, lista)"pointer break" | Procura o primeiro caractere de s que esteja na lista. | ponteiro, ou NULL | strpbrk("R$ 12,90", "0123456789") → 12,90 | Funções de String |
strspn(s, lista)"span", extensão | Conta quantos caracteres do começo de s estão na lista. | size_t | strspn("2026-10-17", "0123456789") → 4 | Validar a Entrada |
strcspn(s, lista)"complement span" | Conta quantos caracteres do começo de s não estão na lista. | size_t | strcspn("Ana\n", "\n") → 3. O uso clássico: linha[strcspn(linha, "\n")] = '\0'; tira o Enter que o fgets deixa | fgets |
memchr(m, c, n) | Como strchr, mas olha n bytes e não para no '\0'. | ponteiro, ou NULL | memchr("abc\0def", 'e', 7) → ef (passou pelo '\0') | Arrays |
strtok(s, seps)"tokenize", picar em pedaços | Divide s em pedaços separados por qualquer caractere de seps. Na 1ª chamada, passe a string; nas outras, NULL. Estraga a string original (troca cada separador por '\0') e pula pedaços vazios. | o próximo pedaço, ou NULL no fim | "arroz,feijão,,café" → arroz, feijão, café (o vazio sumiu); depois, lista vale só arroz | Contador de Palavras |
- Sempre teste o
NULLantes de usar o resultado destrchr,strstretc.:printf("%s", strchr(email, '#'))com um resultadoNULLé comportamento indefinido. Aula: Ponteiro Nulo. strtoknão funciona numa string literal (char *lista = "a,b"), porque escreve nela; use um array (char lista[] = "a,b"). Ela também guarda a posição numa variável escondida: não dá para usarstrtokem duas strings ao mesmo tempo. A versão que resolve isso é astrtok_r, do POSIX: funciona direto no gcc e, no editor, com#define _DEFAULT_SOURCEantes dos#include.
strchr respeita o const
No C23, strchr, strrchr, strstr, strpbrk e memchr devolvem const char * quando recebem uma string const. Por isso, no programa acima, o resultado vai para const char *arroba. Com char *arroba = strchr(email, '@');, o gcc 15 avisa:
procurar.c:6:20: warning: initialization discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
6 | char *arroba = strchr(email, '@');
| ^~~~~~
O Clang do editor ainda não avisa. Aula: const e Ponteiros.
Blocos de memória: as funções mem…
As mem… trabalham com bytes, não com texto: recebem um void * (qualquer endereço; aula void*) e um número de bytes, e não ligam para o '\0'. Servem para arrays de qualquer tipo e para structs.
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main(void) {
int notas[5];
memset(notas, 0, sizeof notas);
printf("memset 0: %d %d %d %d %d\n", notas[0], notas[1], notas[2], notas[3], notas[4]);
memset(notas, 1, sizeof notas);
printf("memset 1: %d\n", notas[0]);
char senha[8] = "segredo";
memset(senha, '*', strlen(senha));
printf("memset '*': [%s]\n", senha);
int origem[3] = {7, 8, 9}, copia[3];
memcpy(copia, origem, sizeof origem);
printf("memcpy: %d %d %d\n", copia[0], copia[1], copia[2]);
char texto[20] = "abcdef";
memmove(texto + 2, texto, 4);
printf("memmove: [%s]\n", texto);
memset_explicit(senha, 0, sizeof senha);
printf("memset_explicit: strlen=%zu\n", strlen(senha));
printf("strerror(ENOENT): %s\n", strerror(ENOENT));
printf("strerror(EACCES): %s\n", strerror(EACCES));
printf("strerror(0): %s\n", strerror(0));
return 0;
}
$ gcc -std=c23 -Wall -Wextra memoria.c -o memoria $ ./memoria memset 0: 0 0 0 0 0 memset 1: 16843009 memset '*': [*******] memcpy: 7 8 9 memmove: [ababcd] memset_explicit: strlen=0 strerror(ENOENT): No such file or directory strerror(EACCES): Permission denied strerror(0): Success
No editor, o memset_explicit não existe (error: use of undeclared identifier 'memset_explicit'). Sem essa linha, o resto sai igual.
| Função | O que faz | Devolve | Exemplo → resultado | Aula |
|---|---|---|---|---|
memset(m, c, n)"memory set" | Põe o byte c em cada um dos n bytes. | m | memset(notas, 0, sizeof notas) → tudo 0. Com 1, cada int vira 16843009 (os 4 bytes valem 1: 0x01010101), não 1! | Arrays |
memcpy(d, o, n)"memory copy" | Copia n bytes. Os dois blocos não podem se sobrepor. | d | copia um int[3] inteiro: 7 8 9 | Arrays |
memmove(d, o, n)"memory move" | Como memcpy, mas funciona mesmo se os blocos se sobrepõem (copia como se usasse uma área temporária). | d | memmove(texto + 2, texto, 4) em "abcdef" → ababcd | Array que Cresce |
memcmp(a, b, n) | Compara n bytes (veja Comparar). | negativo, 0 ou positivo | (acima) | Arrays |
memchr(m, c, n) | Procura um byte (veja Procurar). | ponteiro, ou NULL | (acima) | Arrays |
memset_explicit(m, c, n) C23 | Como memset, mas o compilador é proibido de apagá-lo na otimização. Para limpar senhas e chaves da memória. | m | memset_explicit(senha, 0, sizeof senha) → strlen = 0 (só no gcc) | Segurança |
Por que memset_explicit? Com otimização (-O2), o compilador pode apagar um memset(senha, 0, …) feito logo antes de a variável deixar de existir, já que "ninguém mais vai ler". A senha fica na memória. O memset_explicit não pode ser apagado.
strerror: a mensagem de um erro
| Função | O que faz | Devolve | Exemplo → resultado | Aula |
|---|---|---|---|---|
strerror(num)"string error" | Traduz o número de um erro do sistema (o errno) num texto em inglês. | a mensagem (não mexa nela) | strerror(ENOENT) → No such file or directory; strerror(EACCES) → Permission denied | errno e perror |
O uso típico: fprintf(stderr, "Não abri %s: %s\n", nome, strerror(errno)); logo depois de um fopen que devolveu NULL. É o mesmo texto que o perror mostra.
Qual usar?
| Para… | Evite | Use | Por quê |
|---|---|---|---|
| copiar para um array | strcpy(d, o) | snprintf(d, sizeof d, "%s", o) | nunca passa do tamanho e sempre põe o '\0'; o retorno diz se cortou (aula Texto ↔ Número) |
| copiar só uma parte | strncpy sem o '\0' manual | strncpy(d, o, sizeof d - 1); d[sizeof d - 1] = '\0'; | o strncpy sozinho deixa a string sem fim se a origem for longa |
| juntar textos | strcat em sequência | snprintf(d, sizeof d, "%s %s", nome, sobrenome) | uma linha, com o tamanho conferido |
| comparar textos | a == b | strcmp(a, b) == 0 | == compara endereços, não letras |
| copiar para memória nova | malloc(strlen(s)) + strcpy | strdup(s) | o malloc à mão costuma esquecer o + 1 do '\0' |
| blocos que se sobrepõem | memcpy | memmove | com sobreposição, memcpy é comportamento indefinido |
| dividir com campos vazios | strtok | strchr num laço | strtok pula o campo vazio de "a,,c", e num CSV isso desloca as colunas |
Editor × gcc
O que muda no <string.h> entre o editor (Clang + wasi-libc) e o gcc 15 (glibc), conferido com os programas desta página:
| Assunto | Editor | gcc 15 (glibc) |
|---|---|---|
strndup e memccpy (C23), strtok_r (POSIX) | só com #define _DEFAULT_SOURCE antes dos #include; sem isso, error: use of undeclared identifier 'strndup'; did you mean 'strdup'? | funcionam direto |
memset_explicit (C23) | não existe (use of undeclared identifier) | funciona |
Valor de strncmp("Banana", "Bando", 4) | -1 | -3 (o sinal é o mesmo) |
char *p = strchr(texto_const, …) | sem aviso | aviso discards ‘const’ qualifier (C23) |
Mudar uma string literal (char *s = "ana"; s[0] = 'A';) | funciona, calado (mostra Ana) | Falha de segmentação (139): as literais ficam numa memória só de leitura |
String sem '\0' no printf("%s") | mostra lixo depois do texto (SPX9) | também é lixo; nesta execução, saiu só SPX |
strlen(NULL) | devolve 0, calado | Falha de segmentação (139) |
Iguais nos dois: todos os outros resultados desta página, os sinais de strcmp/strncmp/memcmp e os textos do strerror (também strerror(0) = Success).
Erros comuns
Este programa junta os enganos mais frequentes com strings. O -Wall pega todos, mas o programa compila e roda:
#include <stdio.h>
#include <string.h>
void limpar(char *s) {
memset(s, 0, sizeof s);
}
int main(void) {
char nome[4];
strcpy(nome, "Ana Souza");
char a[] = "Ana", b[] = "Ana";
if (a == b) printf("iguais\n");
const char *c = "Ana";
if (c == "Ana") printf("igual ao literal\n");
char sigla[3];
strncpy(sigla, "SPX", sizeof sigla);
limpar(nome);
printf("%s %s\n", nome, sigla);
return 0;
}
$ gcc -std=c23 -Wall -Wextra errostr.c -o errostr
errostr.c: In function ‘limpar’:
errostr.c:5:25: warning: argument to ‘sizeof’ in ‘memset’ call is the same expression as the destination; did you mean to provide an explicit length? [-Wsizeof-pointer-memaccess]
5 | memset(s, 0, sizeof s);
| ^
errostr.c: In function ‘main’:
errostr.c:12:11: warning: comparison between two arrays [-Warray-compare]
12 | if (a == b) printf("iguais\n");
| ^~
errostr.c:12:11: note: use ‘&a[0] == &b[0]’ to compare the addresses
errostr.c:14:11: warning: comparison with string literal results in unspecified behavior [-Waddress]
14 | if (c == "Ana") printf("igual ao literal\n");
| ^~
errostr.c:16:5: warning: ‘strncpy’ output truncated before terminating nul copying 3 bytes from a string of the same length [-Wstringop-truncation]
16 | strncpy(sigla, "SPX", sizeof sigla);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
errostr.c:10:5: warning: ‘__builtin_memcpy’ writing 10 bytes into a region of size 4 overflows the destination [-Wstringop-overflow=]
10 | strcpy(nome, "Ana Souza");
| ^~~~~~~~~~~~~~~~~~~~~~~~~
errostr.c:9:10: note: destination object ‘nome’ of size 4
9 | char nome[4];
| ^~~~
$ ./errostr
igual ao literal
SPX
| Linha | gcc 15 | Clang (editor) | O que acontece e como consertar |
|---|---|---|---|
strcpy(nome, "Ana Souza"); num char nome[4] | ‘__builtin_memcpy’ writing 10 bytes into a region of size 4 overflows the destination [-Wstringop-overflow=] | 'strcpy' will always overflow; destination buffer has size 4, but the source string has length 10 (including NUL byte) [-Wfortify-source] | Escreve 6 bytes além do fim do array, por cima de outras variáveis. Aqui passou calado; em outros programas, estraga valores ou derruba o programa. Use um array maior ou snprintf. Aula: Segurança. |
if (a == b) com dois arrays | comparison between two arrays [-Warray-compare] | array comparison always evaluates to false [-Wtautological-compare] | Compara os endereços dos dois arrays, que nunca são iguais: o iguais não saiu, mesmo com o mesmo texto. Use strcmp(a, b) == 0. |
if (c == "Ana") | comparison with string literal results in unspecified behavior [-Waddress] | result of comparison against a string literal is unspecified (use an explicit string comparison function instead) [-Wstring-compare] | Aqui deu "igual" porque o compilador guardou as duas "Ana" no mesmo lugar, mas isso não é garantido. Use strcmp(c, "Ana") == 0. |
strncpy(sigla, "SPX", sizeof sigla); | ‘strncpy’ output truncated before terminating nul copying 3 bytes from a string of the same length [-Wstringop-truncation] | (nenhum aviso) | Os 3 bytes encheram o array e não sobrou lugar para o '\0': o printf continua lendo a memória seguinte (no editor saiu SPX9). Reserve um byte a mais: char sigla[4]. |
memset(s, 0, sizeof s); com char *s | argument to ‘sizeof’ in ‘memset’ call is the same expression as the destination; did you mean to provide an explicit length? [-Wsizeof-pointer-memaccess] | 'memset' call operates on objects of type 'char' while the size is based on a different type 'char *' [-Wsizeof-pointer-memaccess] | sizeof s é o tamanho do ponteiro (8 no gcc), não do array. Passe o tamanho como parâmetro: void limpar(char *s, size_t tam). Aula: Ponteiros e Arrays. |
#include <stdio.h>
int main(void) {
char *nome = "ana";
printf("Antes: %s\n", nome);
nome[0] = 'A';
printf("Depois: %s\n", nome);
return 0;
}
$ gcc -std=c23 -Wall -Wextra literal.c -o literal $ ./literal Antes: ana Falha de segmentação (imagem do núcleo gravada) ./literal $ echo $? 139
O que significa: "ana" é uma string literal, e o gcc a guarda numa parte da memória que só pode ser lida. O char *nome só aponta para ela; escrever ali derruba o programa. Nenhum aviso, nem com -Wall. No editor, o programa mostra Depois: Ana sem erro, mas continua errado.
Como consertar: para um texto que muda, use um array, que é uma cópia sua: char nome[] = "ana";. Para um texto que não muda, deixe claro com const char *nome = "ana";: aí o compilador dá erro se você tentar escrever. Aula: Ponteiros e Strings.
strcat num array sem valor inicial
char frase[50]; strcat(frase, "Oi"); procura o '\0' do fim de frase, mas o array tem lixo: o texto vai parar num lugar qualquer. Como consertar: comece com uma string vazia, char frase[50] = "";. Aula: Strings.
fgets deixou o Enter
Depois de fgets(nome, sizeof nome, stdin), o nome termina em '\n': um strcmp(nome, "Ana") dá diferente e um printf("[%s]", nome) pula linha antes do ]. Como consertar: nome[strcspn(nome, "\n")] = '\0'; (é a missão abaixo). Aula: fgets.
Experimente
Missão: o programa lê o nome da Ana com fgets (a entrada já vem preenchida com Ana Souza), mas o ] sai na linha de baixo e o tamanho conta um byte a mais. Use strcspn para tirar o Enter, de modo que a saída seja Olá, [Ana Souza]! Seu nome tem 9 bytes. Depois, teste outras funções da página na mesma caixa.
#include <stdio.h>
#include <string.h>
int main(void) {
char nome[40];
printf("Seu nome: ");
if (fgets(nome, sizeof nome, stdin) == NULL) {
return 1;
}
// tire o '\n' aqui
printf("Olá, [%s]! Seu nome tem %zu bytes.\n", nome, strlen(nome));
return 0;
}
#include <stdio.h>
#include <string.h>
int main(void) {
char nome[40];
printf("Seu nome: ");
if (fgets(nome, sizeof nome, stdin) == NULL) {
return 1;
}
nome[strcspn(nome, "\n")] = '\0';
printf("Olá, [%s]! Seu nome tem %zu bytes.\n", nome, strlen(nome));
return 0;
}
Resumo
- Tamanho:
strlen(bytes até o'\0'; não é osizeofdo array). - Cópia e junção:
strcpy,strcat(não conferem o tamanho),strncpy(pode deixar sem'\0'),strncat,strdup/strndup(memória nova, comfree). Prefirasnprintf. - Comparação:
strcmp,strncmp,memcmp,strcoll. Teste== 0,< 0ou> 0, nunca== -1. Nunca==entre strings. - Busca:
strchr,strrchr,strstr,strpbrk,memchr(devolvem ponteiro ouNULL),strspn,strcspn(devolvem contagens).strtokdivide, mas estraga a string e pula campos vazios. - Memória:
memset(byte a byte),memcpy(sem sobreposição),memmove(com sobreposição),memset_explicit(para senhas, C23). strerror(errno)dá o texto do erro do sistema.