Masz już powiedziano o std::getline
, ale nie wspomina jeden szczegół, który prawdopodobnie okaże się przydatne: podczas rozmowy getline
można również przekazać parametr informujący go jaką postać traktować jako koniec wejścia. Aby odczytać numer, można użyć:
std::string number;
std::string name;
std::getline(infile, number, ':');
std::getline(infile, name);
To będzie umieścić dane aż do „:” w number
, wyrzucić „:” i przeczytać resztę linii do name
.
Jeśli chcesz odczytać dane z >>
, możesz to zrobić, ale jest to trochę trudniejsze i zagłębia się w obszar standardowej biblioteki, której większość ludzi nigdy nie dotyka. Strumień jest powiązany z locale
używanym do formatowania liczb i (co ważniejsze) określania, co stanowi "białą przestrzeń". Możesz zdefiniować własne ustawienia narodowe, aby zdefiniować ":" jako białą przestrzeń i spację ("") jako białą przestrzeń. Poinformuj strumień, aby używał tego ustawienia narodowego, i pozwoli Ci bezpośrednio odczytać dane.
#include <locale>
#include <vector>
struct colonsep: std::ctype<char> {
colonsep(): std::ctype<char>(get_table()) {}
static std::ctype_base::mask const* get_table() {
static std::vector<std::ctype_base::mask>
rc(std::ctype<char>::table_size,std::ctype_base::mask());
rc[':'] = std::ctype_base::space;
rc['\n'] = std::ctype_base::space;
return &rc[0];
}
};
Teraz go używać, my „nasycić” strumień z lokalizacji:
#include <fstream>
#include <iterator>
#include <algorithm>
#include <iostream>
typedef std::pair<int, std::string> data;
namespace std {
std::istream &operator>>(std::istream &is, data &d) {
return is >> d.first >> d.second;
}
std::ostream &operator<<(std::ostream &os, data const &d) {
return os << d.first << ":" << d.second;
}
}
int main() {
std::ifstream infile("testfile.txt");
infile.imbue(std::locale(std::locale(), new colonsep));
std::vector<data> d;
std::copy(std::istream_iterator<data>(infile),
std::istream_iterator<data>(),
std::back_inserter(d));
// just for fun, sort the data to show we can manipulate it:
std::sort(d.begin(), d.end());
std::copy(d.begin(), d.end(), std::ostream_iterator<data>(std::cout, "\n"));
return 0;
}
Teraz wiesz dlaczego że część biblioteki jest tak zaniedbane. Teoretycznie, zdobycie standardowej biblioteki, która wykona twoją pracę dla ciebie, jest wspaniałe - ale w rzeczywistości, w większości przypadków łatwiej jest wykonać taką pracę na własną rękę.
Strumienie w C++ są jedną z rzeczy, których nienawidzę o C++. – AraK
Ponieważ jestem nowy w C++, miałem nadzieję, że strumienie były jedną z tych rzeczy, które ostatecznie doprowadziły do epifanii "oooooh that's clever", ale po twoim komentarzu zaczynam myśleć, że to się nigdy nie wydarzy. :( – dreamlax