c语言字符串定界符,关于c ++:按字符分割字符串
我知道這是一個(gè)非常簡單的問題,但我只想一次為自己解決
我只想使用字符作為分割定界符將字符串分割成數(shù)組。 (很像C#著名的.Split()函數(shù)。我當(dāng)然可以應(yīng)用蠻力方法,但是我想知道是否有什么更好的方法了。)
到目前為止,我已經(jīng)搜索過,也許最接近的解決方案是使用strtok(),但是由于不方便(將字符串轉(zhuǎn)換為char數(shù)組等),我不喜歡使用它。有沒有更簡單的方法來實(shí)現(xiàn)這一目標(biāo)?
注意:我想強(qiáng)調(diào)這一點(diǎn),因?yàn)槿藗兛赡軙?#xff1a;"蠻力為什么不起作用"。我的暴力解決方案是創(chuàng)建一個(gè)循環(huán),并在其中使用substr()函數(shù)。但是,由于它需要起點(diǎn)和長度,因此在我想分割日期時(shí)會失敗。因?yàn)橛脩艨赡茌斎氲臅r(shí)間是2012年7月12日或2011年7月3日,所以在計(jì)算" /"定界符的下一個(gè)位置之前,我可以真正說出長度。
拆分字符串C ++的可能重復(fù)項(xiàng)
使用向量,字符串和stringstream。有點(diǎn)麻煩,但可以解決問題。
std::stringstream test("this_is_a_test_string");
std::string segment;
std::vector<:string> seglist;
while(std::getline(test, segment, '_'))
{
seglist.push_back(segment);
}
導(dǎo)致向量的內(nèi)容與
std::vector<:string> seglist{"this","is","a","test","string" };
實(shí)際上,這種方法正是我所尋找的。很容易理解,不使用外部庫,只是非常簡單。謝謝@thelazydeveloper!
如果要提高性能,可以添加seglist.reserve(std::count_if(str.begin(), str.end(), [&](char c) { return c == splitChar; }) + (str.empty() ? 1 : 0));如果要拆分的原始字符串存儲在str中。
喜歡RegEx的人的另一種方式(C ++ 11 / boost)。就我個(gè)人而言,我非常喜歡RegEx這類數(shù)據(jù)。 IMO比使用分隔符簡單地分割字符串要強(qiáng)大得多,因?yàn)槟梢愿鶕?jù)需要選擇對構(gòu)成"有效"數(shù)據(jù)的內(nèi)容更加了解。
#include
#include ? ? // copy
#include ? ? // back_inserter
#include ? ? ? ?// regex, sregex_token_iterator
#include
int main()
{
std::string str ="08/04/2012";
std::vector<:string> tokens;
std::regex re("\\d+");
//start/end points of tokens in str
std::sregex_token_iterator
begin(str.begin(), str.end(), re),
end;
std::copy(begin, end, std::back_inserter(tokens));
}
因此,您可以在代碼中包括整個(gè)正則表達(dá)式匹配器,僅用于拆分字符串。傷心...
@Dev否,包括一個(gè)正則表達(dá)式匹配器,以便對構(gòu)成有效數(shù)據(jù)的內(nèi)容更加智能-例如選擇數(shù)字,并允許使用其他分隔符,例如點(diǎn)或連字符
就二進(jìn)制大小和整體效率而言,這都是不好的,但是由于這兩個(gè)原因都不涉及這種情況,因此我不再繼續(xù)。
@Dev如果一個(gè)人對二進(jìn)制大小有如此極端的約束,那么他們甚至應(yīng)該重新考慮使用C ++,或者至少使用它的標(biāo)準(zhǔn)庫(例如string / vector / etc),因?yàn)樗鼈兌紩a(chǎn)生類似的效果。關(guān)于效率,最好的建議來自Donald Knuth-"過早的優(yōu)化是萬惡之源";換句話說,在進(jìn)行優(yōu)化之前,首要任務(wù)是確定是否存在問題,然后通過諸如剖析之類的客觀手段來確定原因,而不是浪費(fèi)時(shí)間試圖尋找每一個(gè)可能的微觀優(yōu)化。
"在這種情況下,兩個(gè)人都不關(guān)心"-我自己。
@Dev然后我想知道什至提起它們的目的是什么。
我只是不想將整個(gè)正則表達(dá)式引擎用于查找整數(shù)。但是,如果您不想專門化代碼,這很好。
Boost具有您要在algorithm/string.hpp中查找的split():
std::string sample ="07/3/2011";
std::vector strs;
boost::split(strs, sample, boost::is_any_of("/"));
另一種可能性是使流具有使用特殊ctype構(gòu)面的語言環(huán)境。流使用ctype構(gòu)面確定什么是"空白",將其視為分隔符。使用將分隔符分類為空格的ctype構(gòu)面,讀取結(jié)果可能非常簡單。這是實(shí)現(xiàn)方面的一種方法:
struct field_reader: std::ctype {
field_reader(): std::ctype(get_table()) {}
static std::ctype_base::mask const* get_table() {
static std::vector<:ctype_base::mask>
rc(table_size, std::ctype_base::mask());
// we'll assume dates are either a/b/c or a-b-c:
rc['/'] = std::ctype_base::space;
rc['-'] = std::ctype_base::space;
return &rc[0];
}
};
我們通過使用imbue告訴流使用包含它的語言環(huán)境,然后從該流中讀取數(shù)據(jù)來使用它:
std::istringstream in("07/3/2011");
in.imbue(std::locale(std::locale(), new field_reader);
設(shè)置好后,拆分幾乎變得微不足道-只需使用幾個(gè)istream_iterator初始化向量以從字符串(嵌入在istringstream中)讀取片段即可:
std::vector<:string>((std::istream_iterator<:string>(in),
std::istream_iterator<:string>());
顯然,如果只在一個(gè)地方使用它,則可能會導(dǎo)致過度殺傷。但是,如果您使用過多,則在保持其余代碼的整潔度方面可能要走很長的路要走。
我天生不喜歡stringstream,盡管我不確定為什么。今天,我編寫了此函數(shù),以允許將std::string通過任意字符或字符串拆分為向量。我知道這個(gè)問題很舊,但是我想分享一種拆分std::string的替代方法。
盡管可以很容易地修改它以包括它們,但是該代碼完全省略了從結(jié)果中分割出的字符串部分。
#include
#include
void split(std::string str, std::string splitBy, std::vector<:string>& tokens)
{
/* Store the original string in the array, so we can loop the rest
* of the algorithm. */
tokens.push_back(str);
// Store the split index in a 'size_t' (unsigned integer) type.
size_t splitAt;
// Store the size of what we're splicing out.
size_t splitLen = splitBy.size();
// Create a string for temporarily storing the fragment we're processing.
std::string frag;
// Loop infinitely - break is internal.
while(true)
{
/* Store the last string in the vector, which is the only logical
* candidate for processing. */
frag = tokens.back();
/* The index where the split is. */
splitAt = frag.find(splitBy);
// If we didn't find a new split point...
if(splitAt == string::npos)
{
// Break the loop and (implicitly) return.
break;
}
/* Put everything from the left side of the split where the string
* being processed used to be. */
tokens.back() = frag.substr(0, splitAt);
/* Push everything from the right side of the split to the next empty
* index in the vector. */
tokens.push_back(frag.substr(splitAt+splitLen, frag.size()-(splitAt+splitLen)));
}
}
要使用,只需像這樣致電...
std::string foo ="This is some string I want to split by spaces.";
std::vector<:string> results;
split(foo,"", results);
現(xiàn)在,您可以隨意訪問向量中的所有結(jié)果。就這么簡單-沒有stringstream,沒有第三方庫,沒有回到C!
您對為什么會更好會有任何爭議?
看看boost :: tokenizer
如果您想?yún)R總自己的方法,則可以使用std::string::find()確定拆分點(diǎn)。
感謝您的字符串查找提示。永遠(yuǎn)喜歡聽到std解決方案!
erase()函數(shù)呢?如果您知道要在字符串中拆分的位置,則可以使用erase()"提取"字符串中的字段。
std::string date("01/02/2019");
std::string day(date);
std::string month(date);
std::string year(date);
day.erase(2, string::npos); //"01"
month.erase(0, 3).erase(2); //"02"
year.erase(0,6); //"2019"
您是否有理由不想將string轉(zhuǎn)換為字符數(shù)組(char*)?調(diào)用.c_str()相當(dāng)容易。您還可以使用循環(huán)和.find()函數(shù)。
弦類
字符串.find()
字符串.c_str()
總結(jié)
以上是生活随笔為你收集整理的c语言字符串定界符,关于c ++:按字符分割字符串的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iterm php,iTerm2笔记
- 下一篇: php的web表单系统源码毕设_从业十多