2015-07-13 83 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