2012-07-07 26 views
14

Czy istnieje sposób, aby odczytać sformatowany ciąg taki jak ten, na przykład :48754+7812=Abcs.Najprostszy sposób na odczyt sformatowanego wejścia w C++?

Powiedzmy mam trzy Stringz X, Y i Z, a chcę

X = 48754 
Y = 7812 
Z = Abcs 

wielkości dwóch liczb i długości łańcucha mogą się różnić, więc nie chcę używać substring() ani nic tak.

Czy to możliwe, aby dać C++ parametr jak ten

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

więc bezpośrednio wie, co się dzieje?

Odpowiedz

11

Możliwość jest boost::split(), co umożliwia określenie wielokrotnych ograniczników i nie wymaga uprzedniej znajomości wielkości wejściowych:

#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; 
} 

Lub przy 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; 
} 

Jednak Ograniczeniem jest tutaj to, że maksymalna długość ciągu (Z) musi zostać ustalona przed analizą danych wejściowych.

+0

za dużo za odpowiedź, ale czy jest coś innego niż doładowanie lub jakiekolwiek biblioteki zewnętrzne .. jest to możliwe do zrobienia w standardowym C++ lub przynajmniej stl –

+0

@LoersAntario, zaktualizowana odpowiedź. – hmjd

+0

Czy mógłbyś to wyjaśnić? – hmjd

2

na przykład.

#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; 
    } 
} 

i drugi wariant, działają tylko z ciągiem.

#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 za sugerowanie wyrażeń regularnych –

+1

Wyrażenia regularne są dobrą propozycją w wielu takich przypadkach, +1 za to. Zwróć uwagę, że obsługa wyrażeń regularnych jest dostępna jako część C++ w C++ 11 - nie ma już potrzeby korzystania z Boostu 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, ponieważ jest to jedyna odpowiedź, która dokładnie uwzględnia faktyczne pytanie, inne odpowiedzi nie, ponieważ ** 1 używanie boost nie jest najprostszym sposobem ** (przyznaję, że może być najbardziej elitarnym sposobem) i ** 2. scanf nie jest w stylu C++ ** (jak wspomniano przez autora odpowiedniej odpowiedzi). – ChristophK

3

Można użyć scanf. To nie jest zbyt C++ - owski, ale załatwia sprawę z niezwykle kilku linii kodu:

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; 

Chodzi o to, aby określić znaków akceptowanych przez struny lekturę przy użyciu bardzo ograniczonej składni wyrażeń regularnych. W tym przypadku pierwszy łańcuch jest odczytywany do plusa, a drugi łańcuch jest odczytywany do znaku równości.