Bạn đã được thông báo về std::getline
, nhưng họ đã không đề cập đến một chi tiết mà có thể bạn sẽ tìm thấy hữu ích: khi bạn gọi getline
, bạn cũng có thể vượt qua một tham số nói nó những gì nhân vật để điều trị như là kết thúc của đầu vào. Để đọc số điện thoại, bạn có thể sử dụng:
std::string number;
std::string name;
std::getline(infile, number, ':');
std::getline(infile, name);
này sẽ đưa dữ liệu lên đến ':' vào number
, loại bỏ các ':', và đọc phần còn lại của dòng vào name
.
Nếu bạn muốn sử dụng >>
để đọc dữ liệu, bạn cũng có thể làm điều đó, nhưng khó hơn một chút và đi sâu vào một khu vực của thư viện chuẩn mà hầu hết mọi người không bao giờ chạm vào. Một luồng có một liên kết locale
được sử dụng cho những thứ như số định dạng và (quan trọng) xác định những gì cấu thành "khoảng trắng". Bạn có thể xác định miền địa phương của mình để xác định ":" làm khoảng trắng, và khoảng trống ("") là không phải là khoảng trắng. Yêu cầu luồng sử dụng ngôn ngữ đó và nó sẽ cho phép bạn đọc dữ liệu trực tiếp.
#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];
}
};
Bây giờ sử dụng nó, chúng tôi "thấm nhuần" dòng với một ngôn ngữ:
#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;
}
Bây giờ bạn biết lý do tại sao rằng một phần của thư viện được nên bỏ qua. Về lý thuyết, việc có được thư viện chuẩn để làm công việc của bạn cho bạn là rất tốt - nhưng thực tế, hầu hết thời gian bạn dễ dàng thực hiện loại công việc này hơn thay cho bạn.
Streams trong C++ là một trong những điều tôi ghét về C++. – AraK
Khi tôi mới bắt đầu với C++, tôi đã hy vọng rằng các luồng là một trong những điều cuối cùng dẫn đến một biểu hiện của "oooooh thông minh" nhưng sau khi bình luận của bạn, tôi bắt đầu nghĩ rằng điều đó sẽ không bao giờ xảy ra. :( – dreamlax