Encontrar uma palavra dentro de uma string em C

1. Encontrar uma palavra dentro de uma string em C

Natã Molima Marques
mrroot

(usa Debian)

Enviado em 09/04/2017 - 11:31h

Olá pessoal. Tudo bem?
Pessoal ja quebrei de mais a cabeça nisso , então peço a ajuda de vocês nisto.
Eu preciso encontrar uma palavra dentro de uma string, ja utilizei o algoritmo Força Bruta e o algoritmo de Boyer Moore, entretando por falta de boas explicações, eu não consigo executar estes algoritmos sem erros.
Então escrevi meu próprio algoritmo, mas mesmo assim não consigo.
Peço a ajuda de vocês por favor, se possível, poderiam escrever um algoritmo similar para eu estudar por favor?
Segue abaixo o meu algoritmo


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

int search_string(char texto[],char frase[]);
void limpa_string(char string[]);
int main()
{
//int p;
char texto[100];
char frase[100];
printf("Digite um texto:");
scanf("%[^\n]s",texto);
getchar();
printf("Digite uma frase:");
scanf("%[^\n]s",frase);
search_string(texto,frase);

}
int search_string(char texto[],char frase[])
{
int i,j; //variavel de loop
int aux; // armazena a posição de i caso a posição de i combine com a frase na posição 0
char teste[strlen(frase)];
char c;
int x;
int p = 0;
limpa_string(teste);
for(i=1;i<=strlen(texto)-strlen(frase);i++)
{
if(texto[i]==frase[1])
{
aux = i;
for(j=1;j<=strlen(frase);j++)
{
c = texto[aux];
teste[j] = c;
aux++;
}
}
x = strcmp(teste,frase);
limpa_string(teste);
if(x==0)
{
p = p + 1;
}
}
printf("%d",p);
}
void limpa_string(char string[])
{
int i = 0;

while(i<strlen(string))
{
string[i] = '\0';
i++;
}
}



  


2. Re: Encontrar uma palavra dentro de uma string em C

Paulo
paulo1205

(usa Ubuntu)

Enviado em 10/04/2017 - 08:43h

mrroot escreveu:

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

int search_string(char texto[],char frase[]);
void limpa_string(char string[]);


Eu prefiro a notação de ponteiros como argumentos de função usando a forma geral de delcaração de ponteiros “char *texto”, em vez de “char texto[]”.

E a sua função limpa_string deveria ter um segundo parâmetro, especificando o tamanho máximo que a string pode possuir.

int main() 


O programa é em C ou em C++? Se for em C, deveria haver a palavra-chave void entre os parênteses, de modo a indicar que main() não vai receber argumentos. Com os parênteses vazios, o significado em C é que main() pode receber uma quantidade qualquer de argumentos de quaisquer tipos.

{
//int p;
char texto[100];
char frase[100];
printf("Digite um texto:");
scanf("%[^\n]s",texto);


Sua string de formatação está errada. Aquele “s” após o fechamento de colchetes está sobrando, e na prática faz com que a função interrompa a execução antes de chegar ao final da string de formatação.

Você possivelmente pensou que os colchetes e a expressão dentro deles são modificadores da conversão "%s", mas não é assim que a coisa funciona. A conversão "%[" é uma conversão de seu próprio direito, distinta de "%s" e com regras de funcionamento diferentes.

Além do mais, conviria a você testar o valor de retorno de scanf() (algumas implementações exigem que você faça isso; o Ubuntu, por exemplo, o faz), bem como colocar limites na quantidade de caracteres que a conversão pode colocar na string. Como texto é um array com espaço para cem caracteres, eis como você poderia fazer.

int a, b, c, r;

/* ... */

/* Prepara leitura. */
a=b=c=0;

/*
Lê, descartando espaços no início da linha, limitando a largura do
texto a 100 caracteres (99 de texto, mais um para o terminador),
e tenta encontrar e consumir o terminador de linha (o que dispensa
o uso que você fez de getchar(), mais abaixo). Guarda as quanti-
dades de caracteres consumidos antes do texto, entre o fim do
texto e a tentativa de consumir o fim de linha e após o suposto
consumo desse fim de linha, respectivamente, em ‘a’, ‘b’ e ‘c’,
para ajudar a ver se a linha está de acordo com o formato
esperado.
*/
r=scanf(" %n%99[^\n]%n%*1[\n]%n", &a, texto, &b, &c);

/* Valida a leitura. */
if(r!=1 || b<=a || c<=b){
/*
Se r!=1, a conversão falhou. Se b<=a, o texto é vazio (caso que
eu considero inválido, até porque não deveria ocorrer, especial-
mente com o descarte de espaços no início da linha). Se c<=b,
então faltou o fim de linha, o que pode ser indicativo de que o
texto excedeu 99 caracteres (fácil de testar, verificando quanto
é o valor de b-a) ou que ocorreu alguma exceção, como erro de
leitura ou fim de arquivo.

Em todo caso, se você cair aqui, ou o valor de texto é inválido,
ou o buffer de entrada vai estar num estado inconsistente para
uma próxima operação de leitura. Você deve dar um tratamento
de erro adequando, em vez de simplesmente seguir com a exe-
cução do programa.
*/
/* COLOQUE SEU TRATAMENTO DE ERRO AQUI. */
}

/* Neste ponto, ‘texto’ deve conter um texto válido. */


		getchar();
printf("Digite uma frase:");
scanf("%[^\n]s",frase);


Mesmo comentário sobre o uso equivocado de scanf().

	    search_string(texto,frase);

}
int search_string(char texto[],char frase[])
{
int i,j; //variavel de loop
int aux; // armazena a posição de i caso a posição de i combine com a frase na posição 0
char teste[strlen(frase)];


Eu GARANTO a você que você não vai precisar de um terceiro array. Mesmo que precisasse, você deveria alocar espaço para strlen(frase)+1 caracteres, pois o terminador da string tem de ser considerado como parte do vetor que contém a string.

	char c;
int x;
int p = 0;
limpa_string(teste);


Você deveria usar um outro argumento para indicar o tamanho da área de dados a ser limpa.

	for(i=1;i<=strlen(texto)-strlen(frase);i++) 


Grande chance de erro aí. Lembre-se que, em C, os índices de vetores sempre começam a ser contados de zero, não de 1. Em outras palavras, um vetor com N elementos tem índices que vão de 0 até N-1. Você parece estar querendo ir de 1 até N, e estará errando se o fizer.

	{
if(texto[i]==frase[1])
{
aux = i;
for(j=1;j<=strlen(frase);j++)


Mesmo problema com índices fora da faixa, com o agravante de que você não reservou espaço para o terminador em teste. Como você efetua a cópia do terminador (ainda que o faça sem querer!), copia-o para uma posição inválida no array de destino. Sabe-se lá o que existirá nessa posição inválida -- pode ser outra variável, algum dado de controle, um endereço de retorno da função, ou mesmo uma posição de memória inválida, que faça o programa capotar quando a ela se faz acesso.

			{
c = texto[aux];
teste[j] = c;
aux++;
}
}
x = strcmp(teste,frase);


Note o desperdício: você mal acabou de varrer todo o array frase, comparando-o com texto, e agora faz outra varredura de comparação! Não lhe soa isso como um sinal de que a segunda comparação é redundante (desde que você embuta algumas partes faltando junto à primeira comparação)?

		limpa_string(teste);
if(x==0)
{
p = p + 1;


Você quer saber onde no texto se localiza a frase ou quantas vezes a frase acontece dentro do texto? Parece que você acabou tentando implementar a segunda opção.

		}
}
printf("%d",p);


Você disse que a função retorna um valor inteiro. Onde está o comando que efetivamente faz esse valor inteiro ser retornado?

}
void limpa_string(char string[])


Já disse acima que esta função deveria ter dois parâmetros, com um deles informando o tamanho da área a ser limpada.

{
int i = 0;

while(i<strlen(string))


Qual você espera que seja o valor retornado por strlen(string)? Acha que ele tem alguma relação com o tamanho do array onde a string está contida?

Se acha, saiba que não tem. Você não tem sequer qualquer garantia de que o ponteiro passado como argumento é válido ou que aponte para uma string (i.e. que exista pelo menos um caráter nulo dentro do espaço apontado, dentro dos limites do vetor original). Eis outra razão pela qual seria necessário ter outro parâmetro, informando o tamanho a ser limpado, mesmo que o vetor originalmente não possa ser usado com strlen().

	{
string[i] = '\0';
i++;
}
}



3. Re: Encontrar uma palavra dentro de uma string em C

Natã Molima Marques
mrroot

(usa Debian)

Enviado em 10/04/2017 - 15:44h

Poxa valew mesmo pela explicação.
Irei pegar sua explicação e rachar a cuca aqui para conseguir.






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts