【问题标题】:Split values in string separated by both comma and a letter以逗号和字母分隔的字符串中的拆分值
【发布时间】:2018-08-02 19:44:29
【问题描述】:

我目前正在使用 Arduino,我有一个字符串,例如看起来像这样:

"30,30,20,10,50,50M20"

我说例如,因为值总是可以改变的。但是,该字母将始终是 1 个单词的字母。总会有 7 个数字和 1 个字母。该字母将始终介于 6 和 8 之间。

在该字符串中有不同的值,它们由逗号和字母分隔,这使得解决方案更加棘手。

如果我破坏了上面的字符串,我需要像这样存储它:

A = 30
B = 30
C = 20
D = 10
E = 50
F = 50
G = M
H = 20

这些值会定期更改(以及每个值的长度),因此必须以某种方式设置代码,以便通过 ',' 和字母(在本例中为 'M')分隔值。

这是我自己尝试做的:

char c = Serial.read(); 
FindA = c.indexOf(',');
A = c.substring(0, ind1); 
FindB = c.indexOf(',', ind1+1 );       
B = c.substring(ind1+1, ind2+1);

然后以某种方式实现,以便取出字母前后的值(也需要存储)。

我也有这个评价 String recievedMessage += (char)Serial.read();.

我正在开发 Arduino。

【问题讨论】:

  • 我不熟悉 arduino,但在 C++ 中 char 是单字节字符原始类型。该类型没有任何成员函数。
  • Serial.read()的返回类型是什么?
  • @smac89 Arduino 的Serial.read() 返回int
  • @FrançoisAndrieux,Op 正在调用read(小写)方法。那是一样的吗? Nvm,我看到这是一个错字
  • 请注意,这个String recievedMessage += (char)Serial.read(); 不是有效的 C++。它应该是 String recievedMessage; recievedMessage += (char)Serial.read();String recievedMessage = String((char)Serial.read());

标签: c++ string split arduino


【解决方案1】:

假设字符串作为行发送(末尾有一个换行符\n)。

typedef struct {
    int A = 0;
    int B = 0;
    int C = 0;
    int D = 0;
    int E = 0;
    int F = 0;
    char G = 0;
    int H = 0;
} Line;

typedef void (*LineHandler)(Line data);

bool line_parser(char c, LineHandler line_handler) {
    static Line data;
    static int value = 0;
    static byte state = 0;
    bool complete = false;

    // ignore the carriage return character
    if (c == '\r') return complete;

    if (state < 8) {
        if (isdigit(c)) {
            value = value*10 + c-'0';  // add the digit
        }
        else if (c == ',' || c == '\n') {
            // if a comma or end of line is found, save the value
            switch (state) {
                case 0: data.A = value; break;
                case 1: data.B = value; break;
                case 2: data.C = value; break;
                case 3: data.D = value; break;
                case 4: data.E = value; break;
                // the F and G are set when the letter is found
                case 7: data.H = value; break;
            }
            // advance the parsing state and reset the value
            state++;
            value = 0;
        }
        else if (state == 5 && isalpha(c)) { // if parsing the 6th number and a letter is found
            data.F = value; // save the 6th number
            data.G = c; // save the letter
            state += 2; // advance to parsing the 8th value
            value = 0; // reset the value
        }
        else
            state = 10; // unexpected character; stop the parser
    }
    if (c == '\n') {
        if (state == 8) {
            //got complete line
            line_handler(data);
            complete = true;
        }
        else {
            // parsing failed
        }
        // reset the parser
        value = 0;
        state = 0;
    }
    return complete;
}

void handle_line(Line data) {
    // just print out the data
    Serial.println("Line:");
    Serial.print("A = ");
    Serial.println(data.A);
    Serial.print("B = ");
    Serial.println(data.B);
    Serial.print("C = ");
    Serial.println(data.C);
    Serial.print("D = ");
    Serial.println(data.D);
    Serial.print("E = ");
    Serial.println(data.E);
    Serial.print("F = ");
    Serial.println(data.F);
    Serial.print("G = ");
    Serial.println(data.G);
    Serial.print("H = ");
    Serial.println(data.H);
    Serial.println();
}

void setup() {
    Serial.begin(115200);
}

void loop() {
    if (Serial.available()) {
        line_parser(Serial.read(), handle_line);
    }
}

这个解析器是非阻塞的,是一个字符一个字符的输入,在接收到整行之后,它会调用一个函数来处理解析后的数据。

发送:

54,125,11045,11,78,4H45
invalid line
11,22,33,44,55,66K88
30,30,20,10,50,50M20

应该发回:

Line:
A = 54
B = 125
C = 11045
D = 11
E = 78
F = 4
G = H
H = 45

Line:
A = 11
B = 22
C = 33
D = 44
E = 55
F = 66
G = K
H = 88

Line:
A = 30
B = 30
C = 20
D = 10
E = 50
F = 50
G = M
H = 20

【讨论】:

    【解决方案2】:

    您可以为您的字符串编写一个小型解析器,例如:

    #include<cstdlib>
    #include<cctype>
    #include<iterator>
    #include<vector>
    
    std::vector<int> values(1);
    char separator = ',';
    
    // read every char from the stream and store it in i
    for (int i = Serial.read(); i >= 0; i = Serial.read())
    {
        // check if i is a digit (and if so, append it to the previous digit)
        if (std::isdigit(i))
        {
            values.back() = values.back() * 10 + std::atoi(i);
        }
        // check if i is a letter [A-Z][a-z]
        else if (std::isalpha(i))
        {
            values.back() = i;
            i = separator;
        }
    
        // check if i is the separator 
        if (i == separator)
        {
            values.push_back(0);
        }    
    }
    
    A = values[0];
    B = values[1]
    // ...
    

    【讨论】:

    • 嘿,现在测试一下。我编写的所有代码都没有语法错误,但我不确定如何将所有不同的值存储在 ` if (i == separator)` 内的自己的字符串中
    • A = value[0], B = value[1] 像这样吗?
    • @CarlosRodrigez 我更新了代码。从您的问题来看,您似乎对 C++ 不是很熟悉。我强烈建议阅读一些有关现代 C++(C++ 11 或更高版本)的基础知识。
    • 我去看看!是的,我对 C++ 很陌生。会做
    • 尝试在 Arduino 上下载矢量。有点挣扎。是否有其他选择或向量是要走的路?
    猜你喜欢
    • 2018-12-21
    • 1970-01-01
    • 2015-03-07
    • 1970-01-01
    • 2017-01-05
    • 1970-01-01
    • 1970-01-01
    • 2012-05-24
    相关资源
    最近更新 更多