Теперь с учетом того, чему мы научились на опыте прототипа, попробуем создать библиотеку общего назначения. Наиболее очевидные требования такие: csvgetline должна быть более устойчива, то есть уметь обрабатывать и длинные строки, и большое количество полей; более осторожно надо подойти и к синтаксическому разбору полей.
Для создания интерфейса, который могли бы использовать и другие люди, мы должны выработать решения по аспектам, перечисленным в начале главы: интерфейсы, сокрытие деталей, управление ресурсами и обработка ошибок; их взаимосвязь оказывает сильнейшее влияние на проект. Наше разделение этих проблем было несколько произвольно, так как они сильно взаимосвязаны.
Интерфейс. Мы выработали решение о трех базовых операциях:
char *csvgetline(FILE *): читает новую CSV строку;
char *csvf ield(int n): возвращает n-е поле текущей строки;
int csvnf leld(void): возвращает число полей в текущей строке.
Какое значение должна возвращать csvgetline? Желательно, чтобы она возвращала побольше полезной информации; тогда напрашиваете* возвращение того же количества полей, как и в прототипе. Но тогда количество полей будет подсчитываться даже в случае, если поля эти больше использоваться не будут. Еще один вариант возврата — длина вводимой строки, но это значение зависит от того, включать ли в длину завершающий символ перевода строки. После ряда экспериментов мы пришли к выводу, что csvgetline должна возвращать указатель на оригинальную строку ввода или NULL, если был достигнут конец файла.
Мы будем удалять символ перевода строки из конца строки, возвращаемой csvgetline, так как, если понадобится, его можно без труда вписать обратно.
С определением поля дело обстоит довольно сложно; мы попробовали собрать воедино варианты, которые встречались в электронных таблицах и других программах. Получилось примерно следующее.
Поле является последовательностью из нуля или более символов. Поля разделены запятыми. Открывающие и завершающие пробелы (пропуски) сохраняются. Поле может быть заключено в двойные кавычки, в этом случае оно может содержать запятые.