2010-02-02 8 views
14

C++ nie jest moim preferowanym językiem.Potrzebujesz podstawowej pomocy parsowania ciągu znaków w C++

Mam plik, który zawiera to:

e 225,370 35,75 

Chcę oddzielić e, 225, 370, 35 i 75 od siebie w char i int ale mam problemy. Próbowałem zrobić wszystko, co znalazłem online i w mojej książce C++ i nadal nie działa. Proszę pomóż.

Byłoby mi łatwiej robić to w Javie.

+0

Powiedz nam, co masz. – bmargulies

+0

Dzięki chłopaki. C++ jest dla mnie bardzo frustrujący, ponieważ najpierw uczyłem się języka Java. –

+2

Chociaż czasami może to być frustrujące, pomaga uzyskać kilka potężnych bibliotek, które nie zawsze są pakowane bezpośrednio tak jak w Javie. Wyobraź sobie, jak frustrująca byłaby Java, gdybyś miał tylko podstawowy język i brak bibliotek. – joshperry

Odpowiedz

-1
#include <iostream> 
#include <fstream> 

using namespace std; 

int main() 
{ 
     ifstream f("a.txt"); // check for errors. 

     char ch,dummy; 
     int i1,i2,i3,i4; 

     f>>ch>>i1>>dummy>>i2>>i3>>dummy>>i4; 

     cout<<ch<<endl<<i1<<endl<<i2<<endl<<i3<<endl<<i4<<endl; 

     return 0; 
} 
2

Zakładając, że czytałeś dane do strun ...

  1. strchr jest jak String.index.
  2. strtol jest jak Integer.parseInt()

Czego jeszcze trzeba?

+1

strtok byłby wygodniejszy niż strchr –

+0

'strtok' nie jest bezpieczny dla wątków, jeśli jest to problemem. – greyfade

2
#include <fstream> 

/* ... */ 

ifstream file; 
file.open("yourfile.txt"); 
char c, dummy; 
int i[4]; 
file >> c >> i[0] >> dummy >> i[1] >> i[2] >> dummy >> i[3]; 
file.close(); 
+0

Nie jestem pewien zachowania, ponieważ nie jestem programistą C++, ale byłbym zaskoczony, gdyby to po prostu zignorowało przecinki w pliku. Czy to? – danben

+0

@danben: może, ale domyślnie nie. Nawet najbardziej wyspecjalizowani programiści C++ nigdy nie dotykają części biblioteki koniecznej, aby zignorować przecinki (trzeba utworzyć niestandardowy "aspekt ctype", utworzyć "locale" zawierający ten "facet", a następnie "nasycić" strumień z że 'locale'). –

+0

@danden, masz rację. Zaktualizowałem moje rozwiązanie. –

4

Jeśli masz kontrolę nad tym formacie, to będzie (nieznacznie) łatwiejsze do odczytania, jeśli wyeliminować przecinki, i po prostu wejście jak

e 225 370 35 75

Przy użyciu tego formatu, kod Poita_ do odczytu danych będzie działał [edytuj: on jest od aktualizacji swojego kodu, aby wyraźnie przeczytać i pominąć przecinki]. W przeciwnym razie trzeba wyraźnie przeskoczyć nad przecinkami:

char ingore1, ignore2; 
char ch; 
int i[4]; 

file >> ch >> i[0] >> ignore1 >> i[1] >> i[2] >> ignore2 >> i[3]; 

[Edit: jeśli jesteś paranoikiem czy naprawdę trzeba zweryfikować swój wkład, w tym momencie można sprawdzić, że ignore1 i ignore2 zawierać przecinków.]

W większości przypadków, jednak dane te są prawdopodobnie związane, więc będziemy chcieli, aby przeczytać całą linię w jednej struktury (lub klasy):

struct data { 
    char ch; 
    int i[4]; 

    std::istream &operator>>(std::istream &is, data &d) { 
     char ignore1, ignore2; 
     return is >> ch >> i[0] >> ignore1 >> i[1] >> i[2] >> ignore2 >> i[3]; 
    } 
}; 

zrobiwszy tego, można przeczytać cały obiekt data na raz:

std::ifstream infile("my data file.txt"); 
data d; 

infile >> d; 

Albo, jeśli masz cały plik pełny z nich, można przeczytać je wszystkie do wektora:

std::vector<data> d; 

std::copy(std::istream_iterator<data>(infile), 
    std::istream_iterator<data>(), 
    std::back_inserter(d)); 
+0

Niezły. Zwykle używam metod find i substr. – StackedCrooked

3

Jeśli chcesz użyć starej C czas pracy

FILE * pf = fopen(filename, "r"); 
char e; 
int a, b, c, d; 
int ii = fscanf(pf, "%c %d,%d %d,%d", &e, &a, &b, &c, &d); 
if (ii < 5) 
    printf("problem in the input file"); 
fclose (pf); 

edytuj: dodano sprawdzanie błędów na podstawie komentarza z dreamlax

+1

Ten jest bardzo czysty. Mimo to upewnij się, że zwracana wartość 'fscanf' wynosi 5, aby upewnić się, że wszystkie zmienne zostały odpowiednio przypisane. – dreamlax

+1

W tych sytuacjach uważam, że fscanf jest lepszy od C++. – StackedCrooked

+0

Co się dzieje z całym dyskiem dzięki przecenianiu tej odpowiedzi? obecny wynik to +4 -3, a nie pojedynczy spadek skłonny wyjaśnić, dlaczego. –

2

wykorzystanie Zwiększ Tokenizer, aby podzielić ciąg znaków. Jestem zakładając, że tylko pierwszy znak jest char, więc przykładowy kod byłoby coś jak:

#include <iostream> 
#include <boost/tokenizer.hpp> 
#include <string> 
#include <vector> 

using namespace std; 

... 

typedef boost::tokenizer<boost::char_separator<char> > tokenizer; 

string teststring("e 225,370 35,75"); 
boost::char_separator<char> separators(", "); 
tokenizer tokens(teststring, separators); 
vector<string> substrings; 
for (tokenizer::iterator iter = tokens.begin(); iter != tokens.end(); ++iter) 
{ 
    substrings.push_back(*iter); 
} 

i, voila, masz wszystkich podciągów w estetycznym wektorze.Znak char jest w podciągach [0] jako std :: string, a następujące wartości int są w podciągach [1] i następnych, również jako std :: string. Konieczne będzie przekonwertowanie ich na wartości całkowite. Do tego proponuję spojrzeć na stringstream.

+0

Biblioteki doładowania można znaleźć tutaj: http://www.boost.org/users/download/ – Demi

13

C++ String Toolkit Library (StrTk) ma następujące rozwiązanie problemu:

 
int main() 
{ 
    std::string data("e 225,370 35,75"); 
    char c1; 
    int i1,i2,i3,i4; 
    strtk::parse(data,", ",c1,i1,i2,i3,i4); 
    return 0; 
} 

Więcej przykładów można znaleźć Here

Powiązane problemy