যেহেতু সমস্ত সিএসভি প্রশ্ন এখানে পুনঃনির্দেশিত হয়েছে বলে মনে হয়েছে, আমি আমার উত্তর এখানে পোস্ট করব। এই উত্তরটি সরাসরি প্রশ্নকারীর প্রশ্নের সমাধান করে না। আমি সিএসভি ফর্ম্যাটে পরিচিত এমন স্ট্রিমে পড়তে সক্ষম হতে চেয়েছি এবং প্রতিটি ক্ষেত্রের প্রকারগুলি ইতিমধ্যে জানা ছিল। অবশ্যই, নীচের পদ্ধতিটি প্রতিটি ক্ষেত্রকে একটি স্ট্রিং ধরণের হিসাবে বিবেচনা করতে ব্যবহার করা যেতে পারে।
আমি কীভাবে একটি সিএসভি ইনপুট স্ট্রিমটি ব্যবহার করতে সক্ষম হতে চেয়েছিলাম তার উদাহরণ হিসাবে, নিম্নলিখিত ইনপুটটি বিবেচনা করুন ( সিএসভিতে উইকিপিডিয়া পৃষ্ঠা থেকে নেওয়া ):
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(); }
};
নিম্নলিখিত সহায়কগুলির সাথে যা সি ++ 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
সম্ভব হলে দূরে থাকুন ।