代码之家  ›  专栏  ›  技术社区  ›  Pascal

用strtok拆分字符串(嵌套)

  •  1
  • Pascal  · 技术社区  · 6 年前

    我使用arduino MEGA解析url的参数部分。 参数的顺序应该不重要。我有下面的代码,我试着用strtok。

    char text[] = "ssid=SSID&pwd=PASSWORD&userId=1234"
    

    会分道扬镳

    ssid=SSID
    pwd=PASSWORD
    userId=1234
    

    在键和值中再次拆分

    ssid
    SSID
    
    pwd
    PASSWORD
    
    userId
    1234
    

    我试着用史崔托克做第一次分裂。

      char *ptr;
      ptr = strtok(params, "&");
    
      while (ptr != NULL) {
        Serial.println(urlParam);
        ptr = strtok(NULL, "&");
      }
    

    结果如预期:

    输出:

    ssid=ssid
    密码
    用户ID=1234
    

    然后下一个分割:

      char *ptr;
      ptr = strtok(params, "&");
    
      while (ptr != NULL) {
    
        char *paramKey;
        char *paramValue;
        paramKey = strtok(ptr, "=");
        Serial.println(paramKey);
    
        if (paramKey == 'ssid'){
          paramValue = strtok(NULL, "=");
          Serial.println(paramValue);       
    
          ssidName = paramValue;
        }
    
        if (paramKey == 'pwd'){
          ...
        }
    
        if (paramKey == 'userId'){
          ...
        }       
    
        ptr = strtok(NULL, "&");
      }
    

    但结果是

    ssid
    SSID
    

    看起来循环工作不正常。

    我在哪里犯错误? 有没有其他方法可以解决这个字符串?

    4 回复  |  直到 6 年前
        1
  •  3
  •   dbush    6 年前

    这个 strtok 函数使用内部静态变量跟踪其当前状态。当您像您这样对多个交叉排列的不同子串使用该函数时,您将进入内部状态。

    你需要用 strtok_r ,它使用外部变量来跟踪状态。

      char *ptr, *sav1 = NULL;
      ptr = strtok_r(params, "&", &sav1);    // outer strtok_r, use sav1
    
      while (ptr != NULL) {
    
        char *paramKey;
        char *paramValue;
        char *sav2 = NULL;
        paramKey = strtok_r(ptr, "=", &sav2);   // inner strtok_r, use sav2
        Serial.println(paramKey);
    
        if (!strcmp(paramKey, "ssid")) {
          paramValue = strtok_r(NULL, "=", &sav2);  // inner strtok_r, use sav2
          Serial.println(paramValue);       
    
          ssidName = paramValue;
        }
    
        if (!strcmp(paramKey, "pwd")) {
          ...
        }
    
        if (!strcmp(paramKey, "userId")) {
          ...
        }       
    
        ptr = strtok_r(NULL, "&", &sav1);    // outer strtok_r, use sav1
      }
    

    与解析问题无关,也不能将字符串与 == . 你需要使用 strcmp 相反,字符串常量用双引号括起来,而不是单引号。

        2
  •  1
  •   Some programmer dude    6 年前

    你有 问题:

    1. 首先是使用特定于实现的多字符文本,例如。 'ssid' ,当您应该使用 "ssid" .

    2. 第二个问题是 == 比较字符串。几乎不可能去上班,因为你比较 指针 而不是字符串内容。要比较需要使用的字符串 strcmp .

    3. 这个 strtok 函数不可重入。不能有多个 斯特托克 同时进行的牧师。或者分开步骤,或者使用 strtok_s (或 strtok_r 如果有这种功能)。

        3
  •  0
  •   user4853414user4853414    6 年前
    #include <stdio.h>
    #include <string.h>
    
    struct split_result {
        char first_part[64];
        char second_part[64];
    };
    
    split_result return_left(char splitter, const char *str);
    
    int main() {
        /*
            ssid=SSID
            pwd=PASSWORD
            userId=1234
        */
        char *str = "ssid=109304905995";
        split_result result = return_left('=', str);
    
        printf("first part: %s \n second part: %s\n", result.first_part, result.second_part);
    
        return 0;
    }
    
    split_result return_left(char splitter, const char *str) {
        int i = 0;
    
        split_result split_ptr;
    
        while (str[i] != 0) {
            //we found splitter
            if ((char)str[i] == splitter) {
                //remove first half
                strncpy_s(split_ptr.first_part, str, (int)(&str[i]-str));
                break;
            }
    
            //we need to remove second half now
            i++;
        }
        strcpy_s(split_ptr.second_part, &str[i+1]);
        return split_ptr;
    }
    

    我希望这对任何人都有帮助。

        4
  •  0
  •   user3121023    6 年前

    如果输入总是 key=value&...key=value ,您可以遍历字符串并使用 strtok .

    #include <stdio.h>
    #include <string.h>
    
    int main ( void) {
        char text[] = "ssid=SSID&pwd=PASSWORD&userId=1234";
        char *key = NULL;
        char *value = NULL;
        char *ssidName = NULL;
        char *pwdName = NULL;
        char *useridName = NULL;
    
        key = strtok(text, "=");//first key
        while ( key) {
            printf ( "\nkey %s\n", key);
            value = strtok(NULL, "&");//value between = and &
            if ( !strcmp ( key, "ssid")) {
                if ( value) {
                    ssidName = value;
                    printf ( "value %s\n", ssidName);
                }
            }
            if ( !strcmp ( key, "pwd")) {
                if ( value) {
                    pwdName = value;
                    printf ( "value %s\n", pwdName);
                }
            }
            if ( !strcmp ( key, "userId")) {
                if ( value) {
                    useridName = value;
                    printf ( "value %s\n", useridName);
                }
            }
            key = strtok(NULL, "=");//next key
        }
        return 0;
    }
    

    注意指针 *Name 指向某处 text . 如果 文本 则这些指针不再指向它们以前的值。在这种情况下,为指针分配内存并复制内容。