2015-07-13 51 views
-2

我有的看起来像这样的数据:拆分字符数组为单独的字符串

header:dataA:dataB 

我试图让头和数据A和数据B作为单独的字符串。 所以我写了这个功能,这可能并不好:

void newDataFromBLE(char header[],char dataA[], char dataB[]) 
{ 
    Serial.println("got:"); 
    Serial.println(header); 
    Serial.println(dataA); 
    Serial.println(dataB); 
    if (strcmp (header,"setWifi") == 0) 
     //... do stuff here 

我来到这里:

#define maxDataSize 50 
//..... 

char header[20]; 
char dataA[maxDataSize]; 
char dataB[maxDataSize]; 

//**** a call to the function that parse the data 
getHeader(BLEcontent,1,header); // here "BLEcontent" has the incoming data 
getHeader(BLEcontent,2,dataA); 
getHeader(BLEcontent,3,dataB); 

//***** call the function that use the data 
newDataFromBLE(header,dataA, dataB); 

//function that parses the data: 
void getHeader(char localString[], int seperatorNum,char *newdata) 
{ 
    const char seperator=':'; 
    int counter=0; 
    int divider=0; 

    //clear array when it has garbage it added 
    for(int i = 0; i < maxDataSize; ++i) 
     newdata[i] = (char)0; 

    for(int k=0;k<maxDataSize;k++) 
    { 
     if (localString[k]== seperator ) 
     { 
      counter++; 
      divider=k+1; 
      if(counter==seperatorNum) 
      { return ;  } 
     } 
     if((seperatorNum-1) ==counter) 
      newdata[k-divider]=localString[k]; 
    } 
    return ; 
} 

当我试图使用功能数据,存储在头/数据A /数据B之后一些非常奇怪的结果。例如,如果传入数据是setWifi:a,我会得到一个好结果。如果是abcd:abc我得到垃圾。如果是setWifi:a:b,我也会得到垃圾。

看来,如果我发送的是不对应于第一个if声明,它会给我垃圾,即使它在if之前。看来,它知道(??)即将到来的if ..

它使用前的工作..

+2

您可以用['strtok'](http://stackoverflow.com/questions/3889992/how-does-strtok-split-the-string-into-tokens -in-C)? – Evert

+0

我在你的'Serial.println'线组合C-标签混淆。如果有一些全球性结构'Serial'蒙山一个函数指针'println()一样' – Evert

+0

这将是唯一有效的C。但是,是的,我的想法 - 不要推倒重来,使用'的strtok()',可选输入字符串的副本。 –

回答

1

您可以使用strsep。该man page

strsep()功能被引入作为strtok(3)的替代品,因为后者无法处理空字段。它是线程安全的。

使用strsep

#include <string.h> 
#include <stddef.h> 

. . . 

const char string[] = "header:dataA:dataB"; 
const char delimiters[] = ":"; 
char * running = strdupa(string); 
char * token; 

. . . 

token = strsep(&running, delimiters); /* token => "header" */ 
token = strsep(&running, delimiters); /* token => "dataA" */ 
token = strsep(&running, delimiters); /* token => "dataB" */ 
token = strsep(&running, delimiters); /* token => NULL */ 
+0

http://www.gnu.org/software/libc/manual/html_node/Finding-Tokens-in-a-String.html strsep和strtok_r之间的一个区别是,如果输入字符串包含多个来自分隔符的字符行strsep从分隔符中为每对字符返回一个空字符串。这意味着程序通常应该在处理之前测试返回空字符串的strsep。 – Zelldon

+0

@Zelldon对,这需要检查非空的'token'。 – Shreevardhan

3

要分割你的数据,你可以使用char* strtok(char* str, const char* delim);功能。 对于线程的Safty使用char *strtok_r(char *str, const char *delim, char **saveptr);功能。

参见下面的实施例,它使用strtok_r功能:

#include <stdio.h> 
#include <string.h> 

//#define maxsize 20 
int main() 
{ 
    int i = 0; 
    char str[] ="setWifi:dataA:dataB"; 
    char *delimeter = ":"; 
    char *saveptr1; 
    char *header = strtok_r(str, delimeter, &saveptr1); 
    char **dataArr = malloc(5); 

    for (i=0; i< 5; i++) { 
    dataArr[i] = strtok_r(NULL, delimeter, &saveptr1); 
    if (dataArr[i] == NULL) 
     break; 
    printf(" %s\n", dataArr[i]); 
    } 


    if (strcmp(header, "setWifi") == 0) { 
    printf("'setWifi' header was set!"); 
    } 
    free(dataArr); 

    return 0; 
} 

工作实施例: http://ideone.com/renn2q

输出:

dataA 
dataB 
'setWifi' header was set! 

的strtok_r()函数是一个可重入版本strtok()函数。所述saveptr 参数是一个指向到被以维持该 解析相同的字符串的连续调用之间的上下文内部使用 strtok_r()一个char *变量。

参见:http://linux.die.net/man/3/strtok_r

+2

我无法使用它。那是因为strtok有记忆,而我正在用线程在这里工作,我宁愿不会进入这个。 – Curnelious

+0

@Curnelious:我不明白你想说什么? – ckruczek

+2

strtok有记忆。如果你在你的软件中使用线程,你可能会陷入复杂的情况,在内存中存在某些内容,而不是你想用另一个字符串来使用它。 – Curnelious