有窮自動機實現拆分字符串爲vector

拆分字符串爲vector

字符串分割,在網上看到幾種方法https://www.jb51.net/article/55954.htm
1 使用strtok分割

//藉助strtok實現split
#include <string.h>
#include <stdio.h> 
int main()
{
char s[] = "Golden Global View,disk * desk";
const char* d = " ,*";
char* p;
p = strtok(s, d);
while (p)
{
printf("%s\n", p);
p = strtok(NULL, d);
}
return 0;
}

但是 strtok 在高版本的vs 中需要定義 _CRT_NON_CONFORMING_WCSTOK才能使用,而且在內部實現有
_SECURE_VERSION版本和非安全版本,非安全版本多線程同時訪問會可能會發生問題。
2 用STL進行字符串的分割

//字符串分割函數
std::vector<std::string> split(std::string str, std::string pattern)
{
	std::string::size_type pos;
	std::vector<std::string> result;
	str += pattern;//擴展字符串以方便操作
	int size = str.size();

	for (int i = 0; i < size; i++)
	{
		pos = str.find(pattern, i);
		if (pos < size)
		{
			std::string s = str.substr(i, pos - i);
			result.push_back(s);
			i = pos + pattern.size() - 1;
		}
	}
	return result;
}

這個例子沒有考慮多個拆分符的情況
3 使用boost 庫
這種情況不貼代碼了,就是庫的使用,boost太大,不喜歡

這裏再介紹一種方法
根據基本的有窮自動機
在這裏插入圖片描述

  • 我們實現對分隔符的處理
  • 0 是初始狀態
  • 1 的時候接收到一個普通字符
  • 2 是結束狀態
  • 處理分隔符在 狀態1->0跳轉的時候處理,保存字符串
  • 從0-2 從 1->2 是退出
  • 下面貼代碼
template<class T>
bool in_string(T c, const T* str)
{
	while (*str)
	{
		if (*str++ == c)
		{
			return true;
		}
	}
	return false;
}
void split_string(
	string& roldids,
	string& split_str,
	vector<string>& vec)
{
	int i = 0;
	int pos = -1;
	char c = 0;
	int stat = 0;
	while (true)
	{
		char c = roldids[i];
		switch (stat)
		{
		case 0:
		{
			if (!in_string(c, split_str.data()))
			{
				stat = 1;
				pos = i;
			}
			if (c == 0)
			{
				return;
			}

			break;
		}
		case 1:
			if (in_string(c, split_str.data()) || (c == 0 && pos != roldids.size() - 1))
			{
				string s;
				s.insert(s.begin(), roldids.begin() + pos, roldids.begin() + i);
				vec.push_back(s);
				stat = 0;
			}
			if (c == 0)
			{
				return;
			}
			break;
		}
		i++;
	}
}
  • 上面代碼就是拆分函數,輸出到vector中去
  • 下面是測試函數
int main()
{
	//測試用例
	//1 使用一種分割符 3 個測試用例
	//2 使用混合分隔符
	//3 分割符在最前
	//4 分割符在最後
	//5 分隔符湊在一起
	string s = "hello,welcome,to beijing,歡迎到中國來;啦啦啦";
	string split_str = ", ;";
	vector<string> vec;

	split_string(s, split_str, vec);

	s = ",; hello,welcome,to,beijing, ; ";

	vec.clear();

	split_string(s, split_str, vec);
	return 0;
}
  • 僅僅使用了有窮自動機畫了個簡單的圖就搞定了。如果使用正則表達式的庫或許威力更大,但是少了些樂趣。
  • 下面完整代碼
// 各種類型轉字符串.cpp : 此文件包含 "main" 函數。程序執行將在此處開始並結束。
//
#include <cstdint>
#include <iostream>
#include <string>
#include <list>
#include <string.h>
#include <iomanip>      // std::setw
#include <vector>
using namespace std;
std::string to_utf8(int32_t v)
{
	char b[8] = {};
	_itoa_s(v, b, 10);
	return b;
}
template<class T>
bool in_string(T c, const T* str)
{
	while (*str)
	{
		if (*str++ == c)
		{
			return true;
		}
	}
	return false;
}

void split_string(
	string& roldids,
	string& split_str,
	vector<string>& vec)
{
	int i = 0;
	int pos = -1;
	char c = 0;
	int stat = 0;
	while (true)
	{
		char c = roldids[i];
		switch (stat)
		{
		case 0:
		{
			if (!in_string(c, split_str.data()))
			{
				stat = 1;
				pos = i;
			}
			if (c == 0)
			{
				return;
			}

			break;
		}
		case 1:
			if (in_string(c, split_str.data()) || (c == 0 && pos != roldids.size() - 1))
			{
				string s;
				s.insert(s.begin(), roldids.begin() + pos, roldids.begin() + i);
				vec.push_back(s);
				stat = 0;
			}
			if (c == 0)
			{
				return;
			}
			break;
		}
		i++;
	}
}

int main()
{
	//測試用例
	//1 使用一種分割符 3 個測試用例
	//2 使用混合分隔符
	//3 分割符在最前
	//4 分割符在最後
	//5 分隔符湊在一起
	string s = "hello,welcome,to beijing,歡迎到中國來;啦啦啦";
	string split_str = ", ;";
	vector<string> vec;

	split_string(s, split_str, vec);

	s = ",; hello,welcome,to,beijing, ; ";

	vec.clear();

	split_string(s, split_str, vec);
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章