“ String ” contém função em C

Esta função verifica se uma substring needle existe ou não em outra string haystack e retorna a posição se sim ou 0 se não, a menos que o a posição é 0, caso em que não será localizado.

Procurando maneiras de melhorar este código, especificamente melhor tratamento de erros.

#include <stdio.h> #include <stdlib.h> #include <string.h> size_t contains(const char * needle, const char *haystack); int main(void) { char *needle = "test"; char *haystack = "This is a dinosaurtest."; printf("Position: %lu", contains(needle, haystack)); return EXIT_SUCCESS; } size_t contains(const char * needle, const char *haystack) { if(needle == NULL || haystack == NULL) { return 0; } long int first_char_pos = -1; size_t len_h = strlen(haystack); size_t len_n = strlen(needle); size_t i, j; size_t exist_count = 0; // Find the first character. If it doesn"t exist, we"re done. for(i = 0; i < len_h; i++) { if((haystack[i] == needle[0]) && (first_char_pos == -1)) { first_char_pos = i; exist_count++; } } if(first_char_pos == -1) { return 0; } printf("First char match index: %li\n", first_char_pos); printf("Char: %c\n", haystack[first_char_pos]); size_t current_index = (size_t) first_char_pos; for(i = first_char_pos; i < len_h; i++) { if(haystack[i] == needle[exist_count] && (i == (current_index + 1))) { current_index = i; exist_count++; } printf("Exist count: %lu\n", exist_count); //<--Debugging if(exist_count == len_n) { return first_char_pos; } } return 0; } 

Comentários

  • Adicione alguns exemplos para mostrar exatamente o que você quer dizer com ” contém “. Duvido que seu código funcione conforme o esperado.
  • Isso já existe: strstr(). Há ‘ s uma versão mais segura chamada . Você pode encontrar uma implementação aqui: github.com/lattera/freebsd/blob/master/lib/libc/string/…
  • @RolandIllig: por que, você pode explicar?
  • contains("tt", "test") deve retornar verdadeiro?
  • @ CacahueteFrito Então, você paga um custo considerável em usabilidade e desempenho para mascarar a corrupção de dados em algumas raras circunstâncias, em vez de depender das invariáveis do seu programa, corrigindo os dados ou relatando o erro? Parece uma má ideia geral.

Resposta

Apenas algumas observações:

  • Você deve adicionar uma nova linha após a última linha:

     $ ./nh First char match index: 18 Char: t Exist count: 1 Exist count: 2 Exist count: 3 Exist count: 4 Position: 18 $ 
  • Eu não sei o que compilador que você usa, mas com quando compilado com gcc e -Wall -Wextra -pedantic você obtém:

    gcc -O2 nh.c -lm -o nh -Wall -Wextra -pedantic nh.c: In function ‘contains’: nh.c:25:15: warning: unused variable ‘j’ [-Wunused-variable] size_t i, j; ^ 
  • A formatação do código deve ser mais consistente. Por exemplo, nesta linha você coloca um espaço em branco antes de needle, mas não coloque um espaço em branco antes haystack:

    size_t contains(const char * needle, const char *haystack); 
  • %lu não é um especificador portátil para o tipo size_t, você deve usar %zu introduzido no C99.

  • Você disse:

retorna a posição se sim ou 0 se não, a menos que o a posição é 0; nesse caso, ela não será localizada.

Isso realmente não é bom. Por exemplo, com isso, ele retorna 0:

char *needle = "This"; char *haystack = "This is a dinosaurtest."; 

Com isso, ele também retorna zero:

char *needle = "non-existent"; char *haystack = "This is a dinosaurtest."; 

Você não pode dizer a diferença entre sucesso e fracasso nestes dois exemplos. Na verdade, atoi() tem o mesmo problema. Não sei qual sistema operacional você usa mas talvez você possa usar ssize_t como o tipo de retorno se estiver disponível e retornar -1 em caso de falha.

Resposta

Acrescentando à resposta anterior de @Arkadiusz Drabczyk:

Uma implementação simples e trivial de contains poderia ser feito assim:

ssize_t contains(const char * needle, const char *haystack) { char *needle_in_haystack; if(!needle || !haystack) return -1; needle_in_haystack = strstr(haystack, needle); return needle_in_haystack ? needle_in_haystack - haystack : -1; } 

Então, este programa (com algumas alterações conforme mencionado acima) deve funcionar:

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> ssize_t contains(const char * needle, const char *haystack) { char *needle_in_haystack; if(!needle || !haystack) return -1; needle_in_haystack = strstr(haystack, needle); return needle_in_haystack ? needle_in_haystack - haystack : -1; } int main(void) { char *needle = "test"; char *haystack = "This is a dinosaurtest."; char *haystack2 = "This does not contain the string."; printf("Position: %zd\n", contains(needle, haystack)); printf("Position: %zd\n", contains(needle, haystack2)); return EXIT_SUCCESS; } 

Resultado:

Posição: 18
Posição: -1

Comentários

  • Gostaria de remover a verificação de que a entrada não é NULL e ju st use uma extensão de idioma para isso (__attribute__((nonnull)) no GCC). NULL é algo que você nunca esperaria como entrada para esta função e adiciona uma ou duas linhas de código desnecessárias. Eu preferiria escrever na documentação da função algo como: ” Se a entrada para esta função for um ponteiro NULL, o comportamento é indefinido. “.
  • @CacahueteFrito O código original fez isso, e eu quero me esforçar para manter a compatibilidade (quem sabe como o OP estava usando isso?).
  • Falta inclusão para ssize_t: #include <sys/types.h>. Outra opção seria usar ptrdiff_t em vez de #include <stddef.h>; você está, na verdade, retornando uma diferença de ponteiro: ? needle_in_haystack - haystack :

Resposta

Seu código não funciona. Ele retorna 0 para haystack "abbc" e needle "bc", embora haystack contenha needle .

Resposta

Você não precisa do primeiro loop e de todos os cálculos de comprimento. A propósito, a função não é bem-sucedida se o primeiro caractere for encontrado, mas apenas a segunda ocorrência do primeiro caractere se encaixa com agulha.

A tarefa pode ser reduzida a algumas linhas:

int contains(char *buf, char *needle) { char *src, *srch, *srcp; for(src=buf; *src; src++) { for(srch = needle, srcp = src; *srch && *srcp && *srch == *srcp; srch++, srcp++); if(!*srch) return src - buf; } return -1; } 

Comentários

  • Qual é uma boa maneira de escrever um código C mais compacto e eficiente como este ?Isso me lembra de K & R C.

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *