C strtok()無法擷取連續兩個分隔符之間的空字串, 解決方法

C   strtok()無法擷取連續兩個分隔符之間的空字串, 解決方法

前言

  • 問題描述:
    與前臺約定按順序解析對應資訊, 如果中間出現空資料(或者出現連續兩個分隔符), strtok就會出問題.

看下面這個例子:

  1 #include <string.h>
2 #include <stdio.h>
3 
4 int main()
5 {
6     char str[] = "abc||de|fghi";
7 
8     char* p = strtok(str, "|");
9     for(int i = 0; p != NULL;   i)
10     {
11         printf("substr[%d]:%s\n", i, p);
12         p = strtok(NULL, "|");
13     }
14 
15     return 0;
16 }

源字串為:”abc||de|fghi”
分隔符為: ‘|’
執行結果為:
這裡寫圖片描述

中間abc與de之間的連續兩個’|’, strtok在分隔的時候, 直接把空字串跳過了,
而有的時候, 即使分隔符間是空字串, 我們也是需要獲取的;
那麼此時strtok就無法滿足需要了, 下面是我用c 實現的, 可以擷取空串的方法.

方法介紹

#include <stdio.h>
#include <string>
#include <vector>
/*
名稱:my_split(const std::string& src, const char& delim,
std::vector<std::string>& vec)
功能:用分隔符將源字串分隔為多個子串並傳出;
引數:
src-傳入引數, 源字串;
delim-傳入引數, 分隔符;
vec-傳出引數, 子串的集合;
返回值:
0-成功;
其它-失敗;
*/
int my_split(const std::string& src, const char& delim,
std::vector<std::string>& vec)
{
int src_len = src.length();
int find_cursor, read_cursor = 0;
vec.clear();
while(read_cursor < src_len){
find_cursor = src.find(delim, find_cursor);
//1.找不到分隔符
if(-1 == find_cursor){
if(read_cursor <= 0) return -1;
//最後一個子串, src結尾沒有分隔符
if(read_cursor < src_len){
vec.push_back(src.substr(read_cursor, src_len - read_cursor));
return 0;
}
}
//2.有連續分隔符的情況
else if(find_cursor == read_cursor){
//字串首位(read_cursor=0)遇到分隔符不處理
if(read_cursor != 0) 
vec.push_back(std::string(""));
}
//3.找到分隔符
else 
vec.push_back(src.substr(read_cursor, find_cursor - read_cursor));
read_cursor =   find_cursor;
if(read_cursor == src_len) return 0;
}//end while()
return 0;
}

呼叫

int main()
{
std::string src = "|abc||de|fghi|"; 
char delim = '|';
std::vector<std::string> vec;
int iRet = my_split(src, delim, vec);
if(0 != iRet){
printf("split fail!\n");
return -1;
}
printf("src:%s\n", src.c_str());
int index = 0;
for(auto it : vec)//c  11
printf("vec[%d]:%s\n", index  , it.c_str());
return 0;
}

執行結果:
這裡寫圖片描述

可以看到, 中間abc和db之間的空字串, 也能通過分隔符擷取出來了.

結語

上述方法比strtok有以下優點:

  • 沒有用到static變數, 故執行緒安全;
  • 傳入源字串為const引用, 不會改變源字串;
  • 可以擷取到連續分隔符間的空串;
  • 如果首次未找到分隔符將會返回失敗, 而strtok會返回源字串

如有不足, 望不吝賜教, 感謝收看!