2010-02-06 6 views
3

J'écris un programme de tokenisation de chaînes de caractères pour une affectation de devoirs en C++, qui utilise des pointeurs. Cependant, quand je lance & le déboguer, il indique que mon pointeur pStart, est invalide. J'ai le sentiment que mon problème réside dans mon constructeur param'ed, j'ai inclus le constructeur et la création d'objet ci-dessous.Bad Pointer? - C++

J'apprécierais que vous me disiez pourquoi on dit que pStart est un mauvais pointeur quand je le débogue.

Merci!

StringTokenizer::StringTokenizer(char* pArray, char d) 
{ 
pStart = pArray; 
delim = d; 
} 

// create a tokenizer object, pass in the char array 
// and a space character for the delimiter 
StringTokenizer tk("A test char array", ' '); 

stringtokenizer.cpp complète:

#include "stringtokenizer.h" 
#include <iostream> 
using namespace std; 

StringTokenizer::StringTokenizer(void) 
{ 
pStart = NULL; 
delim = 'n'; 
} 

StringTokenizer::StringTokenizer(const char* pArray, char d) 
{ 
pStart = pArray; 
delim = d; 
} 

char* StringTokenizer::Next(void) 
{ 
char* pNextWord = NULL; 

while (pStart != NULL) 
{ 
    if (*pStart == delim) 
    { 
     *pStart = '\0'; 
     pStart++; 
     pNextWord = pStart; 

     return pNextWord; 
    } 
    else 
    { 
     pStart++; 
    } 
} 
    return pNextWord; 
} 

La fonction est ensuite censé arriver pour retourner un pointeur sur le mot suivant dans le tableau de caractères. Ce n'est pas fini pour le moment. :)

stringtokenizer.h complète:

#pragma once 

class StringTokenizer 
{ 
public: 
StringTokenizer(void); 
StringTokenizer(const char*, char); 
char* Next(void); 
~StringTokenizer(void); 
private: 
char* pStart; 
char delim; 
}; 

main.cpp complète:

const int CHAR_ARRAY_CAPACITY = 128; 
const int CHAR_ARRAY_CAPCITY_MINUS_ONE = 127; 

// create a place to hold the user's input 
// and a char pointer to use with the next() function 
char words[CHAR_ARRAY_CAPACITY]; 
char* nextWord; 

cout << "\nString Tokenizer Project"; 
cout << "\nyour name\n\n"; 
cout << "Enter in a short string of words:"; 
cin.getline (words, CHAR_ARRAY_CAPCITY_MINUS_ONE); 

// create a tokenizer object, pass in the char array 
// and a space character for the delimiter 
StringTokenizer tk(words, ' '); 

// this loop will display the tokens 
while ((nextWord = tk.Next ()) != NULL) 
{ 
    cout << nextWord << endl; 
} 


system("PAUSE"); 
return 0; 
+0

Quel est le message d'erreur que vous obtenez? – ihtkwot

+0

'CXX0030: Erreur: l'expression ne peut pas être évaluée' Merci! – Alex

+0

le CXX003 est un exécutable C/C++ runtime/compile-timeerror mais juste une erreur que vous obtenez dans le débogueur qui dit que vous utilisez abusivement évaluateur de valeur - http://msdn.microsoft.com/en-us/library/ 360csw6a (VS.71) .aspx Il serait préférable que vous puissiez envoyer un code plus complet. Les bits que vous avez collés sont incomplets et incorrects sous cette forme, c'est-à-dire que pStart est quoi? – mloskot

Répondre

0

Modifiez pStart dans la classe StringTokenizer de char * à const char * et apportez la même modification au constructeur.

+0

Merci! Aide majeure sur le projet! – Alex

1

changement

StringTokenizer::StringTokenizer(char* pArray, char d) 

à

StringTokenizer::StringTokenizer(const char * pArray, char d) 

Un littéral de chaîne est toujours une variable const char * const, et puisque C++ convertit automatiquement un const non const, il ne peut pas convertir un const en non const.

Vous pouvez également créer différents constructeurs, mais je ne pense pas que vous en aurez besoin, du moment que vous venez de lire la chaîne pArray.

Vous pouvez utiliser quelque chose comme ceci:

TokenList& StringTokenizer::StringTokenizer(const char* pArray, char d){ 
    TokenList lst(); 
    size_t i=0; 
    char buffer[100]; //hardcoded limit, just an example, you should make it grow dinamically, or just use a std::string 
    while((*pArray)){ 
    if(*pArray == d){ 
     buffer[i] = 0; //string ending character, 0 = '\0'; 
     lst.add(buffer); 
     i=0; 
    } 
    pArray++; 
    } 
    //Last token in the input string won't be ended by the separator, but with a '\0'. 
    buffer[i] = 0; 
    lst.add(buffer); 

    return lst; 
} 
+0

Mais maintenant je reçois: 'erreur C2440: '=': ne peut pas convertir de 'const char *' en 'char *' – Alex

+0

Je lis dans un tableau char par le chemin – Alex

+0

S'il vous plaît, ajouter plus d'infos les. Vous voyez, le littéral de chaîne est CONSTANT, vous ne pouvez pas le modifier en aucune façon. Je pense que vous l'attribuez en fait à un autre caractère *, vous ne pouvez pas, vous devez l'assigner à un autre caractère *. Je vais modifier la réponse pour vous montrer un peu du code réel que je pense. – Spidey

3

Vous ne pouvez pas modifier pStart dans votre tokenizer, parce qu'une chaîne littérale en C et C++ est non modifiable, il a un type const char *. Lorsque vous faites l'affectation

pStart = pArray; 

dans votre constructeur, pStart est maintenant pointant vers une mémoire non modifiable. Très probablement c'est votre problème. Vous devrez poster plus de code si ce n'est pas le cas.

Édition: Après avoir regardé votre modification, vous semblez avoir modifié votre code pour utiliser un tableau. C'est bon. Je ne l'ai pas regardé votre code dans trop de détails, mais il y a au moins une erreur:

while (pStart != NULL) 

devrait être:

while (pStart != NULL && *pStart) 

Ceci est parce que vous voulez arrêter votre boucle quand vous frappez la terminaison '\0' dans votre chaîne. Je ne vois pas pourquoi vous utilisez des chaînes de style C en C++. Est-ce une exigence dans vos devoirs?

+0

Cela change-t-il quelque chose si j'utilise un tableau char? – Alex

+0

tableau tableau de bord où? Si 'pStart' est un tableau char, l'assignation ne serait même pas compilée: vous ne pouvez pas l'assigner à un tableau en C++. Post code minimal complet s'il vous plaît. –

0

À mon avis, vous devez changer le constructeur et destructor de StringTokenizer:

StringTokenizer::StringTokenizer(char* pArray, char d) 
{ 
    pStart = str = strdup(pArray); 
    delim = d; 
} 

StringTokenizer::~StringTokenizer(char* pArray, char d) 
{ 
    free(str); 
} 

Maintenant, vous pouvez utiliser PSTART dans la façon dont vous utilisez: modifier la chaîne, mettre des zéros pour marquer des mots, etc. Vous avez seulement besoin d'ajouter un attribut privé "char * str" à StringTokenizer.

L'astuce ici est que vous créez votre propre copie de la chaîne, ainsi vous pouvez manipuler comme vous voulez, à condition de le libérer dans le destructeur. Le seul inconvénient est que vous avez besoin de mémoire pour stocker la copie (donc vous avez besoin de deux fois la mémoire pour chaque chaîne).

La raison pour laquelle votre solution n'a pas fonctionné est que les littéraux sont ou peuvent être stockés dans la mémoire morte, ils sont donc correctement marqués comme const char *, étant "impossible" d'y écrire.