【问题标题】:Reading/parsing multiple INTs from a String从字符串中读取/解析多个 INT
【发布时间】:2012-08-19 03:12:33
【问题描述】:

我一直在阅读有关将字符串转换为整数、“atoi”和“strol”C 标准库函数以及其他一些我似乎无法理解的内容。

我最初尝试做的是从字符串中获取一系列数字并将它们放入一个 int 数组中。这是字符串的sn-p(单个字符串中有多行):

getldsscan
AngleInDegrees,DistInMM,Intensity,ErrorCodeHEX
0,0,0,8035
1,0,0,8035
2,1228,9,0
3,4560,5,0
...
230,1587,80,0
231,0,0,8035
232,1653,89,0
233,1690,105,0
234,0,0,8035
...
358,0,0,8035
359,0,0,8035
ROTATION_SPEED,4.99

输出来自我的真空机器人“Neato XV-21”。我已经通过 COM 端口连接获得了上面的输出,并且我目前将它存储在一个字符串中。 (因为机器人可以输出各种不同的东西)。在这个例子中,我从一个 stringneatoOutput 中读取数据,该字符串包含了在我向其激光扫描仪请求更新后机器人的输出。

“getldsscan”是我发送给机器人的命令,当我得到 COM 输出时它只是被读回,所以我们跳过它。下一行只是关于输出的每个值的有用信息,可以跳过。从此输出有趣的数据。


我正在尝试获取每行数据中第二个数字的值。该数字是从扫描仪到障碍物的距离。我想要一个整洁的 int distanceArray[360] ,其中包含机器人报告的所有距离值。机器人将输出 360 个距离值。

我还没有对错误检查或从每行数据中读取其他值大惊小怪,因为一旦我弄清楚如何提取我想要的当前基本数据,我就会得到它们。到目前为止,我可以使用类似的东西:

int startIndex = 2 + neatoOutput.find("X",0); //Step past end of line character

所以 startIndex 应该给我数据开始位置的字符索引,但正如您在上面的示例中看到的那样,每个数字的值的大小范围从单个字符到 4 个字符.所以简单地在字符串中前进一个设定的数量是行不通的。

我想做的事情是……

neatoOutput.find("\n",startIndex );

如果有更多的代码,我应该能够一次解析一行。但是我仍然对如何提取我想要的行中的第二个数字感到困惑。


如果有人对对机器人进行黑客攻击/编码感兴趣,您可以转到:-



更新:已解决

感谢大家的帮助,这是我近期要使用的代码。您会注意到我最终不需要知道我认为需要使用的 int startIndex 变量。

//This is to check that we got data back
signed int dataValidCheck = neatoOutput.find("AngleInDegrees",0);
if (dataValidCheck == -1)
    return;

istringstream iss(neatoOutput);
int angle, distance, intensity, errorCode;
string line;

//Read each line one by one, check to see if its a line that contains distance data
while (getline(iss,line))
{
    if (line == "getldsscan\r")
        continue;
    if (line == "AngleInDegrees,DistInMM,Intensity,ErrorCodeHEX\r")
        continue;

    sscanf(line.c_str(),"%d,%d,%d,%d",&angle,&distance,&intensity,&errorCode); //TODO: Add error checking!
    distanceArray[angle] = distance;
}

【问题讨论】:

    标签: c++ c string robot


    【解决方案1】:

    试试这个(未经测试,所以可能是小错误):

    #include <iostream>
    #include <sstream>
    #include <string>
    #include <cstdio>
    using namespace std;
    
    int main()
    {
        string s("3,2,6,4\n2,3,4,5\n");
        istringstream iss(s);
        int a, b, c, d;
        string line;
        while (getline(iss,line))
        {
            // Method 1: Using C
            sscanf(line.c_str(),"%d,%d,%d,%d",&a,&b,&c,&d);
    
    
            // Method 2: Using C++
            std::stringstream  lineStream(line);
            char  comma;
            lineStream >> a >> comma >> b >> comma >> c >> comma >> d;
    
    
            // do whatever
        }
    
    }
    

    【讨论】:

    • 你应该永远使用来自 sscanf 的返回值
    【解决方案2】:

    您可以自己解析字符串。很简单。

    代码:

    int ParseResult(const char *in, int *out)
    {
        int next;
        const char *p;
    
        p = in;
        next = 0;
    
        while (1)
        {
            /* seek for next number */
            for (; !*p && !isdigit(*p); ++p);
    
            if (!*p)
                break;  /* we're done */
    
            out[next++] = atoi(p);  /* store the number */
    
            /* looking for next non-digit char */
            for (; !*p && isdigit(*p); ++p);
        }
    
        return next;  /* return num numbers we found */
    }
    

    【讨论】:

    • 我认为你的 for 循环条件需要修改。第一个循环过去数字( isdigit() true 导致另一个循环),第二个循环非数字(!isdigit() true 导致另一个循环)。此外,两个 for 循环都将空终止符视为继续循环的原因( !*p (或 *p == '\0' )再次表示循环。
    猜你喜欢
    • 2016-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-25
    • 1970-01-01
    • 2017-09-26
    • 2013-08-12
    • 1970-01-01
    相关资源
    最近更新 更多