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
  • " \backslash n " é 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.

Passo 1

O que o enunciado fornece e o que se espera que eu explique:
  • Foi apresentada a função da biblioteca C strcspn com seu protótipo:
    size_t strcspn(const char *str1, const char *str2);
    
  • Foram dados parâmetros: str1 (string onde busca) e str2 (conjunto de caracteres procurados).
  • Foi explicado, resumidamente, que a função retorna o número de caracteres iniciais de str1 que não aparecem em str2.
  • 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 como strcspn funciona, por que e como usá-la junto com fgets, 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:
  • strcspn percorre str1 caractere a caractere (do início para o fim).
  • Para cada caractere c de str1, ela verifica se c aparece em str2.
  • Se encontrar o primeiro caractere de str1 que também está em str2, ela para e retorna a posição (índice) desse caractere, contando a partir de zero.
  • Se percorrer toda str1 sem encontrar nenhum caractere presente em str2, ela retorna o comprimento de str1.
  • 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. strcspn retorna 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 como 0).
  • Se eu quero remover o '\n' (nova linha) que fgets deixa 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:
    palavras[i][strcspn(palavras[i], "\n")] = '\0';
    
    Isso funciona tanto se houver '\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 str2 do início ao fim; para cada j verifica if (str1[k] == str2[j]):
      • Se for igual, retorna k.
    • Se nenhum str2[j] igual a str1[k] foi encontrado, incrementa k.
  • Se chegar em str1[k] == '\0' sem encontrar correspondência, retorna k (que é strlen(str1)).
    Isso deixa claro porque o pior caso tem custo proporcional ao produto dos comprimentos de str1 e str2 (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 → retorna 5.
  • strcspn("abc123", "0123456789"):
    • percorre ‘a’,‘b’,‘c’ (nenhum é dígito) → na posição 3 encontra ‘1’ que está em str2 → retorna 3.
  • 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 de str2 dentro de str1, ou comprimento se nada for encontrado.

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 buf de tamanho N.
    if (fgets(buf, N, stdin) != NULL) {
        buf[strcspn(buf, "\n")] = '\0';
    }
    
    Explicando:
    • fgets lê até N-1 caracteres 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 comprimento strlen(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: strcspn retorna no máximo strlen(buf) que é ≤ N-1.
    • Não precisa testar explicitamente se '\n' existe — o próprio strcspn cuida disso.

Passo 7

Casos especiais e armadilhas (importante para prova e para código robusto)
  • Se str2 for string vazia "", então não há caracteres para procurar e strcspn retorna strlen(str1) (ou seja, nada é encontrado).
  • Se str1 for vazia "", retorna 0.
  • strcspn trabalha byte a byte. Em strings UTF-8 (multibyte), ele vê bytes, não caracteres multibyte; se str2 conté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 (ou wchar_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 str2 for longo e você chamar strcspn muitas vezes, pode ser menos eficiente; mas para o caso comum de str2 = "\n" é super rápido e trivial.
  • Segurança: strcspn não escreve na memória, só retorna um índice. A escrita com buf[idx] = '\0' é onde se deve garantir que buf é grande o suficiente — normalmente garantido se buf veio de fgets.

Passo 8

Alternativas e quando preferir cada uma
  • strchr pode ser usada se só se quer procurar um único caractere:
    char *p = strchr(buf, '\n');
    if (p) *p = '\0';
    
    Isso pode ser mais direto quando se procura exatamente um caractere.
  • strtok(buf, "\n") também remove o '\n', mas strtok modifica 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:
    1. fgets lê a linha, colocando ‘\n’ se coube.
    2. strcspn(buf, "\n") retorna índice do ‘\n’ ou comprimento.
    3. Atribuir '\0' naquele índice garante que buf termina 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 em str1 que também aparece em str2, ou strlen(str1) se nenhum for encontrado.
  • Padrão para remover \n de fgets:
    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’;

Exercícios relacionados