質問

長々と書きましたが、単純な文字列tokenizingを使用してプログラムのポインタのための最近の学校プロジェクト.しかし、うまく自分の StringTokenizer::Next() 方法、そういうわけで、これを返すポインタを最初の文字の次の単語のchar配列に格納します。ませんのでコンパイル時にエラー、ん、ランタイムエラーが発生する状態:

Unhandled exception at 0x012c240f in Project 5.exe: 0xC0000005: Access violation reading location 0x002b0000.

のプログラムtokenizesのchar配列のの、その後停止し、このエラーを出します。思いで、 NULL チェックになっている私 Next() 方法。

ではどうしたらいいですか?

また、予告なしかできなかったんより効率的にまたはより良い練習、ぜひ<url>までご連絡ください。

感謝!!


StringTokenizer.h:

#pragma once

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

StringTokenizer.cpp:

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

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

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

char* StringTokenizer::Next(void)
{
pNextWord = pStart;
if (pStart == NULL) { return NULL; }

while (*pStart != delim) // access violation error here
{
    pStart++;
}

if (pStart == NULL) { return NULL; }

*pStart = '\0'; // sometimes the access violation error occurs here
pStart++;

return pNextWord;
}

StringTokenizer::~StringTokenizer(void)
{
delete pStart;
delete pNextWord;
}

Main.cpp:

// The PrintHeader function prints out my
// student info in header form
// Parameters - none
// Pre-conditions - none
// Post-conditions - none
// Returns - void
void PrintHeader();

int main ( )
{
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;

PrintHeader();

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


編集:

大丈夫、私にとって、プログラム細かい作業を、どの区切り文字はスペースです。がんでは`/'としてdelimでのアクセス違反エラーです。そのアイデア?

機能と空間

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

if (*pStart == '\0') { return NULL; }

while (*pStart != delim)
{
    pStart++;
}

if (*pStart = '\0') { return NULL; }

*pStart = '\0';
pStart++;

return pNextWord;
}
役に立ちましたか?

解決

この回答については編集質問やコメント/観察その他の回答...

最初に、どのような状態pStart時Next()が呼?

  1. pStartがNULLの場合(デフォルトのコンストラクタまたは別段の定めのNULL)
  2. *pStartは'\0'(空文字列の文字列)
  3. *pStartはdelim(空の文字列で隣接する区切り文字)
  4. *pStartは何(空文字列トークン)

今だけの心配をする必要が初のオプションです。そう考えると、使用のオリジナルの"場"こちらで確認できます:

if (pStart == NULL) { return NULL; }

これは、私たちの心配が要件2または3ですか。おそらく扱いたい隣接する区切り文字として空の文字列トークンとしてどの開始と終了の文字列になります。(なければ、調整のお肉を挽肉にしました。) しながらループの取り扱い、提供またの追加'\0'にチェックが必要に関わらず):

while (*pStart != delim && *pStart != '\0')

後しながらループは、あなたが注意が必要です。どのような国か?

  1. *pStartは'\0'(トークンを端末の文字列)
  2. *pStartはdelim(トークンで次の区切り文字)

ご注意pStartもNULLにできません。

希pNextWord(現在のトークン) これらの条件はありませんの最後のトークン(時-pStartは'\0').のコードを取り扱う場合には2つの正しくない場合1(オリジナルコードの危険増加pStart過去の'\0'は、新しいコードの返却はNULL。また、リセットpStart用例1正しく、その次に呼び出される次の()はNULLを返します。てしまい正確なコードとしての運動リーダーでの宿題をすべて;)

この運動に概要を示可能な状態のデータの全機能を確定するための正しい行動を各国における、正式に定義ベースの場合に対再帰的の場合を含ます。

最後に、気付いたので削除を求両pStartとpNextWordにデストラクタ.まず、削除する配列を使用する必要があり delete [] ptr; (つまり、配列の削除を押します。-第二に、すこともございません削除pStartとpNextWordでpNextWordポイントのpStart配列になります。第三に、pStartなポイントのメモリですが別途必要員は、原始の delete [] ます。最後に、これらの配列が割り当てのスタックなエディタで開き、ヒープであること char var[], ない char* var = new char[]めなが削除されます。したがって、この活空のデストラクタ.

できるようにチップをカウントの数 newdelete 電話;は同じ番号になる。この場合、ゼロ new 通話、 delete 通話が深刻な問題です。また反対側かを示すメモリリークを引き起こします。

他のヒント

アクセス違反または"区分断層"の一部のOsのことだった読み込みまたは書き込み位置をメモリにすると割り当てられます。

を考慮しながらループでは、Next():

while (*pStart != delim) // access violation error here
{
    pStart++;
}

そうすることで文字列 "blah\0".ているので注意してほしの終了はnullになります。現在、自分自身に尋ね:どのようなループから停止まで到達すると文字列の末尾に?

より重要なのは:う *pStart 場合、ループ 失敗した ス文字列の末尾に?

内::次に確認する必要があるのdelim文字も要チェックのためのバッファに、私の推測で示されるa\0)です。

while (*pStart != '\0' && *pStart != delim) // access violation error here
{
    pStart++;
}

というと、これらの試験::次

if (pStart == NULL) { return NULL; }

すべきことです。

if (*pStart == '\0') { return NULL; }

は、確認のためのNul文字ではなく、nullポインタです。そのなかすいためこれらの試験の検出、初期化されていないpStartポインタの終わりにバッファです。

アクセス違反の通常手段と悪いポインタです。

この場合、最も蓋然性が高い原因がなくなってきた文字列の前にあります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top