Библиотека для работы с 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
.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д