A função strcspn é uma função da biblioteca string.h que calcula o comprimento do segmento inicial de uma string que não contém nenhum dos caracteres especificados em outra string.
Protótipo:
size_t strcspn(const char *str1, const char *str2);
Parâmetros:
- str1: String onde a busca será realizada
- str2: String contendo os caracteres a serem procurados
Retorno:
- Retorna o número de caracteres no início de str1 que não correspondem a nenhum caractere em str2
Como funciona:
A função percorre str1 caractere por caractere, comparando cada um com todos os caracteres de str2. Quando encontra o primeiro caractere de str1 que também está presente em str2, ela para e retorna a posição (índice) desse caractere.
Exemplo no código da atividade:
palavras[i][strcspn(palavras[i], "\n")] = 0;
Neste caso:
- palavras[i] é a string lida com fgets
- "
" é a string contendo apenas o caractere de nova linha
- strcspn(palavras[i], “\n”) retorna a posição onde o \n está localizado
- Ao atribuir 0 (caractere nulo) nessa posição, estamos removendo o \n e tudo que vem depois dele
Exemplos práticos:
strcspn("hello\n", "\n") // retorna 5 (posição do '\n')
strcspn("abc123", "0123456789") // retorna 3 (posição do primeiro digito)
strcspn("teste", "xyz") // retorna 5 (nenhum caractere encontrado, retorna o comprime:
Por que usar no contexto do fgets?
Quando usamos fgets, ele lê a linha inteira incluindo o caractere de nova linha In que o usuário digita ao pressionar Enter. Para remover esse \n indesejado, usamos strcspn para encontrar sua posição e substituí-lo por \0 (terminador de string), efetivamente “cortando” a string naquele ponto.
size_t strcspn(const char *str1, const char *str2);
A função percorre str1 caractere por caractere, comparando cada um com todos os caracteres de str2. Quando encontra o primeiro caractere de str1 que também está presente em str2, ela para e retorna a posição (índice) desse caractere.
palavras[i][strcspn(palavras[i], "\n")] = 0;
strcspn("hello\n", "\n") // retorna 5 (posição do '\n')
strcspn("abc123", "0123456789") // retorna 3 (posição do primeiro digito)
strcspn("teste", "xyz") // retorna 5 (nenhum caractere encontrado, retorna o comprime:
Quando usamos fgets, ele lê a linha inteira incluindo o caractere de nova linha In que o usuário digita ao pressionar Enter. Para remover esse \n indesejado, usamos strcspn para encontrar sua posição e substituí-lo por \0 (terminador de string), efetivamente “cortando” a string naquele ponto.
Passo 1
O que o enunciado fornece e o que se espera que eu explique:
- Foi apresentada a função da biblioteca C
strcspncom seu protótipo:size_t strcspn(const char *str1, const char *str2); - Foram dados parâmetros:
str1(string onde busca) estr2(conjunto de caracteres procurados). - Foi explicado, resumidamente, que a função retorna o número de caracteres iniciais de
str1que não aparecem emstr2. - Foi mostrado um uso prático comum com
fgets:palavras[i][strcspn(palavras[i], "\n")] = 0; - O enunciado incluiu exemplos curtos (um deles truncado).
O que devo fazer: explicar passo a passo comostrcspnfunciona, por que e como usá-la junto comfgets, mostrar exemplos concretos e cobrir os casos especiais e armadilhas — tudo explicado de forma didática e sem pular etapas.
Passo 2
O que faz
strcspn, explicando bem devagar:strcspnpercorrestr1caractere a caractere (do início para o fim).- Para cada caractere
cdestr1, ela verifica secaparece emstr2. - Se encontrar o primeiro caractere de
str1que também está emstr2, ela para e retorna a posição (índice) desse caractere, contando a partir de zero. - Se percorrer toda
str1sem encontrar nenhum caractere presente emstr2, ela retorna o comprimento destr1. - O valor retornado tem tipo
size_t(um tipo inteiro sem sinal, adequado para tamanhos/índices).
Exemplo intuitivo: em"hello\n"procurar"\n"— os caracteres de"hello\n"na posição 0…4 são h,e,l,l,o e na posição 5 está\n.strcspnretorna 5 (a posição do\n).
Passo 3
Por que o retorno é útil para “cortar” a string:
- Em C, uma string termina no caractere nulo
'\0'(também escrito numericamentre como0). - Se eu quero remover o
'\n'(nova linha) quefgetsdeixa no buffer, faço: colocar'\0'na posição onde está o'\n'. - Como
strcspn(palavras[i], "\n")dá a posição do'\n'(ou o comprimento se não houver'\n'), atribuir'\0'naquela posição corta a string exatamente antes do'\n'. - Exemplo prático e seguro:
Isso funciona tanto se houverpalavras[i][strcspn(palavras[i], "\n")] = '\0';'\n'(substitui por'\0') quanto se não houver (atribui'\0'na posição igual ao comprimento — que já é o'\0'final ou coloca um'\0'no final, não trazendo erro).
Passo 4
Passo a passo do algoritmo (como se fosse um loop) — para você entender e poder implementar mentalmente:
- Começa com um índice
k = 0. - Enquanto
str1[k] != '\0':- Percorre
str2do início ao fim; para cadajverificaif (str1[k] == str2[j]):- Se for igual, retorna
k.
- Se for igual, retorna
- Se nenhum
str2[j]igual astr1[k]foi encontrado, incrementak.
- Percorre
- Se chegar em
str1[k] == '\0'sem encontrar correspondência, retornak(que éstrlen(str1)).
Isso deixa claro porque o pior caso tem custo proporcional ao produto dos comprimentos destr1estr2(ou seja, O(n·m) no sentido conceitual).
Passo 5
Exemplos concretos com explicação índice a índice:
strcspn("hello\n", "\n"):- percorre ‘h’ (não em
\n), ‘e’, ‘l’, ‘l’, ‘o’ → nenhum está em"\n". - chega em
'\n'na posição 5 → retorna5.
- percorre ‘h’ (não em
strcspn("abc123", "0123456789"):- percorre ‘a’,‘b’,‘c’ (nenhum é dígito) → na posição 3 encontra ‘1’ que está em
str2→ retorna3.
- percorre ‘a’,‘b’,‘c’ (nenhum é dígito) → na posição 3 encontra ‘1’ que está em
strcspn("teste", "xyz"):- percorre toda a string ‘t’,‘e’,‘s’,‘t’,‘e’ sem encontrar ‘x’,‘y’ ou ‘z’ → retorna
5(o comprimento de"teste"). (Corrigindo o trecho truncado do enunciado.)
Esses exemplos mostram o comportamento típico: retorna índice da 1ª ocorrência de qualquer caractere destr2dentro destr1, ou comprimento se nada for encontrado.
- percorre toda a string ‘t’,‘e’,‘s’,‘t’,‘e’ sem encontrar ‘x’,‘y’ ou ‘z’ → retorna
Passo 6
Uso prático com
fgets: código mínimo e explicação linha a linha- Situação típica: ler linha do usuário para um buffer
bufde tamanhoN.
Explicando:if (fgets(buf, N, stdin) != NULL) { buf[strcspn(buf, "\n")] = '\0'; }fgetslê atéN-1caracteres e coloca'\0'no final; se a linha lida inclui'\n', o'\n'também é incluído antes do'\0'.strcspn(buf, "\n")acha a posição do'\n'se existir, ou o comprimentostrlen(buf)se não existir.- Atribuir
'\0'naquela posição remove o'\n'(ou simplesmente mantém a string igual se'\n'não estava lá).
- Por que esse padrão é seguro:
- Nunca escreve fora do buffer:
strcspnretorna no máximostrlen(buf)que é ≤N-1. - Não precisa testar explicitamente se
'\n'existe — o própriostrcspncuida disso.
- Nunca escreve fora do buffer:
Passo 7
Casos especiais e armadilhas (importante para prova e para código robusto)
- Se
str2for string vazia"", então não há caracteres para procurar estrcspnretornastrlen(str1)(ou seja, nada é encontrado). - Se
str1for vazia"", retorna0. strcspntrabalha byte a byte. Em strings UTF-8 (multibyte), ele vê bytes, não caracteres multibyte; sestr2contém um byte que faz parte de uma sequência UTF-8, o comportamento pode “cortar” no meio de um caractere Unicode. Para textos multibyte, use funções adequadas (ouwchar_t+wcscspn) se necessário.strcspné case-sensitive:'a'e'A'são diferentes. Para comparar sem diferenciar maiúsculas/minúsculas, é preciso normalizar a string antes.- Performance: se
str2for longo e você chamarstrcspnmuitas vezes, pode ser menos eficiente; mas para o caso comum destr2 = "\n"é super rápido e trivial. - Segurança:
strcspnnão escreve na memória, só retorna um índice. A escrita combuf[idx] = '\0'é onde se deve garantir quebufé grande o suficiente — normalmente garantido sebufveio defgets.
Passo 8
Alternativas e quando preferir cada uma
strchrpode ser usada se só se quer procurar um único caractere:
Isso pode ser mais direto quando se procura exatamente um caractere.char *p = strchr(buf, '\n'); if (p) *p = '\0';strtok(buf, "\n")também remove o'\n', masstrtokmodifica estado interno e não é reentrante — cuidado.- Fazer um laço manual
for (i=0; buf[i] && buf[i] != '\n'; ++i); buf[i] = '\0';é equivalente e explícito, útil em prova para mostrar entendimento. strcspné a forma elegante e concisa, muito usada em códigos reais e em aulas.
Passo 9
Exemplo final completo, comentado e robusto (prática para prova)
#include <stdio.h>
#include <string.h>
#define N 100
int main(void) {
char buf[N];
if (fgets(buf, N, stdin) != NULL) {
/* remove final newline se existir */
buf[strcspn(buf, "\n")] = '\0';
printf("Linha lida sem newline: '%s'\n", buf);
}
return 0;
}
- Passo a passo do exemplo:
fgetslê a linha, colocando ‘\n’ se coube.strcspn(buf, "\n")retorna índice do ‘\n’ ou comprimento.- Atribuir
'\0'naquele índice garante quebuftermina antes do'\n'.
Passo 10
Resumo de dicas para a prova (curtinho e fácil de decorar)
- Saber:
strcspn(str1, str2)retorna o índice do primeiro caractere emstr1que também aparece emstr2, oustrlen(str1)se nenhum for encontrado. - Padrão para remover
\ndefgets:buf[strcspn(buf, "\n")] = '\0'; - Se procurar só um caractere,
strchré alternativa direta. - Atenção a strings multibyte e case-sensitivity.
size_té o tipo do retorno (índice/contagem sem sinal).
Resposta
palavras[i][strcspn(palavras[i], “\n”)] = ‘\0’;