resueltos - Analizar(dividir) una cadena en C++ usando un delimitador de cadena(C++ estándar)
leer cadena de caracteres en c (11)
Para delimitador de cuerdas
Cadena dividida basada en un delimitador de cadena . Como dividir la cadena "adsf-+qwret-+nvfkbdsj-+orthdfjgh-+dfjrleih" basado en delimitador de cadena "-+" , la salida será {"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;
}
Salida
adsf qwret nvfkbdsj orthdfjgh dfjrleih
Para delimitador de un solo carácter.
Cadena dividida basada en un delimitador de caracteres. Como dividir la cadena "adsf+qwer+poui+fdgh" con el delimitador "+" dará como resultado {"adsf", "qwer", "poui", "fdg"h}
#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;
}
Salida
adsf qwer poui fdgh
Esta pregunta ya tiene una respuesta aquí:
- ¿Cómo itero sobre las palabras de una cadena? 74 respuestas
Estoy analizando una cadena en C ++ usando lo siguiente:
string parsed,input="text to be parsed";
stringstream input_stringstream(input);
if(getline(input_stringstream,parsed,'' ''))
{
// do some processing.
}
El análisis con un solo delimitador de caracteres está bien. Pero qué pasa si quiero usar una cadena como delimitador.
Ejemplo: quiero dividir:
scott>=tiger
con> = como delimitador para que pueda obtener scott y tiger.
Aquí está mi opinión sobre esto. Maneja los casos de borde y toma un parámetro opcional para eliminar entradas vacías de los resultados.
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;
}
Ejemplos
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]()
Este código divide líneas del texto y agrega a todos a un vector.
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());
}
list.push_back(s);
return list;
}
Llamado por:
vector<string> listFilesMax = split(buffer, "/n");
Este método utiliza std::string::find sin mutar la cadena original al recordar el principio y el final del token de subcadena anterior.
#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);
}
Puede usar la función std::string::find() para encontrar la posición de su delimitador de cadena, luego use std::string::substr() para obtener un token.
Ejemplo:
std::string s = "scott>=tiger";
std::string delimiter = ">=";
std::string token = s.substr(0, s.find(delimiter)); // token is "scott"
La función
find(const string& str, size_t pos = 0)devuelve la posición de la primera aparición destren la cadena, onpossi no se encuentra la cadena.La función
substr(size_t pos = 0, size_t n = npos)devuelve una subcadena del objeto, comenzando en la posiciónposy de la longitudnpos.
Si tiene varios delimitadores, después de haber extraído un token, puede eliminarlo (incluido el delimitador) para continuar con las extracciones posteriores (si desea conservar la cadena original, solo use s = s.substr(pos + delimiter.length()); ):
s.erase(0, s.find(delimiter) + delimiter.length());
De esta manera puede hacer un bucle fácilmente para obtener cada token.
Ejemplo completo
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;
Salida:
scott
tiger
mushroom
Puedes usar la siguiente función para dividir la cadena:
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;
}
Si no desea modificar la cadena (como en la respuesta de Vincenzo Pii) y desea enviar también el último token, puede usar este método:
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;
}
Yo usaría boost::tokenizer . Aquí hay documentación que explica cómo realizar una función de tokenizer adecuada: http://www.boost.org/doc/libs/1_52_0/libs/tokenizer/tokenizerfunction.htm
Aquí hay uno que funciona para su caso.
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'';
}
strtok te permite pasar múltiples caracteres como delimitadores. Apuesto a que si pasaste "> =" tu cadena de ejemplo se dividiría correctamente (aunque> y = se cuentan como delimitadores individuales).
EDITAR si no desea usar c_str() para convertir de cadena a char *, puede usar substr y find_first_of para tokenizar.
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());
}
#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;
}
PS: funciona solo si las longitudes de las cadenas después de la división son iguales
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;
}