2012-07-07 28 views
14

¿Hay alguna manera de leer una cadena formateada como esta, por ejemplo :48754+7812=Abcs?¿La forma más fácil de leer datos formateados en C++?

Digamos que tengo tres Stringz X, Y y Z, y quiero

X = 48754 
Y = 7812 
Z = Abcs 

El tamaño de los dos números y la longitud de la cadena puede variar, así que no desee utilizar substring() o nada como eso.

¿Es posible dar un parámetro C++ como esto

":#####..+####..=SSS.." 

por lo que conoce directamente lo que está pasando?

Respuesta

11

Una posibilidad es boost::split(), que permite la especificación de múltiples delimitadores y no requiere conocimiento previo del tamaño de la entrada:

#include <iostream> 
#include <vector> 
#include <string> 

#include <boost/algorithm/string.hpp> 
#include <boost/algorithm/string/split.hpp> 

int main() 
{ 
    std::vector<std::string> tokens; 
    std::string s(":48754+7812=Abcs"); 
    boost::split(tokens, s, boost::is_any_of(":+=")); 

    // "48754" == tokens[0] 
    // "7812" == tokens[1] 
    // "Abcs" == tokens[2] 

    return 0; 
} 

O bien, con sscanf():

#include <iostream> 
#include <cstdio> 

int main() 
{ 
    const char* s = ":48754+7812=Abcs"; 
    int X, Y; 
    char Z[100]; 

    if (3 == std::sscanf(s, ":%d+%d=%99s", &X, &Y, Z)) 
    { 
     std::cout << "X=" << X << "\n"; 
     std::cout << "Y=" << Y << "\n"; 
     std::cout << "Z=" << Z << "\n"; 
    } 

    return 0; 
} 

Sin embargo, la limitación aquí es que la longitud máxima de la cadena (Z) debe decidirse antes de analizar la entrada.

+0

gracias por la respuesta, pero ¿hay algo más que aumentar o cualquier biblioteca externa ... se puede hacer en C++ estándar o al menos stl –

+0

@LoersAntario, respuesta actualizada. – hmjd

+0

¿Podrían los infractores explicar? – hmjd

2

por ejemplo.

#include <boost/regex.hpp> 
#include <iostream> 

int main() 
{ 
    boost::regex re("\":(\\d+)\\+(\\d+)=(.+)\""); 
    std::string example = "\":48754+7812=Abcs\""; 
    boost::smatch match; 
    if (boost::regex_match(example, match, re)) 
    { 
     std::cout << "f number: " << match[1] << " s number: " << match[2] << " string: " << match[3] 
     << std::endl; 
    } 
    else 
    { 
     std::cout << "not match" << std::endl; 
    } 
} 

y segunda variante, funcionan solo con cuerda.

#include <string> 
#include <iostream> 

int main() 
{ 
    std::string s = "\":48754+7812=Abcs\""; 
    std::string::size_type idx = s.find(":"); 
    std::string::size_type end_first = s.find("+", idx + 1); 
    std::string f_number = s.substr(idx + 1, end_first - (idx + 1)); 
    std::cout << f_number << std::endl; 
    std::string::size_type end_second = s.find("=", end_first + 1); 
    std::string s_number = s.substr(end_first + 1, end_second - (end_first + 1)); 
    std::cout << s_number << std::endl; 
    std::string::size_type string_end = s.find("\"", end_second); 
    std::string str = s.substr(end_second + 1, string_end - (end_second + 1)); 
    std::cout << str << std::endl; 
} 
+0

+1 para sugerir expresiones regulares –

+1

Las expresiones regulares son una buena sugerencia en muchos casos, +1 para eso. Sin embargo, tenga en cuenta que la compatibilidad con expresiones regulares está disponible como parte de C++ en C++ 11; no es necesario usar Boost regex. – jogojapan

+1

@jogojapan not now = (http://liveworkspace.org/code/b66dcfa19ce7620fb7b9e4c203c42f43 – ForEveR

11
#include <iostream> 
#include <sstream> 

int main(int argc, char **argv) { 
    std::string str = ":12341+414112=absca"; 
    std::stringstream ss(str); 
    int v1, v2; 
    char col, op, eq; 
    std::string var; 
    ss >> col >> v1 >> op >> v2 >> eq >> var; 
    std::cout << v1 << " " << v2 << " " << var << std::endl; 
    return 0; 
} 
+2

+1 porque esta es la única respuesta que tiene en cuenta la pregunta real. Las otras respuestas no, porque ** 1 .utilizar boost no es la forma más simple ** (admito que podría ser la forma más elástica) y ** 2. scanf no es el estilo C++ ** (como lo menciona el autor de la respuesta correspondiente). – ChristophK

3

Puede utilizar scanf. No es excesivamente C++ - ish, pero hace el truco con muy pocas líneas de código:

char a[101], b[111], c[121]; 
sscanf(":48754+7812=Abcs", ":%100[^+]+%110[^=]=%120s", a, b, c); 
string sa(a), sb(b), sc(c); 
cout << sa << "-" << sb << "-" << sc << endl; 

La idea es especificar los caracteres aceptados por las cadenas que se leen utilizando una sintaxis de expresiones regulares muy limitado. En este caso, la primera cadena se lee hasta el más, y la segunda cadena se lee hasta el signo de igual.

Cuestiones relacionadas