2

この例に従って、指定された区切り文字で文字列を分割しようとしています: http://msdn.microsoft.com/en-us/library/ftsafwz3(v=VS.90).aspx

私のコードは、Visual C++ 2010 ではエラーなしでコンパイルされますが、実行しようとすると、次のエラー メッセージが表示されます。

Test.exe の 0x773a15de で未処理の例外: 0xC0000005: アクセス違反の読み取り場所 0x00000000。

これが私のコードです:

#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <regex>

using namespace std;

vector<char *> splitString(char in[])
{
vector<char *> parts(15);
char seps[]   = " ,\t\n";
char *next_token1 = NULL;
char *token1 = NULL;
token1 = strtok_s(in, seps, &next_token1);
while ((token1 != NULL))
{
    if (token1 != NULL)
    {
        token1 = strtok_s( NULL, seps, &next_token1);
                    //printf( " %s\n", token1 );
        parts.push_back(token1);
    }
}
return parts;
}

int main(int argc, char * argv[])
{
char string1[] =
    "A string\tof ,,tokens\nand some  more tokens";
vector<char *> parts=splitString(string1);
cout << parts[0] <<endl;
cout << parts[1] <<endl;
return 0;
}

ベクトルの要素を表示しようとするのは違法のようですが、なぜですか?

ベクターの容量は十分である必要があります。

printf( " %s\n", token1 );

while ループでトークンを出力します。

4

2 に答える 2

2

の使い方vectorが間違っています。これは15要素で構成され、最初の 15 のpush_back()に新しい要素を追加する文字列を追加するために使用されます。これは、最初の要素が割り当てられていない (null)ことを意味します。15

std::cout << parts[0] << end; // parts[0] is null

また:

  • 構築時に要素を事前に割り当てない、または
  • use operator[]and not push_back()(追加のループ ターミネータを追加して、ベクトルの末尾を超えることを保護します)

( に変更することを検討してくださいstd::vector<std::string>。)

入力文字列からboost::split()トークンのリスト ( ) を生成し、複数の区切り文字を指定できることを言及するだけです。std::vector<std::string>

于 2012-10-03T08:12:13.177 に答える
2

問題は、一般的な注意事項です。C strtok++ で関数 (のファミリー) を使用しています。この古いAPIはその引数を変更することに注意してください。これは多くの場合、期待どおりではないため、このCライブラリ関数を使用しないことをお勧めします。

さらに、15 個の要素が読み取られ、「余剰」要素が初期化されないままになると想定しています。これもまた、これらの要素にアクセスする際に未定義の動作を引き起こします。


あなたがそれを使用しているので、C++アプローチを提案できますか:

#include <iostream>
#include <sstream>
#include <iterator>
#include <algorithm>

using namespace std;

vector<std::string> splitString(const char in[])
{
    std::istringstream iss(in);
    std::istream_iterator<std::string> first(iss), last;

    std::vector<std::string> parts;
    std::copy(first, last, std::back_inserter(parts));
    return parts;
}

int main(int argc, char * argv[])
{
    const char string1[] = "A string\tof ,,tokens\nand some  more tokens";
    vector<std::string> parts = splitString(string1);
    cout << parts[0] <<endl;
    cout << parts[1] <<endl;
    return 0;
}

これは、デフォルトで iostream がskipws(空白をスキップする)という事実を利用しています。

于 2012-10-03T08:24:40.033 に答える