0

初めて stringstream を使い始めたばかりで、コンセプトは気に入っていますが、stringstream 関数でメモリ内の範囲外を正確に見つけるのに苦労しています。

私の関数は、たとえば、「N02550 G3 X16.7379 Y51.7040 R0.0115」などの文字列を受け取ります。これは、私の職場の CNC マシンのマシン コードです。X、Z、Y が隣にある文字列を見つけるために、文字列を stringstream に渡します。これらは座標です。次に、浮動小数点数を私の構造体「座標」に保存するために、最初に文字を取り除きます(x、y、zの3つの倍精度があります)。

この 33 行のマシン コードを含むテキスト ファイルを実行すると、私のプログラムは動作します。718 行のマシン コードで実行すると、718 になり、範囲外のメモリでクラッシュします。次に、別の奇妙な部分は、118,000 行のマシン コードを実行すると、約 22,000 行になり、クラッシュすることです。そのため、なぜそれができるのか、何が問題の原因なのかを理解するのに苦労しています。

関数は次のとおりです。

   void getC(string& line, Coordinates& c)//coordinates holds 3 doubles, x, y, z
{
    //variables
    string holder;
    stringstream ss(line);

    while(ss)
    {
        ss >> holder;
        if(holder.at(0) == 'X')
        {
            holder.erase(0,1);//get rid the the character at the beggining
            stringstream sss(holder);
            sss >> c.x;
            sss.clear();
        }
        if(holder.at(0) == 'Y')
        {
            holder.erase(0,1);
            stringstream sss(holder);
            sss >> c.y;
            sss.clear();
        }
        if(holder.at(0) == 'Z')
        {
            holder.erase(0,1);
            stringstream sss(holder);
            sss >> c.z;
            sss.clear();
        }
        if(ss.eof()) // to get out of the ss stream
            break;

    }
    ss.clear();
}

アプリケーション全体を確認したい場合 (アプリケーションは十分に文書化されています)、マシンコードを含む txt ファイルが必要かどうかを尋ねてください。ありがとうございました!

4

1 に答える 1

2

変更してみてください:

while(ss)
{
    ss >> holder;
    ...
    if(ss.eof()) // to get out of the ss stream
        break;
}

これを簡単にするには:

while(ss >> holder)
{
    ...
}

そして、一時的なものであり、それ以上何もしていないことをclear考えると、実際には何もしないため、各ブランチ (X/Y/Z)でこれらの呼び出しを取り除くことができます(何かにフラグを設定しても意味がありません)。sss直後に破棄します)。holder.at(0)範囲外の問題は、失敗した後にアクセスしようとしたことが原因であると思われss >> holderます。

通常、トークンを読み取った直後に入力の失敗をチェックする必要があります。入力の試行と失敗のチェックの両方を同時に行う便利な方法は、ss >> tokenが true に評価されるかどうかを単純にチェックすることです。したがって、次のようなコードを書くことができます。

if (ss >> token)
{
    ...
}
else
{
    // handle failure if necessary
}

私は一般的に、手動でエラー フラグをチェックするよりも、そのような方法でコードを作成する方が問題を回避する方がはるかに簡単であると考えています。

簡略版として:

void getC(string& line, Coordinates& c)
{
    stringstream ss(line);   
    for (string holder; ss >> holder; )
    {
        const char ch = holder.at(0);
        stringstream sss(holder.substr(1));
        if (ch == 'X')
            sss >> c.x;
        else if (ch == 'Y')
            sss >> c.y;
        else if (ch == 'Z')
            sss >> c.z;
    }
}
于 2015-06-02T05:38:20.580 に答える