3

我正在为 C++ 中的家庭作业编写一个字符串标记化程序,它使用指针。但是,当我运行和调试它时,它说我的指针 pStart 无效。我有一种感觉,我的问题存在于我的参数构造函数中,我在下面包含了构造函数和对象创建。

如果您能告诉我为什么它说 pStart 在我调试它时是一个错误的指针,我将不胜感激。

谢谢!

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:

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

函数 Next 应该返回指向 char 数组中下一个单词的指针。目前还没有完成。:)

完整的 stringtokenizer.h:

#pragma once

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

完整的 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;
4

4 回答 4

3

您无法pStart在标记器中进行修改,因为 C 和 C++ 中的文字字符串不可修改,它具有 type const char *。当你做作业时

pStart = pArray;

在您的构造函数中,pStart现在指向不可修改的内存。这很可能是你的问题。如果不是这种情况,您将需要发布更多代码。

编辑:查看您的编辑后,看起来您已更改代码以使用数组。那挺好的。我没有详细查看您的代码,但至少有一个错误:

while (pStart != NULL)

应该:

while (pStart != NULL && *pStart)

这是因为您想在您点击'\0'字符串中的终止符时停止循环。

我不确定你为什么在 C++ 中使用 C 风格的字符串。这是你作业中的要求吗?

于 2010-02-06T03:24:41.160 回答
1

改变

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

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

字符串文字始终是 const char * const 变量,并且由于 C++ 自动将非 const 强制转换为 const,因此它不能将 const 强制转换为非 const。

您也可以创建不同的构造函数,但我认为您不需要它,只要您只读取 pArray 字符串即可。

你可以使用这样的东西:

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;
}
于 2010-02-06T03:23:13.970 回答
0

将 StringTokenizer 类中的 pStart 从 char* 更改为 const char*,并对构造函数进行相同的更改。

于 2010-02-06T03:38:30.347 回答
0

在我看来,你应该改变StringTokenizer的构造函数和析构函数:

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

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

现在您可以按照您使用它的方式使用 pStart:修改字符串、放置零以标记单词等。您只需要向 StringTokenizer 添加一个“char * str”私有属性。

这里的诀窍是您正在创建自己的字符串副本,因此您可以随意操作,只要您在析构函数中释放它。唯一的缺点是您需要内存来存储副本(因此每个字符串需要两倍的内存)。

您的解决方案不起作用的原因是文字已经或可以存储在只读内存中,因此它们被正确标记为 const char*,“不可能”写入它们。

于 2010-02-06T10:03:15.610 回答