的strtok()和strtok_r()是可怕的功能:
- 他們修改輸入字符串
- 他們將連續分隔符爲一體,它可以跳過空白時,可以預期的,但它是解析.CSV(或製表符分隔)輸入時不打算。
最好是完全避免strtok()和strtok_r(),並使用strspn()和strcspn()。下面的函數做到這一點。返回值與snprintf()類似:找到的標記中的字符數(不包括終止NUL字節)
- 如果沒有標記#n:將'\ 0'寫入緩衝區和0返回
- 如果緩衝區對於找到的標記加上終止的NUL字節太小,'\ 0'被寫入緩衝區並且令牌長度返回
- 是緩衝區足夠大,將令牌+'\ 0'寫入它,並返回strlen(令牌)。
#include <stdio.h>
#include <string.h>
size_t extract_nth_token_ohne_strtok_r(char *res, size_t maxlen, const char *str, const char *delim, int n)
{
size_t pos, len;
int itok;
for (itok=0,pos=0; str[pos];) {
len = strcspn(str+pos, delim);
if (itok++ == n) {
if (len < maxlen) memcpy(res, str+pos, len), res[len] = 0;
else res[0] = 0;
return len;
}
pos += len;
if (str[pos]) pos++;
}
res[0] = 0;
return 0;
}
int main(void)
{
char * omg = "zero one\ttwo \tfour\nfive" ;
char token[80];
size_t toklen;
int ii;
printf("\n## With a large enough buffer:\n");
for (ii=0; ii < 7; ii++) {
toklen = extract_nth_token_ohne_strtok_r(token, sizeof token
, omg, " \t\n", ii);
printf("%d: res=%zu \"%s\"\n" , ii, toklen, token);
}
printf("\n## With 4-character buffer:\n");
for (ii=0; ii < 7; ii++) {
toklen = extract_nth_token_ohne_strtok_r(token, 4
, omg, " \t\n", ii);
printf("%d: res=%zu \"%s\"\n" , ii, toklen, token);
}
return 0;
}
注意:如果你做想將連續whitspace爲一體,你可以更換if (str[pos]) pos++;
通過:
pos += strspn(str+pos, delim);
'的問題是,saveptr值沒有記錄。「你在尋找什麼樣的」價值「? –
製作一個字符串的副本並使用它。 – Barmar
@SouravGhosh告訴我它的值是否是最後一個標記 – basin