2016-03-30 49 views
0

我有一個文件,其中有一些由製表符分隔的字段。總是會有17級的標籤,但有順序可以不同,如..在C中分割字符串以識別連續製表符

75104\tDallas\t85\t34.46\t45.64 
75205\tHouston\t\t37.34\t87.32 
93434\t\t\t1.23\t3.32 

當我在下列方式使用strtok

while (fgets(buf, sizeof(buf), fp) != NULL) { 
    tok = strtok(buf,"\t"); 

    while(tok != NULL) { 
     printf("%s->",tok); 
     tok = strtok(NULL,"\t"); 
    } 
} 

我得到的所有令牌,但雙標籤\t\t以上被忽略。但是,我需要知道字段爲空時,我不能忽略多個選項卡,因爲結構取決於要計數的17個選項卡,如果字段爲空,則使用佔位符。

我試着處理這個問題有

if(tok == NULL || '') 

,但我不認爲strtok識別標籤後標籤。處理這個問題的最好方法是什麼?

+1

看着它 - 你的if(tok == NULL ||'')'嘗試看起來像你習慣於另一種語言。這在技術上是有效的,但幾乎肯定不是你想要做的。 – usr2564301

+0

strtok()無法使用。構建狀態機和/或使用strspn()/ strcspn()。 – joop

回答

2

你不能在你的情況下使用strtok。 從man strtok:

的的strtok()函數斷線成的零個或多個非空 令牌 ... 從以上描述的序列,它遵循的兩個或更多個連續 定界符字節序列在解析的字符串中被認爲是一個 單個分隔符,並且 字符串的開頭或末尾的分隔符字節被忽略。換句話說:strtok() 返回的令牌總是非空的字符串。因此,例如,給定字符串 「aaa ;; bbb」,連續調用strtok()以指定分隔符 字符串「;,」將返回字符串「aaa」和「bbb」,然後返回空值 指針

所以,你將不得不尋找替代方案,這可能是手動編寫使用線性搜索和strncpy,或sscanf或使用strsep,如果是能夠使用的功能。後者很可能是我的選擇,因爲它意在替代strtok。

man strsep:

的strsep()函數被引入作爲用於的strtok(3), 因爲後者不能處理空字段的替代品。但是,strtok(3)con 形式爲C89/C99,因此更便於攜帶。

+1

這裏有一個簡單的'strsep()'實現,如果它不是你工具鏈的一部分,你可以使用它:http://stackoverflow.com/a/8514474/12711 –

0

下面是使用strsep的解決方案,它是專門介紹了爲解決這一事實strtok跳過連續的分隔符:

char *cur, *nxt; 
while (fgets(buf, sizeof(buf), fp) != NULL) 
{ 
    nxt = buf; 
    while ((cur = strsep(&nxt, "\t")) != NULL) 
    { 
     printf("%s->",cur); 
    } 
} 

注:傳遞給strsep字符串必須是可寫(通過一個字符串明確不起作用)。它將被修改strsep(在連續調用時用NUL字符覆蓋分隔符)。

0

一個很好的方法來開始消化如何實現,下面的函數將做到這一點,請閱讀它。 :

int splitLine(char *buf, char **argv, int max_args) 
{ 
    int arg; 

    /* skip over initial spaces */ 
    while (isspace(*buf)) buf++; 

    for (arg = 0; arg < max_args 
     && *buf != '\0'; arg++) { 
     argv[arg] = buf; 
     /* skip past letters in word */ 
     while (*buf != '\0' 
      && !isspace(*buf)) { 
      buf++; 
     } 
     /* if not at line's end, mark 
     * word's end and continue */ 
     if (*buf != '\0') { 
      *buf = '\0'; 
      buf++; 
     } 
     /* skip over extra spaces */ 
     while (isspace(*buf)) buf++; 
    } 
    return arg; 
} 

該函數使用空格分隔符,可以重新實現使用其他任何一個。