जैसा कि सभी CSV प्रश्न यहाँ पुनर्निर्देशित होते हैं, मुझे लगता है कि मैं यहाँ अपना उत्तर पोस्ट करूँगा। यह उत्तर सीधे पूछने वाले के प्रश्न को संबोधित नहीं करता है। मैं एक धारा में पढ़ना चाहता था जिसे सीएसवी प्रारूप में जाना जाता है, और प्रत्येक क्षेत्र के प्रकार भी पहले से ही ज्ञात थे। बेशक, नीचे दी गई विधि का उपयोग प्रत्येक क्षेत्र को एक स्ट्रिंग प्रकार होने के लिए किया जा सकता है।
एक उदाहरण के रूप में कि मैं CSV इनपुट स्ट्रीम का उपयोग कैसे करना चाहता था, निम्नलिखित इनपुट पर विचार करें ( CSV पर विकिपीडिया के पृष्ठ से लिया गया है ):
const char input[] =
"Year,Make,Model,Description,Price\n"
"1997,Ford,E350,\"ac, abs, moon\",3000.00\n"
"1999,Chevy,\"Venture \"\"Extended Edition\"\"\",\"\",4900.00\n"
"1999,Chevy,\"Venture \"\"Extended Edition, Very Large\"\"\",\"\",5000.00\n"
"1996,Jeep,Grand Cherokee,\"MUST SELL!\n\
air, moon roof, loaded\",4799.00\n"
;
फिर, मैं इस तरह से डेटा को पढ़ने में सक्षम होना चाहता था:
std::istringstream ss(input);
std::string title[5];
int year;
std::string make, model, desc;
float price;
csv_istream(ss)
>> title[0] >> title[1] >> title[2] >> title[3] >> title[4];
while (csv_istream(ss)
>> year >> make >> model >> desc >> price) {
//...do something with the record...
}
यही वह उपाय था, जिसे मैंने खत्म किया।
struct csv_istream {
std::istream &is_;
csv_istream (std::istream &is) : is_(is) {}
void scan_ws () const {
while (is_.good()) {
int c = is_.peek();
if (c != ' ' && c != '\t') break;
is_.get();
}
}
void scan (std::string *s = 0) const {
std::string ws;
int c = is_.get();
if (is_.good()) {
do {
if (c == ',' || c == '\n') break;
if (s) {
ws += c;
if (c != ' ' && c != '\t') {
*s += ws;
ws.clear();
}
}
c = is_.get();
} while (is_.good());
if (is_.eof()) is_.clear();
}
}
template <typename T, bool> struct set_value {
void operator () (std::string in, T &v) const {
std::istringstream(in) >> v;
}
};
template <typename T> struct set_value<T, true> {
template <bool SIGNED> void convert (std::string in, T &v) const {
if (SIGNED) v = ::strtoll(in.c_str(), 0, 0);
else v = ::strtoull(in.c_str(), 0, 0);
}
void operator () (std::string in, T &v) const {
convert<is_signed_int<T>::val>(in, v);
}
};
template <typename T> const csv_istream & operator >> (T &v) const {
std::string tmp;
scan(&tmp);
set_value<T, is_int<T>::val>()(tmp, v);
return *this;
}
const csv_istream & operator >> (std::string &v) const {
v.clear();
scan_ws();
if (is_.peek() != '"') scan(&v);
else {
std::string tmp;
is_.get();
std::getline(is_, tmp, '"');
while (is_.peek() == '"') {
v += tmp;
v += is_.get();
std::getline(is_, tmp, '"');
}
v += tmp;
scan();
}
return *this;
}
template <typename T>
const csv_istream & operator >> (T &(*manip)(T &)) const {
is_ >> manip;
return *this;
}
operator bool () const { return !is_.fail(); }
};
C ++ 11 में नए अभिन्न लक्षण टेम्पलेट द्वारा सरल किए जा सकने वाले निम्नलिखित सहायकों के साथ:
template <typename T> struct is_signed_int { enum { val = false }; };
template <> struct is_signed_int<short> { enum { val = true}; };
template <> struct is_signed_int<int> { enum { val = true}; };
template <> struct is_signed_int<long> { enum { val = true}; };
template <> struct is_signed_int<long long> { enum { val = true}; };
template <typename T> struct is_unsigned_int { enum { val = false }; };
template <> struct is_unsigned_int<unsigned short> { enum { val = true}; };
template <> struct is_unsigned_int<unsigned int> { enum { val = true}; };
template <> struct is_unsigned_int<unsigned long> { enum { val = true}; };
template <> struct is_unsigned_int<unsigned long long> { enum { val = true}; };
template <typename T> struct is_int {
enum { val = (is_signed_int<T>::val || is_unsigned_int<T>::val) };
};
इसे ऑनलाइन आज़माएं!
boost::spirit
पार्सिंग के लिए देखा है । यह एक सरल फ़ाइल प्रारूप को पार्स करने के लिए व्याकरण को धन्यवाद देने के लिए अधिक है। मेरी टीम का कोई व्यक्ति XML को पार्स करने के लिए इसका उपयोग करने की कोशिश कर रहा था और यह डिबग करने के लिए एक दर्द था।boost::spirit
हो सके तो दूर रहें ।