Ajuda com strtok()/ separar string quando existir um espaço; [RESOLVIDO]

1. Ajuda com strtok()/ separar string quando existir um espaço; [RESOLVIDO]

Simone
dominico

(usa Outra)

Enviado em 20/06/2014 - 23:06h

Olá pessoal sou nova por aqui, tenho um grande dúvida, estou trabalhando com string em c e preciso separar ela a cada espaço e comparar com outra string usando strstr(), para ver se esta presente, na mesma. O meu problema é que não posso alterar a string original onde aplico o strtok(). Não consigo nem mesmo atribuindo a mesma para outra variável, pois recebo um erro utilizando o malloc. Alguém sabe um modo que consiga fazer isso sem alterar a string original, e sem usar strtok()? Vou agradecer muito a ajuda.


  


2. Re: Ajuda com strtok()/ separar string quando existir um espaço; [RESOLVIDO]

Perfil removido
removido

(usa Nenhuma)

Enviado em 21/06/2014 - 14:01h

Por que não usa o strcpy() para copiar a string original para uma temporária, assim a string original fica intacta...


3. Re: Ajuda com strtok()/ separar string quando existir um espaço; [RESOLVIDO]

Simone
dominico

(usa Outra)

Enviado em 21/06/2014 - 14:36h

Então tentei utilizar sim mas, ao realizar a cópia ele aparece um erro que provavelmente é de memória, li em alguns lugares que pode ocorrer algo assim quando se utiliza deste modo. No meu caso chamo a função diversas vezes e em um ponto ela apresenta o erro.Minhas funções que apresentam o erro:
/* Verifica se cada conjunto da lista possui algum elemento
do do conjunto de entrada sendo assim, seguindo a regra de
se A é subconjunto proprio de B, então A está em B, com
a diferença de pelo menos um elemento de B não está em A.
*/
int verificaSubconjunto(char *aux, char *conjunto){
char *divide;
int presente=0;
divide= strtok(conjunto, " ");
while(divide!=NULL){
if(strstr(aux, divide))
presente = presente+1;
divide = strtok(NULL, " ");
}
return presente;
}
/*recebe as entradas para percorrer a lista e chamar a função para verificar se os
conjuntos da lista são subconjuntos da entrada*/
void subconjuntoProprio(CONJ* lista, int pos, char *conjunto){
CONJ *tmp;
int cont=0,i;
for(i=1;i<pos;i++){
tmp = lista[i].prox;
/*Posso atribuir aqui e mandar a nova variavel do tipo um char *aux, utilizando o malloc eu aloco empaço e depois utilizo strcpy(), mas fazendo assim ele da erro, o problema que modificando a variavel original está modificando minha lista toda, no meu caso vetor de listas*/
while (tmp != NULL) {
if(verificaSubconjunto(conjunto, tmp->conjunto)==i){

printf("%d %s\n",i, tmp->conjunto);
cont++;
}
tmp = tmp->prox;

}
}
printf("0\n");
free(tmp);
return;
}

E como o tamanho das entradas podem ser muito grandes, complica um pouco e li que strtok() esta meio ultrapassada exatamente por modificar a variável original.
Obrigado pela dica.


4. Re: Ajuda com strtok()/ separar string quando existir um espaço; [RESOLVIDO]

Perfil removido
removido

(usa Nenhuma)

Enviado em 21/06/2014 - 18:17h

Precisamos do código completo para verificar a saída de erro...

DICA: poste seu código entre as chaves [ code ] <código> ... [ /code ] (sem os espaços entre "[", "]" e "code")


5. Re: Ajuda com strtok()/ separar string quando existir um espaço; [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 21/06/2014 - 20:10h

Você está programando em qual sistema operacional, e com que compilador?

É perigoso você dizer que uma solução de cópia usando malloc() não funciona: se não funciona, é porque você está fazendo de modo errôneo. Você não deveria ter omitido essa parte do código. De todo modo, a forma de fazer seria algo como vai abaixo.

char *copy_str;

/* ... */

/*
Na alocação abaixo, note o "+1", para acomodar o byte
nulo que marca o fim da string. O byte nulo da string
original não é computado pela função strlen().
*/
copy_str=malloc(strlen(orig_str)+1
if(copy_str==NULL){
perror("Erro de alocação");
exit(1);
}
strcpy(copy_str, orig_str);

/* Aqui você manipula copy_str. */

/* Quando acabar a manipulação, desaloca copy_str. */
free(copy_str);



6. usando FOR

Clauber Cesario
klone1

(usa Outra)

Enviado em 22/06/2014 - 13:52h

bom primeiramente devemos saber que em C uma string é um conjunto de char, um vetor de char


se vc quer separar um string por espaço vc pode usar um FOR para percorrer essa string e fica separando os pedaços em outra string exemplo



char nome[30];
char separacao = '#'
char pedacos[2][30]
char junta;
int a = 0;
for (int i = 0 ; nome[i] != '/0' ; i++)
{
junta += nome[i]
if (nome[i] == separacao)
{
pedaco[a] = nome
a++;
junta = '';
}

}


7. Re: Ajuda com strtok()/ separar string quando existir um espaço; [RESOLVIDO]

Simone
dominico

(usa Outra)

Enviado em 23/06/2014 - 15:45h

Então não suprimi a parte do código havia retirado ele mesmo, mas estava fazendo isso, o que me retorna um erro no strcpy(), que usando o valgrind me leva a um erro de memória. Tratei a alocação de memória e ele nunca consegue passar.
Meu sistema operacional é Ubuntu 13.04, o compilador o GCC.
int verificaSubconjunto(char *aux, char *conjunto){
char *divide;
int presente=0;
divide= strtok(conjunto, " ");
while(divide!=NULL){
if(strstr(aux, divide))
presente = presente+1;
divide = strtok(NULL, " ");
}
return presente;
}
/*recebe as entradas para percorrer a lista e chmar a função para verificar se os
conjuntos da lista são subconjuntos da entrada*/
void subconjuntoProprio(CONJ* lista, int pos, char *conjunto){
CONJ *tmp;
char *aux;
int cont=0,i;
aux = (char*) malloc(sizeof(conjunto)); /*Aqui utilizo malloc*/
for(i=1;i<pos;i++){
tmp = lista[i].prox;
strcpy(aux, tmp->conjunto); /*Aqui atribuo a variavel aux com strcpy*/
while (tmp != NULL) {
if(verificaSubconjunto(conjunto, aux)==i){

printf("%d %s\n",i, tmp->conjunto);
cont++;
}
tmp = tmp->prox;

}
}
printf("0\n");
free(aux);/*Depois libero espaço*/
return;
}



8. Re: Ajuda com strtok()/ separar string quando existir um espaço; [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 23/06/2014 - 15:56h

Edite a sua postagem original e coloque o código que você postou entre as tags [code] e [/code]. Não sei se você reparou, mas o fato de não ter feito isso fez com que a ocorrência de “[i]” fosse interpretada como início do texto em itálico, e isso desformatou tudo dali para frente.


9. Re: Ajuda com strtok()/ separar string quando existir um espaço; [RESOLVIDO]

Simone
dominico

(usa Outra)

Enviado em 23/06/2014 - 15:59h

Código completo Ru4an

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

/*variavel tamanho dos conjuntos*/
int tam;
typedef struct conj
{
char *conjunto;
struct conj* prox;
int extensao;
}CONJ;


CONJ *busca(char *x, CONJ *lista, int pos)
{
CONJ *tmp;
tmp = lista[pos].prox;
while(tmp!=NULL && strcmp(tmp->conjunto, x)!=0){
tmp= tmp->prox;
}
return tmp;
}
/*insere na lista o conjunto de forma ordenada*/
void InserirOrd(CONJ *lista, int pos, char *conjunto){
CONJ *aux;
CONJ *tmp;

aux = (CONJ*) malloc((int)sizeof(CONJ));
aux->conjunto = malloc (sizeof (conjunto)+1);
strcpy(aux->conjunto,conjunto);
aux->prox = NULL;

if(busca(conjunto, lista, pos)!=NULL)
printf("E\n");
else{
if(lista[pos].prox == NULL) /*Caso a lista estiver vazia - Insere.*/
lista[pos].prox = aux;
else {
tmp = lista[pos].prox;
if (strcmp(tmp->conjunto, conjunto) > 0) { /*insere como primeiro da lista*/
aux->prox = tmp;
lista[pos].prox = aux;
} /*insere ordenados*/
else
if (tmp->prox == NULL) {
aux->prox = tmp->prox;
tmp->prox = aux;
}
else {
while((tmp->prox != NULL) &&(strcmp(tmp->prox->conjunto, conjunto) < 0))
tmp = tmp->prox;
aux->prox = tmp->prox;
tmp->prox = aux;
}
}
}
lista[pos].extensao = lista[pos].extensao + 1;
printf("0\n");
}
/*Imprimir conjuntos operação * */
void imprimir(CONJ *lista){
int i;
CONJ * tmp;
for(i=1; i<=tam; i++) {
tmp = lista[i].prox;
while (tmp != NULL && lista[i].extensao>0 && tmp->conjunto!=NULL) {
printf("%d %s\n",i, tmp->conjunto);
tmp = tmp->prox;
}
}
printf("0\n");
}
void verifica(char *conjunto, CONJ *lista, int tamanho){
if(busca(conjunto, lista, tamanho)!=NULL){
printf("0\n");
}
else
printf("E\n0\n");
}
CONJ* deletaConjunto(CONJ *lista, int pos, char *conjunto){
CONJ *tmp, *raiz; /* ponteiro para elemento anterior, ponteiro percorrer a lista */
raiz = lista[pos].prox;
/* procura elemento na lista, guardando anterior */
//printf("Entra deletar");
while (raiz != NULL && strcmp(raiz->conjunto, conjunto)!=0) {
tmp = raiz;
raiz = raiz->prox;
}
/* verifica se achou elemento */
if (raiz == NULL){
printf("E\n0\n"); /* não achou*/
return lista;
}

/* retira elemento */
if (tmp == NULL) {
/* retira elemento do inicio */
lista[pos].prox = raiz->prox;
}
else {
/* retira elemento do meio da lista */
tmp->prox = raiz->prox;
}

free(raiz);
lista[pos].extensao--;
printf("0\n");
return lista;

}
/* Verifica se cada conjunto da lista possui algum elemento
do do conjunto de entrada sendo assim, seguindo a regra de
se A é subconjunto proprio de B, então A está em B, com
a diferença de pelo menos um elemento de B não está em A.
*/
int verificaSubconjunto(char *aux, char *conjunto){
char *divide;
int presente=0;
divide= strtok(conjunto, " ");
while(divide!=NULL){
if(strstr(aux, divide))
presente = presente+1;
divide = strtok(NULL, " ");
}
return presente;
}
/*recebe as entradas para percorrer a lista e chmar a função para verificar se os
conjuntos da lista são subconjuntos da entrada*/
void subconjuntoProprio(CONJ* lista, int pos, char *conjunto){
CONJ *tmp;
char *aux;
int cont=0,i;
aux = malloc(strlen(conjunto)+1);
for(i=1;i<pos;i++){
tmp = lista[i].prox;
strcpy(aux, tmp->conjunto);
while (tmp != NULL) {
if(verificaSubconjunto(conjunto, aux)==i){

printf("%d %s\n",i, tmp->conjunto);
cont++;
}
tmp = tmp->prox;

}
}
printf("0\n");
free(aux);
return;
}

void verificaOperacacao(CONJ *lista,char op, int tamanho, char *conjunto){
switch(op){
case '+': InserirOrd(lista, tamanho, conjunto);
break;
case '-': lista = deletaConjunto(lista, tamanho, conjunto);
break;
case '=': verifica(conjunto, lista, tamanho);
break;
case '*': imprimir(lista);
break;
/*case '/': deletaSuperConjunto(lista, tamanho, conjunto);
break;*/
case '<': subconjuntoProprio(lista, tamanho, conjunto);
break;
/*case '>': superConjunto(lista, tamanho, conjunto);
break; */
}
}
int main()
{
char op, *conjunto;
int tamanho,i;
conjunto = (char*)malloc(sizeof(char));
fscanf(stdin, "%d", &tam);
CONJ lista[tam];
/*Inicializa lista*/
for(i=1; i<=tam; i++){
lista[i].conjunto =NULL;
lista[i].prox = NULL;
lista[i].extensao = 0;
}
while(!feof(stdin)){
fscanf(stdin,"\n%c %d\n", &op, &tamanho);
if(op=='*' )
verificaOperacacao(lista,op,tamanho,conjunto);
else{
if(op!='0'){
gets(conjunto);
verificaOperacacao(lista,op,tamanho,conjunto);/*encaminhar para verificar operação*/

}
}
}
return(0);
}



Para compilar e testar utilizo um txt, de entrada:

10
+ 2 2 4
+ 1 7
+ 8 1 2 3 5 6 7 8 10
+ 9 1 2 3 4 6 7 8 9 10
+ 5 1 3 4 6 10
+ 7 3 4 5 7 8 9 10
+ 7 2 4 5 6 7 9 10
+ 2 3 9
+ 1 4
+ 9 1 2 3 5 6 7 8 9 10
+ 4 1 5 7 8
+ 4 4 7 8 10
+ 5 2 3 6 9 10
+ 9 1 2 3 4 5 6 7 8 10
+ 6 1 4 6 8 9 10
+ 6 1 4 6 8 9 10
= 2 2 4
= 9 1 2 3 4 6 7 8 9 10
= 2 2 4
= 9 1 2 3 5 6 7 8 9 10
= 2 3 9
= 2 2 4
= 5 2 3 6 9 10
= 9 1 2 3 4 6 7 8 9 10
= 7 2 4 5 6 7 9 10
= 9 1 2 3 4 5 6 7 8 10
= 10 1 2 3 4 5 6 7 8 9 10
- 7 2 4 5 6 7 9 10
- 2 3 9
- 1 4
- 5 2 3 6 9 10
- 8 1 2 3 5 6 7 8 10
< 3 4 6 7
< 9 1 2 3 5 6 7 8 9 10
*
0

Em relação ao utilizar o for, não consigo saber do tamanho da string para declarar as variáveis auxiliares, o que dificulta utilizar deste modo.


10. Re: Ajuda com strtok()/ separar string quando existir um espaço; [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 23/06/2014 - 16:21h

Você precisa rever os conceitos de tipos de dados, strings, ponteiros e alocação dinâmica de memória.

Veja, por exemplo, o que você fez em main().

conjunto = (char*)malloc(sizeof(char));
/*
...
*/
gets(conjunto);


Traduzindo para Português, você fez o ponteiro conjunto apontar para uma região de memória com espaço para somente UM caráter e, em seguida, espera ler uma linha inteira para essa região de memória. É óbvio que isso vai dar problema.

Não entrei em detalhes do resto do programa, mas parece que os outros usos de malloc() têm problemas parecidos (por exemplo: “malloc(sizeof(conjunto)+1)”, dentro da função InserirOrd(); parece-me que você deveria usar a função strlen() em lugar do operador sizeof).


11. Re: Ajuda com strtok()/ separar string quando existir um espaço; [RESOLVIDO]

Simone
dominico

(usa Outra)

Enviado em 23/06/2014 - 16:35h

Olá Paulo a utilização de malloc() sempre achei meio complicada, vou verificar meu código arrumando estes erros com malloc para verificar se melhoro. Agradeço muito suas respostas e colaboração.


12. Re: Ajuda com strtok()/ separar string quando existir um espaço; [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 23/06/2014 - 17:29h

Eu não tenho como ajudar muito porque parece que você tem mesmo de rever alguns conceitos que demandariam uma explicação muito longa para este espaço. Isso é coisa de livro, seja ele em papel ou on-line, mas não para um fórum.

Parece-me, porém, que seu maior problema é confundir o tipo char com strings de caracteres.

Uma variável do tipo char armazena um único caráter. Em C, aliás, um char é exatamente equivalente a um byte, que é o menor dado que o computador consegue endereçar. Uma variável desse tipo pode não apenas guardar uma letra ou um símbolo, mas também valores inteiros numa faixa que vai, na esmagadora maioria dos computadores, de -128 a 127 ou de 0 a 255 (dependendo de se a representação é com sinal ou sem sinal), inclusive realizando operações aritméticas com tais valores.

String (cuja tradução é "cordão") de caracteres é uma região contígua de memória que armazena um conjunto de caracteres que normalmente estão relacionados por uma razão semântica (por exemplo: você pode ter strings que armazenam nomes de pessoas, frases, códigos de produto, postagens de um fórum etc.). Se você tiver a frase “Ivo viu a uva.” e quiser manipulá-la no seu programa, é natural que guarde esses caracteres em posições adjacentes de memória, em lugar de espalhá-los de modo aparentemente aleatório.

Desse modo, para trabalhar com strings você precisa reservar blocos de memória de tamanhos suficientes para armazenar cada uma delas. Essa reserva pode ser feita na hora da compilação do programa, por meio da declaração de arrays de caracteres, ou no momento da execução do programa (por isso o nome de “alocação dinâmica”), através de funções como malloc() e calloc(), que reservam uma região da memória livre e entrega um ponteiro para a área reservada.

Um aspecto de que você deve lembrar a respeito de strings em C é que, por convenção, o final de qualquer string é marcado por um byte nulo (i.e.: aquele com valor numérico zero, que é obviamente diferente do símbolo para o algarismo zero). Assim sendo, se você quiser que um string armazene o texto "TESTE", quer como array fixo no momento da compilação, quer como bloco alocado dinamicamente e recebido por um ponteiro, deve especificar um tamanho mínimo de seis caracteres, sendo cinco para os que formam a palavra, mais um para o byte nulo.






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts