我刚开始第一次使用stringstream而且我喜欢这个概念,但是我很难通过我的stringstream函数找到我在内存中超出范围的地方。
我的功能是什么,它需要一个字符串,例如,“N02550 G3 X16.7379 Y51.7040 R0.0115”这是我工作的CNC机床的机器代码。我将字符串传递给字符串流,以便找到旁边有X,Z,Y的字符串,这些是坐标。然后它会在开始时删除字符,以便将浮点数保存到我的结构“坐标”(有3个双精度数,x,y,z)。
当我运行一个包含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文件。谢谢!
答案 0 :(得分:2)
尝试更改:
while(ss)
{
ss >> holder;
...
if(ss.eof()) // to get out of the ss stream
break;
}
简单地说:
while(ss >> holder)
{
...
}
你可以在每个分支(X / Y / Z)中删除对clear
的调用,因为它不会真正做任何事情,因为sss
是暂时的,而你#&# 39;不要再用它做任何事情(没有点设置你将要在之后丢弃的东西上的标记)。我怀疑在holder.at(0)
失败后尝试访问ss >> holder
时,您的超出范围问题就出现了。
您通常希望在读取令牌后立即检查输入失败,并且尝试输入和立即检查失败的便捷方法是简单地检查ss >> token
是否评估为真。所以我们可以编写如下代码:
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;
}
}