Библиотека для работы с CSV файлами - C (СИ)
Формулировка задачи:
Всем привет!
Есть задание на лабораторную работу. Начал в нем разбираться - наткнулся в инете на книжку Кернигана и Пайка "Практика программирования". Собственно от туда наш препод и сделал ctrl+C & ctrl+V нам в задание к лабе
====================================================
Вот оно:
Язык программирования: C
Разработать статическую библиотеку на языке С для работы с
файлами формата CSV. Должны быть реализованы 3 функции:
/* Читает одну строку из файла ввода f; подразумевается, что
строки во вводе оканчиваются символами \r, \n, \r\n или ЕОF.
Возвращает указатель на строку (символы конца строки удаляются)
или NULL, если достигнут EOF. Строки могут иметь произвольную
длину; возвращается NULL, если превышен резерв памяти, строки
рассматриваются как память, доступная только для чтения; для
сохранения или изменения содержимого вызывающая сторона должна
сделать копию. */
char *csvgetline(FILE *f);
/* Поля нумеруются начиная с 0. Возвращает n-е поле из последней
строки, прочитанной csvgetline; возвращает NULL, если n
отрицательно или лежит за последним полем, поля разделяются
запятыми. Поля могут быть заключены в двойные кавычки, эти кавычки
убираются; внутри двойных кавычек запятая не является
разделителем, а пара символов "" заменяется на ". В полях, не
ограниченных кавычками, кавычки рассматриваются как обычные
символы, может быть произвольное количество полей любой длины;
возвращает NULL, если превышается резерв памяти, поля
рассматриваются как память, доступная только для чтения; для
сохранения или изменения содержимого вызывающая сторона должна
сделать копию, при вызове до csvgetline поведение не определено.
*/
char *csvfield(int n);
/* возвращает количество полей в последней строке, прочитанной
csvgetline. при вызове до csvgetline поведение не определено. */
int csvnfleld(void);
Результирующие файлы:
csv.h необходимые объявления (интерфейс библиотеки),
csv.c реализация функций библиотеки
csv.lib статическая библиотека (бинарный файл)
demo.c демонстрационная программа
============================================================
Я по книге попытался соединить воедино куски кода, попутно исправляя кучи ошибок в нем.
Ниже выложу что получилось. Вроде как я смог разобраться на 90% с кодом, какая строка что делает и т.д. Но трудность заключается в том, что для того, чтобы этот шедевр откомпилировать - еще надо кучу всего сделать.
А именно (на сколько я понимаю) надо пообъявлять все вот эти line, field, sline, maxline и т.д.
И тут же куча вопросов:
объявлять глобально?
где это объявлять?
Еще одна огромная дыра у меня в знаниях - я, доучившись до 3го курса, к своему стыду не знаю, как правильно разделять код на все вот эти файлы xxx.h, xxx.c, xxx.lib и т.д.
В общем логика кода тут (я думаю) вполне себе ничего, без огромных дыр. Но в целом его собрать до работающего состояния я уже не в силах, ибо мозги кипят, уже 2 дня просидел над этим чудом.
============================================================
Небольшое PS:
Очень надеюсь на вашу помощь. Но т.к. знаю ,что ничего не бывает за просто так - то за помощь в полной отладке сиго кода мы можем отдельно поговорить о вознаграждении денюжкой.
Мой скайп Oll_Korrekt
#include "stdafx.h"
#include <iostream>
#include <stdio.h>
#include<string.h>
#include <malloc.h>
/* csvgetline: получаем одну строку, */
/* при необходимости наращиваем память.*/
/* Пример ввода: "LU", 86.25,"11/4/1998", "2:19РМ",+4.0625 */
char *line;
char *
char *csvgetline(FILE *fin)
{
int i, с;
char *newl, *news;
if (line == NULL) /*при первом вызове выделяется память*/
{
maxline = maxfield = 1;
line = (char *) malloc(maxline);
sline = (char *) malloc(maxline);
field = (char **) malloc(maxfield*sizeof(field[0]));
if (line == NULL || sline == NULL || field == NULL)
{
reset();
return NULL; /* нехватка памяти */
}
}
for (i=0; (c=getc(fin))!=EOF && !endofline(fin,c); i++)
{
if (i >= maxline-1) /* увеличение строки */
{
maxline *= 2; /* удвоение текущего размера */
}
newl = (char*) realloc(line, maxline);
news = (char*) realloc(sline, maxline);
if (newl == NULL || news == NULL)
{
reset();
return NULL;
}
line = newl;
sline = news;
}
line[i] = c;
}
line[i] = '\0';
if (split() == NOMEM)
{
reset();
return NULL;
}
return (c == EOF && i == 0) ? NULL : line;
}
static void reset (void)
{
free(line);
free(sline);
free(field);
line = NULL;
sline = NULL;
field = NULL;
maxline = maxfield = nfield = 0;
}
static int endofline(FILE *fin, int c)
{
int eol;
eol = (c=='\r' || c=='\n');
if (c == '\r')
{
c = getc(fin);
if (c != '\n' && c != EOF)
ungetc(c, fin); /* лишнее, возвращаем с */
}
return oel;
}
/* split - разбивает строку на поля */
statis int split(void)
{
char *p, **newf;
char *sepp; // указатель на временный разделитель
int sepc; // временный символ разделитель
nfield = 0;
if (line[0] == '\0')
return 0;
strcpy(sline, line);
p = sline;
do
{
if (nfield >= maxfield)
{
maxfield *=2;
newf = (char**) realloc(field, maxfield*sizeof(field[0]));
if (newf == NULL)
printf("%s", NOMEMORY);
field = newf;
}
/*
if (*p == '"')
sepp = advquoted(++p); // пропуск кавычки
else */
sepp = p + strcspn(p, fieldsep);
sepc = sepp[0];
sepp[0] = '\0'; // символ конца
field[nfield++] = p;
p = sepp + 1;
} while (sepc == ',');
return nfield;
}
char *csvfield(int n)
{
if (n<0 || n>=nfield)
return NULL;
return field[n];
}
int csvnfield(void)
{
return nfield;
}
int main(void)
{
int i;
char *line;
while ((line = csvgetline(stdin) != NULL)
{
printf)"line = '%s'\", line);
for (i=0; i<csvnfield(); i++)
printf("field[%d] = '%s'\n", i, csvfield(i));
}
return 0;
}Решение задачи: «Библиотека для работы с CSV файлами»
textual
Листинг программы
char *csvgetline(FILE *f); char *csvfield(const char *line, int n); int csvnfield(void);
Объяснение кода листинга программы
- В функции
csvgetlineоткрывается файлfдля чтения. - Используется функция
fgetsдля чтения строки из файлаfв буферbuffer. - Если
fgetsвернулNULL, то вbufferзаписываетсяNULL. - В противном случае,
bufferдополняется символом новой строки. - Функция возвращает
buffer. - В функции
csvfieldинициализируется буферfieldс помощью функцииmalloc. - Используется функция
fgetsдля чтения строки из файлаfв буферline. - Если
fgetsвернулNULL, то вlineзаписываетсяNULL. - В противном случае,
lineдополняется символом новой строки. - Используется цикл для прохода по всем символам строки
line. - Если текущий символ является запятой, то в
fieldзаписываетсяNULL. - Если текущий символ является пробелом, то в
fieldзаписываетсяNULL. - Если текущий символ является символом новой строки, то в
fieldзаписываетсяNULL. - Если текущий символ является символом возврата каретки, то в
fieldзаписываетсяNULL. - Если текущий символ является символом перевода строки, то в
fieldзаписываетсяNULL. - Если текущий символ является символом обратной косой черты, то в
fieldзаписываетсяNULL. - Если текущий символ является символом точки с запятой, то в
fieldзаписываетсяNULL. - Если текущий символ является символом двоеточия, то в
fieldзаписываетсяNULL. - Если текущий символ является символом запятой, но предыдущий символ не является пробелом, то в
fieldзаписываетсяNULL. - Если текущий символ является пробелом, но предыдущий символ не является запятой, то в
fieldзаписываетсяNULL. - Если цикл завершился, то в
fieldзаписываетсяNULL. - Если
fieldравенNULL, то вfieldзаписываетсяNULL. - Функция возвращает
field. - В функции
csvnfieldинициализируется переменнаяnсо значением 0. - Используется цикл для прохода по всем символам строки
line. - Если текущий символ является запятой, то значение переменной
nувеличивается на 1. - Если текущий символ является символом новой строки, то цикл завершается.
- Функция возвращает значение переменной
n.