开发者

Bad Pointer? - C++

I'm writing a string tokenization program for a homework assignment in C++, that uses pointers. However, when I run & debug it, it says that my pointer pStart, is invalid. I have a feeling that my problem resides in my param'ed constructor, I've included both the constructor and the object creation below.

I would appreciate it if you might tell me why it says that pStart is a bad pointer whe开发者_运维技巧n I debug it.

Thanks!

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", ' ' );

Full stringtokenizer.cpp:

#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;
}

The function Next is supossed to return a pointer to the next word in the char array. It's currently not finished. :)

Full stringtokenizer.h:

#pragma once

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

Full main.cpp:

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;


You can't modify pStart in your tokenizer, because a literal string in C and C++ is not modifiable, it has a type const char *. When you do the assignment

pStart = pArray;

in your constructor, pStart is now pointing to a non-modifiable memory. Most likely that is your problem. You will need to post more code if that's not the case.

Edit: After looking at your edit, looks like you have changed your code to use an array. That's good. I haven't looked at your code in too much detail, but there is at least one error:

while (pStart != NULL)

should be:

while (pStart != NULL && *pStart)

This is because you want to stop your loop when you hit the terminating '\0' in your string.

I am not sure why you're using C-style strings in C++. Is this a requirement in your homework?


Change

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

to

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

A string literal is always a const char * const variable, and since C++ automatically casts a non const to const, it can't cast a const to non const.

You can also make different constructors, but I don't think you'll need it, as long as you just read the pArray string.

You could use something like this:

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;
}


Change pStart in the StringTokenizer class from char* to const char*, and make the same change to the constructor.


In my opinion, you should change the constructor and destructor of StringTokenizer:

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

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

Now you can use pStart in the way you are using it: modifying the string, putting zeroes in order to mark words, etc. You do only need to add a "char * str" private attribute to StringTokenizer.

The trick here is that you are creating your own copy of the string, thus you can manipulate anyway you want, provided you free it in the destructor. The only downside is that you need memory in order to store the copy (so you need twice memory for each string).

The reason your solution didn't work is that literals are or can be stored in read-only memory, so they are correctly marked as const char*, being "impossible" to write to them.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜