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

pStartCおよびC++のリテラル文字列は変更できないため、トークナイザーで変更することはできません。タイプはconst char *です。あなたが割り当てを行うとき

pStart = pArray;

コンストラクターで、pStartは変更不可能なメモリを指しています。おそらくそれがあなたの問題です。そうでない場合は、さらにコードを投稿する必要があります。

編集:編集内容を確認すると、配列を使用するようにコードを変更したようです。それは良い。私はあなたのコードをあまり詳しく調べていませんが、少なくとも1つのエラーがあります:

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)

文字列リテラルは常にconstchar* const変数であり、C++は自動的にnonconstをconstにキャストするため、constをnonconstにキャストすることはできません。

さまざまなコンストラクターを作成することもできますが、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*からconstchar*に変更し、コンストラクターにも同じ変更を加えます。

于 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」プライベート属性を追加するだけで済みます。

ここでの秘訣は、文字列の独自のコピーを作成していることです。したがって、デストラクタで解放すれば、任意の方法で操作できます。唯一の欠点は、コピーを保存するためにメモリが必要なことです(したがって、文字列ごとに2倍のメモリが必要です)。

ソリューションが機能しなかった理由は、リテラルが読み取り専用メモリに格納されている、または格納できるため、リテラルがconst char *として正しくマークされ、書き込みが「不可能」であるためです。

于 2010-02-06T10:03:15.610 に答える