【问题标题】:How to split a string by another string in Arduino?如何在Arduino中用另一个字符串分割一个字符串?
【发布时间】:2019-02-22 08:55:41
【问题描述】:

我有一个如下的字符数组:

char array[] = "AAAA... A1... 3. B1.";

如何在 Arduino 中通过字符串 "..." 拆分此数组?我试过了:

ptr = strtok(array, "...");

输出如下:

AAAA,
 A1,
 3,
 B1

但我实际上希望输出是

AAAA,
A1,
3.B1.

如何得到这个输出?

编辑:

我的完整代码是这样的:

char array[] = "AAAA... A1... 3. B1.";
char *strings[10];
char *ptr = NULL;`enter code here` 

void setup()
{
       Serial.begin(9600);

       byte index = 0;
       ptr = strtok(array, "...");  // takes a list of delimiters
       while(ptr != NULL)
       {
            strings[index] = ptr;
            index++;
            ptr = strtok(NULL, "...");  // takes a list of delimiters
       }

       for(int n = 0; n < index; n++)
       {
          Serial.println(strings[n]);
       }
    }

【问题讨论】:

  • 欢迎来到 SO:您写道:“我已经尝试过 strtok() 函数,但是......”很好 :-) 现在请在此处发布该代码并解释出现了什么问题。然后我们可以帮助您更正代码。顺便说一句:strtok 可能是错误的函数,但是当您使用 strtok 发布代码时,我们将能够向您发送正确的方向。
  • @4386427 谢谢我是stackoverflow的新手。我进行了编辑
  • @StefanBecker 进行了编辑,请检查问题
  • 您可以使用strstr 并自己迭代。 strtok 查找分隔符中的任何字符,因此 "..." 将得到与 "." 相同的结果。
  • 现在您知道strtok 无法区分单个'.' 和多个'...',您可以向我们展示您尝试使用strstr 的版本。

标签: c++ arduino embedded c-strings


【解决方案1】:

主要问题是strtok 确实在另一个字符串中找到一个字符串。 strtok 在字符串中查找字符。当您向strtok 提供多个字符时,它会查找其中的任何。因此,写strtok(array, "..."); 与写strtok(array, "."); 完全相同。这就是为什么你在“3”之后得到一个拆分。

有多种方法可以做你想做的事。下面我将向您展示一个使用strstr 的示例。与 strtokstrstr 函数不同,它确实在字符串中找到子字符串 - 正是您要查找的内容。但是..strstr 不是分词器,因此需要一些额外的代码来打印子字符串。

应该这样做:

int main()
{
  char array[] = "AAAA... A1... 3. B1...";

  char* ps = array;
  char* pf = strstr(ps, "..."); // Find first substring
  while(pf)
  {
    int len = pf - ps;          // Number of chars to print
    printf("%.*s\n", len, ps);
    ps = pf + 3;
    pf = strstr(ps, "...");     // Find next substring
  }
  return 0;
}

【讨论】:

    【解决方案2】:

    除了第二个参数的作用外,您可以将自己的 split 实现为 strtok

    #include <stdio.h>
    #include <string.h>
    
    char * split(char *str, const char * delim)
    {
      static char * s;
      char * p, * r;
    
      if (str != NULL)
        s = str;
    
      p = strstr(s, delim);
    
      if (p == NULL) {
        if (*s == 0)
          return NULL;
    
        r = s;
        s += strlen(s);
        return r;
      }
    
      r = s;
      *p = 0;
      s = p + strlen(delim);
    
      return r;
    }
    
    int main()
    {
      char s[] = "AAAA... A1... 3. B1.";
      char * p = s;
      char * t;
    
      while ((t = split(p, "...")) != NULL) {
        printf("'%s'\n", t);
        p = NULL;
      }
    
      return 0;
    }
    

    编译和执行:

    /tmp % gcc -g -pedantic -Wextra s.c
    /tmp % ./a.out
    'AAAA'
    ' A1'
    ' 3. B1.'
    /tmp % 
    

    我在 '' 之间打印以显示返回空格,因为我不确定您是否想要它们,所以在这种情况下,delim 不仅是...

    【讨论】:

      【解决方案3】:

      因为您将其标记为 c++,所以这里是您的代码的 c++“版本”:

      #include <iostream>
      using std::cout;
      using std::endl; 
      
      #include <vector>
      using std::vector;
      
      #include <string>
      using std::string;
      
      
      class T965_t
      {
         string         array;
         vector<string> strings;
      
      public:
         T965_t() : array("AAAA... A1... 3. B1.") 
            {
               strings.reserve(10);
            }
      
         ~T965_t() = default;
      
         int operator()() { return setup(); } // functor entry
      
      private: // methods
      
         int setup()
            {
               cout << endl;
               const string pat1 ("... ");
               string s1 = array; // working copy
      
               size_t indx = s1.find(pat1, 0); // find first ... pattern
               // start search at ---------^
               do
               {
                  if (string::npos == indx)  // pattern not found
                  {
                     strings.push_back (s1); // capture 'remainder' of s1
                     break;                  // not found, kick out
                  }
      
                  // else 
                  // extract --------vvvvvvvvvvvvvvvvv
                  strings.push_back (s1.substr(0, indx));  // capture
                  // capture to vector
      
                  indx += pat1.size(); // i.e. 4
      
                  s1.erase(0, indx); // erase previous capture 
      
                  indx = s1.find(pat1, 0);          // find next
      
               } while(true);
      
               for(uint n = 0; n < strings.size(); n++)
                  cout << strings[n] << "\n";
      
               cout << endl;
               return 0;
            }
      
      }; // class T965_t
      
      int main(int , char**) { return T965_t()(); } // call functor
      

      有输出:

      AAAA
      A1
      3. B1.
      

      注意:我保留更改“3. B1”。到“3.B1.”,并在每行末尾添加逗号(最后一行除外)作为 OP 的练习(如果需要)。

      【讨论】:

      • 想到一个 ATMega48 来实现这个,我不禁轻笑出声。
      • 原始代码也是 C++,风格更适合 Arduino。此代码不是 Arduino 框架代码。原代码中的Setup()函数是Arduino框架的一部分,用于执行初始化。
      【解决方案4】:

      我找了一个拆分功能,但没有找到符合我要求的,所以我做了一个,到目前为止它对我有用,当然将来我会做一些改进,但它让我脱离了麻烦。

      但也有 strtok 功能并更好地使用它。 https://www.delftstack.com/es/howto/arduino/arduino-strtok/

      我有拆分功能

      Arduino 代码:

      void split(String * vecSplit, int dimArray,String content,char separator){
      if(content.length()==0)
          return;
       content = content + separator;
       int countVec = 0;
       int posSep = 0;
       int posInit = 0;
       while(countVec<dimArray){
         posSep = content.indexOf(separator,posSep);
         if(posSep<0){
          return;
         } 
       countVec++;       
       String splitStr = content.substring(posInit,posSep);
       posSep = posSep+1; 
       posInit = posSep;
       vecSplit[countVec] = splitStr;
       countVec++;    
      

      } }

      Llamada 一个函数:

      smsContent = "APN:4g.entel;DOMAIN:domolin.com;DELAY_GPS:60";
      String vecSplit[10];
      
      split(vecSplit,10,smsContent,';');
      for(int i = 0;i<10;i++){
         Serial.println(vecSplit[i]);    
      }
      

      字符串输入: APN:4gentel;DOMAIN:domolin.com;DELAY_GPS:60

      输出:

      • APN:4g.entel
      • 域:domolin.com
      • DELAY_GPS:60
      • 重置:真

      enter image description here

      【讨论】:

        猜你喜欢
        • 2017-11-30
        • 1970-01-01
        • 2015-06-26
        • 1970-01-01
        • 1970-01-01
        • 2023-03-25
        • 2021-12-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多