Реализация на C++
В этом разделе мы напишем версию библиотеки CSV на C++, в которой постараемся
преодолеть некоторые ограничения, имеющиеся в С~версии. Нам придется внести
некоторые изменения в спецификацию, главным из которых станет то, что функции
будут теперь обрабатывать строки C++ вместо массивов символов С.
Использование строк C++ автоматически решит некоторые проблемы, связанные с
хранением данных, поскольку
управлением памятью вместо нас займутся
библиотечные функции. Так, в частности, функции работы с полями будут
возвращать строки, которые затем могут изменяться вызывающей стороной, —
проект получится более гибким, чем в предыдущей версии.
Класс Csv определяет внешние спецификации, изящно скрывая при этом
переменные и функции реализации. Поскольку объект класса исчерпывающе
описывает все состояния
экземпляра, мы можем обрабатывать сразу несколько
переменных Csv, при этом каждая из них будет абсолютно независима, так что
одновременно могут обрабатываться сразу несколько входных потоков CSV.
class Csv { // читает и разбирает CSV
// пример ввода: "LIT, 86. 25, "11/4/1998",
"2:19РМ", +4. 0625
public:
Csv(istream& fin = cin, string sep = ",") :
fin(fin), fieldsep(sep) {}
int getline(string&);
string getfield(int n);
int getnfieldO const { return nfield; }
private:
istream& fin; // указатель на файл ввода
string line; // вводимая строка
vector<string> field; // строки полей
int nfield; // количество полей
string fieldsep; // символы разделителей
int split();
int endofline(char);
int advplain(const string& line,
string& fid, int);
int advquoted(const string& line,
string& fid, int); };
Для конструктора определены параметры, принимаемые по умолчанию, — такой
объект Csv будет читать из стандартного входного потока и использовать обычный
символ-разделитель; эти параметры можно изменить, задав другие значения в
явном виде.
Для работы со строками класс использует не строки С, а стандартные С++-классы st
ring и vector. Для типа st ring не существует невозможного
состояния — "пустая"
строка означает всего лишь строку нулевой длины, и нет никакого значения,
эквивалентного по своему смыслу NULL, который бы мы использовали как сигнал
достижения конца файла. Таким образом, Csv: :getline возвращает введенную строку
через аргумент, передаваемый по ссылке, используя возвращаемое значение для
сообщений о конце файла или ошибках.