0

だから、私はそのようにを返す関数を書こうとしていますvector<char**>

vector<char**> test(string mystr) {

  char*temp=new char[mystr.size()+1];

  strcpy(temp,mystr.c_str());

  char*subStr=strtok(temp,":");

  while(subStr!=NULL) {

    int i=0;

    char**args=new char*[200];

    char*tempsta=newchar[strlen(subStr)+1];

    strcpy(tempsta, subStr);

    args[i]=strtok(tempsta," ");

    while(args[i]!=NULL) {

      i++;

      args[i]=strtok(NULL," ");

    }

    fullVec.push_back(args);

    //cout<<subStr<<endl;

    subStr=strtok(NULL,":");

  }
return fullVec;
}

だから私splitはパラメータ文字列を":"delimeterで、次に""delimeterで上げたい。電話で、からまでcout<<subStrすべてをコメントアウトすると、期待どおりの結果が得られます。これらの行をすべてコメントアウトしないと、最初の行(最初の「:」が検出されるまで)のみが取得され、次に最大のwhileループが終了します。int i=0fullVec.push_back(args)substring

期待されていることのために私は意味します。パラメータが「私の名前は:bon jovi:xxx ab」であると仮定します。すべてがコメント化されている場合、次の行が出力されます。

my name is
 bon jovi
 xxx ab

そのままにしておくとどうなるか

my name is

印刷され、大きなループが終了します

どんな援助もありがたいです、ありがとう!(はい、これははるかにエレガント/簡単に実行できるばかげた演習のように見えることを認識しています...ただし、文字列などを使用して楽しむ前に、このソリューションを機能させたいと思います)

4

3 に答える 3

3

問題は、strtok()が呼び出し間で状態を維持することです。

最初のパラメータがNULLでない場合は、状態をリセットするために使用します。それ以外の場合は、保存した状態を使用して、中断したところから解析を続行します。

strtok()へのネストされた呼び出しが2つあるため、2番目の呼び出しは外部呼び出しの状態を混乱させています。

この呼び出し:

args[i]=strtok(tempsta," ");

strtok()の内部状態をリセットしています。これで、外部呼び出しからの状態について何も認識しなくなります。したがって、内側のループで文字列の最後に到達したとき。

この呼び出し:

subStr=strtok(NULL,":");

現在、内部ループの保存された状態を使用しています。したがって、トークン化ストリームの最後にすでに到達しているため、基本的には終了します。

于 2013-02-16T17:34:13.210 に答える
2

Lokiはすでに完全に指摘しているので、CとC++を混在させないでください。問題のC++ソリューションが必要な場合は、、、などの醜いメモリ管理(RAIIイディオムを参照)を処理するSTLクラスを使用することをお勧めします。std::stringstd::vectorstd::istringstream

関数は次のようになります。

typedef std::vector<std::string> Line;

std::vector<Line> parse(std::string inputString)
{
    std::vector<Line> lines;
    std::istringstream inputStream(inputString);
    for (std::string line; std::getline(inputStream, line, ':'); )
    {
        if (!line.empty())
        {
            lines.push_back(Line());
            std::istringstream lineStream(line);
            for (std::string word; std::getline(lineStream, word, ' '); )
            {
                if (!word.empty())
                    lines.back().push_back(word);
            }
        }
    }
    return lines;
}

使用例:

std::vector<Line> lines = parse("my name is: bon jovi: xxx ab");

for (int li = 0; li < lines.size(); ++li)
{
    for (int wi = 0; wi < lines[li].size(); ++wi)
        std::cout << lines[li][wi] << "_";
    std::cout << std::endl;
}

出力

my_name_is_
bon_jovi_
xxx_ab_

お役に立てれば :)

于 2013-02-16T17:56:51.853 に答える
0

コメントで述べたように、CスタイルとC ++スタイルのコードを混在させているため、かなり混乱します。char* 代わりに頼る「正当な理由」がない限り、またはstd::stringを使用することをお勧めします。stlboost

boost方法:

std::string delims = " :";
boost::split(vector, mystr, boost::is_any_of(delims));

stl方法:

  vector<string> result;
  std::string delims = " :";
  std::istringstream ss( mystr );
  while (!ss.eof())
  {
    getline( ss, field, delims);
    if ((empties == split::no_empties) && field.empty()) continue;
    result.push_back( field );
  }

その他のアプローチと適切な比較については、このcplusplusの記事を参照してください。

于 2013-02-16T17:41:02.043 に答える