【问题标题】:Extract ints from a string [closed]从字符串中提取整数 [关闭]
【发布时间】:2017-08-13 18:18:35
【问题描述】:

我正在尝试从 Arduino 上的字符串中提取一些整数。我正在使用已链接到手机的 Bluefruit 蓝牙模块。

我手机上的一个应用程序通过 Bluefruit 的 TX/RX 向 Arduino 发送一串数据。

我成功地从应用程序接收到数据,并且我可以在我的计算机上的串行监视器中看到它。字符串格式如下:x:xxx,xxx,xxx,第一个数字是 1 到 6,其他数字是三个 0-255。

例如:1:171,54,201

字符串还包含一个回车,因为下一个字符串总是从新行开始。

谁能帮我提取这些整数并将它们设置为变量?

【问题讨论】:

    标签: c++ string int


    【解决方案1】:

    你可以使用Csscanf()函数:

    #include <stdio.h>
    
    char line[] = "1:171,54,201"; // read a line from Bluetooth
    int num1, num2, num3, num4;
    
    if (sscanf(line, "%d:%d,%d,%d", &num1, &num2, &num3, &num4) == 4)
    {
        // use numbers as needed
    }
    

    或者 C++ 包装器,std::sscanf():

    #include <cstdio>
    
    char line[] = "1:171,54,201"; // read a line from Bluetooth
    int num1, num2, num3, num4;
    
    if (std::sscanf(line, "%d:%d,%d,%d", &num1, &num2, &num3, &num4) == 4)
    {
        // use numbers as needed
    }
    

    如果您有可用的 STL(显然 Arduino 没有),您可以改用 STL std::istringstream 类:

    #include <string>
    #include <sstream>
    
    std::string line = "1:171,54,201"; // read a line from Bluetooth
    int num1, num2, num3, num4;
    
    std::istringstream iss(line);
    char ignore;
    
    if (iss >> num1 >> ignore >> num2 >> ignore >> num3 >> ignore >> num4)
    {
        // use numbers as needed
    }
    

    或者:

    #include <string>
    #include <sstream>
    
    bool readInt(std::istream &in, char delim, int &value)
    {
        std::string temp;
        if (!std::getline(in, temp, delim)) return false;
        return (std::istringstream(temp) >> value);
    }
    
    std::string line = "1:171,54,201"; // read a line from Bluetooth
    int num1, num2, num3, num4;
    
    std::istringstream iss(line);
    
    if (readInt(iss, ':', num1) && readInt(iss, ',', num2) && readInt(iss, ',', num3) && readInt(iss, '\n', num4))
    {
        // use numbers as needed
    }
    

    【讨论】:

    • 这似乎是一个很好的解决方案。我现在正在尝试,但我有一个问题,它说字符串不是 std 的一部分。我也不能包含 我正在更新 Arduino IDE 以查看是否可以解决问题。
    • @Lucavanderknaap Arduino“C++”不是真正的“C++”,它更像是一个受限制的子集/方言。供应商在 Arduino 上不提供 STL,但是那里有针对微控制器的小型受限实现。
    • @RemyLebeau 我已将 .h 添加到字符串中,现在它包含它,但我仍然有“字符串不是 std 的成员”的错误
    • @user2176127 所以你的意思是不可能使用 Remy 建议的解决方案,因为这些方法根本不适用于 arduino?
    • @Lucavanderknaap &lt;string&gt;&lt;string.h&gt; 是两个不同的东西。但是,是的,如果 STL 不可用,那么您可以忽略我的大部分答案。 sscanf() 来自 C,而不是 C++,所以试试吧。
    【解决方案2】:

    通过谷歌快速搜索类似问题,我发现an example 如何使用以下代码将字符串 IP 地址转换为数字:

    std::string ip ="192.168.1.54";
    std::stringstream s(ip);
    int a,b,c,d; //to store the 4 ints
    char ch; //to temporarily store the '.'
    s >> a >> ch >> b >> ch >> c >> ch >> d;
    

    但是,由于您的问题“略有”不同,您可以执行以下操作:

    std::string givenExample = "1:171,54,201"
    
    //Since it is known that the value will be 1-6, just take
    //the ASCII value minus 30 hex (or '0') to get the actual value.
    int firstNumber = ((int)givenExample.at(0) - 0x30); //or minus '0'
    
    givenExample.erase(0, 2); //Remove "1:" from the string
    
    std::stringstream s(givenExample);
    int secondNumber, thirdNumber, fourthNumber;
    char ch;
    s >> secondNumber >> ch >> thirdNumber >> ch >> fourthNumber;
    

    但是,如果将第一个示例与第二个示例进行比较,IP 字符串的格式与您的示例几乎相同:4 个整数,由字符分隔。所以两者都会起作用,这取决于哪一个对你更有意义。

    至于您将如何读取该数据(处理回车),这取决于您与从 Arduino 接收的串行数据流的接口。

    【讨论】:

    • int firstNumber = (int)givenExample.at(0); 将使 firstNumber 包含 49 是第一个字符是 '1'。从中提取号码48(或'0')
    • 好电话,谢谢!我已经更新了我的答案。
    • 不幸的是,arduino 上没有 STL,所以我不能使用它。还是谢谢
    • @Trevor:“但是,由于您的问题“略有”不同” - 怎么样? IP 示例提取 4 个以. 分隔的数字。 OP 想要提取 4 个分隔数字,只是使用不同的分隔符。因此,当 IP 示例与那些不同的分隔符一起工作时,您的整个 firstNumber 示例有点矫枉过正。
    猜你喜欢
    • 2015-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-20
    相关资源
    最近更新 更多