Разбор (разделение) строки в C++ с помощью разделителя строк (стандартный C++) [дубликат]
этот вопрос уже есть ответ здесь:
я разбираю строку в C++, используя следующее:
string parsed,input="text to be parsed";
stringstream input_stringstream(input);
if(getline(input_stringstream,parsed,' '))
{
// do some processing.
}
разбор с одним разделителем символов в порядке. Но что делать, если я хочу использовать строку в качестве ограничитель данных.
пример: я хочу разделить:
scott>=tiger
С > = как разделитель, так что я могу получить Скотт и Тигр.
11 ответов:
можно использовать
std::string::find()функция, чтобы найти позицию вашего разделителя строк, а затем использоватьstd::string::substr()чтобы получить маркер.пример:
std::string s = "scott>=tiger"; std::string delimiter = ">="; std::string token = s.substr(0, s.find(delimiter)); // token is "scott"
The
find(const string& str, size_t pos = 0)функция возвращает позицию первого вхожденияstrв строке, илиnposесли строка не найдена.The
substr(size_t pos = 0, size_t n = npos)функция возвращает подстроку объекта, начиная с позицияposи длинойnpos.
если у вас есть несколько разделителей, после извлечения одного токена вы можете удалить его (включая разделитель), чтобы продолжить последующие извлечения (если вы хотите сохранить исходную строку, просто используйте
s = s.substr(pos + delimiter.length());):s.erase(0, s.find(delimiter) + delimiter.length());таким образом, вы можете легко цикл, чтобы получить каждый маркер.
Пример
std::string s = "scott>=tiger>=mushroom"; std::string delimiter = ">="; size_t pos = 0; std::string token; while ((pos = s.find(delimiter)) != std::string::npos) { token = s.substr(0, pos); std::cout << token << std::endl; s.erase(0, pos + delimiter.length()); } std::cout << s << std::endl;выход:
scott tiger mushroom
этот метод использует
std::string::findбез изменения исходной строки путем запоминания начала и конца предыдущего маркера подстроки.#include <iostream> #include <string> int main() { std::string s = "scott>=tiger"; std::string delim = ">="; auto start = 0U; auto end = s.find(delim); while (end != std::string::npos) { std::cout << s.substr(start, end - start) << std::endl; start = end + delim.length(); end = s.find(delim, start); } std::cout << s.substr(start, end); }
вы можете использовать следующую функцию, чтобы разделить строку:
vector<string> split(const string& str, const string& delim) { vector<string> tokens; size_t prev = 0, pos = 0; do { pos = str.find(delim, prev); if (pos == string::npos) pos = str.length(); string token = str.substr(prev, pos-prev); if (!token.empty()) tokens.push_back(token); prev = pos + delim.length(); } while (pos < str.length() && prev < str.length()); return tokens; }
функции strtok позволяет передавать несколько символов в качестве разделителей. Бьюсь об заклад, если вы передали в ">=" ваш пример строка будет разделена правильно (хотя > и = считаются отдельными разделителями).
редактировать, если вы не хотите использовать
c_str()для преобразования из String в char*, вы можете использовать substr и find_first_of для маркировки.string token, mystring("scott>=tiger"); while(token != mystring){ token = mystring.substr(0,mystring.find_first_of(">=")); mystring = mystring.substr(mystring.find_first_of(">=") + 1); printf("%s ",token.c_str()); }
этот код разбивает строки из текста и добавляет все в вектор.
vector<string> split(char *phrase, string delimiter){ vector<string> list; string s = string(phrase); size_t pos = 0; string token; while ((pos = s.find(delimiter)) != string::npos) { token = s.substr(0, pos); list.push_back(token); s.erase(0, pos + delimiter.length()); } return list; }называют:
vector<string> listFilesMax = split(buffer, "\n");
Я хотел бы использовать
boost::tokenizer. Вот документация, объясняющая, как сделать соответствующую функцию токенизатора:http://www.boost.org/doc/libs/1_52_0/libs/tokenizer/tokenizerfunction.htmвот тот, который работает для вашего случая.
struct my_tokenizer_func { template<typename It> bool operator()(It& next, It end, std::string & tok) { if (next == end) return false; char const * del = ">="; auto pos = std::search(next, end, del, del + 2); tok.assign(next, pos); next = pos; if (next != end) std::advance(next, 2); return true; } void reset() {} }; int main() { std::string to_be_parsed = "1) one>=2) two>=3) three>=4) four"; for (auto i : boost::tokenizer<my_tokenizer_func>(to_be_parsed)) std::cout << i << '\n'; }
вот мой взгляд на это. Он обрабатывает граничные случаи и принимает необязательный параметр для удаления пустых записей из результатов.
bool endsWith(const std::string& s, const std::string& suffix) { return s.size() >= suffix.size() && s.substr(s.size() - suffix.size()) == suffix; } std::vector<std::string> split(const std::string& s, const std::string& delimiter, const bool& removeEmptyEntries = false) { std::vector<std::string> tokens; for (size_t start = 0, end; start < s.length(); start = end + delimiter.length()) { size_t position = s.find(delimiter, start); end = position != string::npos ? position : s.length(); std::string token = s.substr(start, end - start); if (!removeEmptyEntries || !token.empty()) { tokens.push_back(token); } } if (!removeEmptyEntries && (s.empty() || endsWith(s, delimiter))) { tokens.push_back(""); } return tokens; }примеры
split("a-b-c", "-"); // [3]("a","b","c") split("a--c", "-"); // [3]("a","","c") split("-b-", "-"); // [3]("","b","") split("--c--", "-"); // [5]("","","c","","") split("--c--", "-", true); // [1]("c") split("a", "-"); // [1]("a") split("", "-"); // [1]("") split("", "-", true); // [0]()
строка разделитель
Разделить строку на основе строки-разделителя. Например, разбиение строки"adsf-+qwret-+nvfkbdsj-+orthdfjgh-+dfjrleih"на основе строки разделителя"-+"на выходе будет{"adsf", "qwret", "nvfkbdsj", "orthdfjgh", "dfjrleih"}#include <iostream> #include <sstream> #include <vector> using namespace std; // for string delimiter vector<string> split(string s, string delimiter) { size_t pos_start = 0, pos_end, delim_len = delimiter.length(); string token; vector<string> res; while ((pos_end = s.find(delimiter, pos_start)) != string::npos) { token = s.substr(pos_start, pos_end - pos_start); pos_start = pos_end + delim_len; res.push_back(token); } res.push_back(s.substr(pos_start)); return res; } int main() { string str = "adsf-+qwret-+nvfkbdsj-+orthdfjgh-+dfjrleih"; string delimiter = "-+"; vector<string> v = split(str, delimiter); for (auto i : v) cout << i << endl; return 0; }
для одного символа-разделителя#include <iostream> #include <sstream> #include <vector> using namespace std; vector<string> split(const string &s, char delim) { vector<string> result; stringstream ss(s); string item; while (getline(ss, item, delim)) { result.push_back(item); } return result; } int main() { string str = "adsf+qwer+poui+fdgh"; vector<string> v = split(str, '+'); for (auto i : v) cout << i << endl; return 0; }
Если вы не хотите изменять строку (как в ответе Винченцо Pii)и хотите вывести последний токен, а также, вы можете использовать этот подход:
inline std::vector<std::string> splitString( const std::string &s, const std::string &delimiter ){ std::vector<std::string> ret; size_t start = 0; size_t end = 0; size_t len = 0; std::string token; do{ end = s.find(delimiter,start); len = end - start; token = s.substr(start, len); ret.emplace_back( token ); start += len + delimiter.length(); std::cout << token << std::endl; }while ( end != std::string::npos ); return ret; }
#include<iostream> #include<algorithm> using namespace std; int split_count(string str,char delimit){ return count(str.begin(),str.end(),delimit); } void split(string str,char delimit,string res[]){ int a=0,i=0; while(a<str.size()){ res[i]=str.substr(a,str.find(delimit)); a+=res[i].size()+1; i++; } } int main(){ string a="abc.xyz.mno.def"; int x=split_count(a,'.')+1; string res[x]; split(a,'.',res); for(int i=0;i<x;i++) cout<<res[i]<<endl; return 0; }P. S: работает только в том случае, если длины строк после разбиения равны
std::vector<std::string> split(const std::string& s, char c) { std::vector<std::string> v; unsigned int ii = 0; unsigned int j = s.find(c); while (j < s.length()) { v.push_back(s.substr(i, j - i)); i = ++j; j = s.find(c, j); if (j >= s.length()) { v.push_back(s.substr(i, s,length())); break; } } return v; }
Comments