Dev - C++ - Metodo "strtok" de cabezera string.h

   
Vista:

Metodo "strtok" de cabezera string.h

Publicado por Juan David juandacalji@hotmail.com (1 intervención) el 06/06/2017 16:09:05
Hola, Buenos días.
Sucede que tengo un inconveniente en un programa que estoy haciendo de lista enlazada doble, el programa consiste en insertar una frase, u oración; y yo tengo que separar las palabra de la oración, así como también los signos de puntuación de las palabras y meter cada uno de estas palabra y caracteres en los nodos de manera ordenada de la lista enlazada doble.
para poder separar las palabras de la frase estoy usando el método strtok de la cabecera cstring. sin embargo tengo problema; por que cuando escribo la frase tengo un auxiliar que me capta la palabra entra en el while del strtok; dentro evalúa si esta palabra separada tiene signo de puntuación, y si lo tiene, pues lo separo de nuevo con el strtok. el problema es cuando el strtok de afuera(el que evalúa las palabra separadas por espacios de la frase original, ingresada desde el principio) no sigue con la siguiente palabra, si no que de una vez manda null el puntero. como arrglo esto.

ejemplo de error:

oración ingresada: la, vaca comia.
primer ciclo del while del primer strtok:
el primer strtok: separa "la,"
segundo strtok: separa "la"

segundo ciclo del while delprimer strtok:
el primer strtok: se llena NULL. <---(deberia seguir con la palabra "vaca").

se cierra el ciclo obviamente.

ADJUNTO CÓDIGO PARA QUE ME AYUDEN:

.cpp: funcion que llama al metodo insertar de la lista enlazada doble.


void Insertar() {
system("cls");
char oracion[200];
system("cls");
cout << "MENU DE INSERTAR\n\n";
cout << "1. ESCRIBIR DE MANERA NORMAL UNA ORACION\n";
cout << "2. ESCRIBIR UN CARACTER O PALABRA EN UNA DETERMINADA POSICION\n";
cin >> opc;
switch (opc)
{
case 1:
cout << "DIGITE SU ORACION:\n";
cin.ignore();
cin.getline(oracion,200,'\n');
Oracion.Insertar(oracion);
break;
case 2:




break;
default:
cout << "OPCION INCORRECTA, INTENTE DE NUEVO.\n";
system("pause");
Insertar();
break;
}
}



lista.h :Adjunto todo el código de la lista.

#include"Nodo.h"
#include<cstring>
using namespace std;

class Lista_Caracter
{
private:
Nodo *lista;
int n;

public:
Lista_Caracter();
int Dame_Tamaño_Lista();
void Insertar(char[200]);
};
//CONSTRUCTOR
Lista_Caracter::Lista_Caracter(){n = 0; lista = NULL;}

//

int Lista_Caracter::Dame_Tamaño_Lista(){ return n; }


//inserta la cadena de caracteres de manera normal
void Lista_Caracter::Insertar(char frase[200]){
char *token_palabra, *token_signo;
int tamaño;
bool bandera = false;
string aux_palabra,aux_puntuacion,signo;
token_palabra = strtok(frase, " ");
aux_palabra = token_palabra;
while (token_palabra != NULL)
{
Nodo *nodo_palabra_sola = new Nodo();
nodo_palabra_sola->palabra = aux_palabra;
tamaño = aux_palabra.size();
for (int i = 0; i < tamaño; i++)
{
if (aux_palabra[i] == ',')
{
char arry_puntuacion[25];
for (int j = 0; j < tamaño; j++)
{
arry_puntuacion[j] = aux_palabra[j];
if (j + 1 == tamaño)
{
arry_puntuacion[j + 1] = '\0';
}
}

token_signo = strtok(arry_puntuacion, ",");
aux_puntuacion = token_signo;
while (token_signo != NULL)
{
aux_puntuacion = token_signo;
token_signo = strtok(NULL, ",");
}
signo = ",";
bandera = true;
}
else if (aux_palabra[i] == ';')
{
char arry_puntuacion[25];
for (int j = 0; j < tamaño; j++)
{
arry_puntuacion[j] = aux_palabra[j];
if (j + 1 == tamaño)
{
arry_puntuacion[j + 1] = '\0';
}
}

token_signo = strtok(arry_puntuacion, ";");
aux_puntuacion = token_signo;
while (token_signo != NULL)
{
aux_puntuacion = token_signo;
token_signo = strtok(NULL, ";");
}
signo = ";";
bandera = true;
}
else if (aux_palabra[i] == '.')
{
char arry_puntuacion[25];
for (int j = 0; j < tamaño; j++)
{
arry_puntuacion[j] = aux_palabra[j];
if (j + 1 == tamaño)
{
arry_puntuacion[j + 1] = '\0';
}
}

token_signo = strtok(arry_puntuacion, ".");
aux_puntuacion = token_signo;
while (token_signo != NULL)
{
aux_puntuacion = token_signo;
token_signo = strtok(NULL, ".");
}
signo = ".";
bandera = true;
}
}

if (bandera == false)
{
Nodo *p = new Nodo();
p->palabra = aux_palabra;
if (lista == NULL)
{
lista = p;
}
else if (lista->siguiente == NULL)
{
p->anterior = lista;
lista->siguiente = p;
}
else
{
Nodo *aux = lista;
while (aux->siguiente != NULL)
{
aux = aux->siguiente;
}
aux->siguiente = p;
p->anterior = aux;
}
}
else
{
Nodo *p_sin_signo = new Nodo();
p_sin_signo->palabra = aux_puntuacion;
if (lista == NULL)
{
lista = p_sin_signo;
}
else if (lista->siguiente == NULL)
{
p_sin_signo->anterior = lista;
lista->siguiente = p_sin_signo;
}
else
{
Nodo *aux = lista;
while (aux->siguiente != NULL)
{
aux = aux->siguiente;
}
aux->siguiente = p_sin_signo;
p_sin_signo->anterior = aux;
}
Nodo *puntuacion = new Nodo();
puntuacion->palabra = signo;
Nodo *aux = lista;
while (aux->siguiente != NULL)
{
aux = aux->siguiente;
}
aux->siguiente = puntuacion;
puntuacion->anterior = aux;
}
token_palabra = strtok(NULL, " ");
if (token_palabra != NULL)
{
aux_palabra = token_palabra;
}
}

n = n + 1;
}


nodo.h: adjunto todo el codigo.


#include<iostream>
#include<cstring>
#include<string.h>
#include<string>
using namespace std;
struct Nodo
{
string palabra;
int repetido,tamaño;
Nodo *siguiente;
Nodo *anterior;
Nodo();
};

Nodo::Nodo() {
siguiente = NULL;
anterior = NULL;
repetido = 1;
tamaño = 0;
}





por favor ayuda, si quieren revísenlo en sus pc y se dan cuenta de lo que quiero decir.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

Metodo "strtok" de cabezera string.h

Publicado por Leonardo (11 intervenciones) el 13/06/2017 14:30:42
Hola! No necesito revisar el código(no sé si es correcto pues no lo he revisado) lo que sí estoy completamente seguro de porque te ocurre eso. Ya a mi me ocurrió una vez. Resulta que esa función es una función estática y eso
hace que las variables que se usan dentro de strtok(en la implementación de la función) son las mismas en cada llamada. Te explico: la función va insertando caracteres nulos '\0' cada vez que encuentra un token y guarda esa posición por lo que la próxima vez que sea llamada ella "recuerda" esa posición y realiza la búsqueda del próximo token a partir de ahí pero como la llamas de nuevo con otra cadena diferente a la de la primer llamada se pierde y te
da resultados erroneos. La solución: te toca implementarla a ti mismo. Yo ya lo hice y fue como resolví el problema.
Espero hayas entendido la explicación. Quizas yo pueda buscar dónde tengo mi versión de la función y enviártela.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar