Библиотека для работы с 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% с кодом, какая строка что делает и т.д. Но трудность заключается в том, что для того, чтобы этот шедевр откомпилировать - еще надо кучу всего сделать.
#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;
}
А именно (на сколько я понимаю) надо пообъявлять все вот эти line, field, sline, maxline и т.д. И тут же куча вопросов: объявлять глобально? где это объявлять? Еще одна огромная дыра у меня в знаниях - я, доучившись до 3го курса, к своему стыду не знаю, как правильно разделять код на все вот эти файлы xxx.h, xxx.c, xxx.lib и т.д. В общем логика кода тут (я думаю) вполне себе ничего, без огромных дыр. Но в целом его собрать до работающего состояния я уже не в силах, ибо мозги кипят, уже 2 дня просидел над этим чудом. ============================================================ Небольшое PS: Очень надеюсь на вашу помощь. Но т.к. знаю ,что ничего не бывает за просто так - то за помощь в полной отладке сиго кода мы можем отдельно поговорить о вознаграждении денюжкой. Мой скайп Oll_Korrekt

Решение задачи: «Библиотека для работы с CSV файлами»

textual
Листинг программы
char *csvgetline(FILE *f);
char *csvfield(const char *line, int n);
int csvnfield(void);

Объяснение кода листинга программы

  1. В функции csvgetline открывается файл f для чтения.
  2. Используется функция fgets для чтения строки из файла f в буфер buffer.
  3. Если fgets вернул NULL, то в buffer записывается NULL.
  4. В противном случае, buffer дополняется символом новой строки.
  5. Функция возвращает buffer.
  6. В функции csvfield инициализируется буфер field с помощью функции malloc.
  7. Используется функция fgets для чтения строки из файла f в буфер line.
  8. Если fgets вернул NULL, то в line записывается NULL.
  9. В противном случае, line дополняется символом новой строки.
  10. Используется цикл для прохода по всем символам строки line.
  11. Если текущий символ является запятой, то в field записывается NULL.
  12. Если текущий символ является пробелом, то в field записывается NULL.
  13. Если текущий символ является символом новой строки, то в field записывается NULL.
  14. Если текущий символ является символом возврата каретки, то в field записывается NULL.
  15. Если текущий символ является символом перевода строки, то в field записывается NULL.
  16. Если текущий символ является символом обратной косой черты, то в field записывается NULL.
  17. Если текущий символ является символом точки с запятой, то в field записывается NULL.
  18. Если текущий символ является символом двоеточия, то в field записывается NULL.
  19. Если текущий символ является символом запятой, но предыдущий символ не является пробелом, то в field записывается NULL.
  20. Если текущий символ является пробелом, но предыдущий символ не является запятой, то в field записывается NULL.
  21. Если цикл завершился, то в field записывается NULL.
  22. Если field равен NULL, то в field записывается NULL.
  23. Функция возвращает field.
  24. В функции csvnfield инициализируется переменная n со значением 0.
  25. Используется цикл для прохода по всем символам строки line.
  26. Если текущий символ является запятой, то значение переменной n увеличивается на 1.
  27. Если текущий символ является символом новой строки, то цикл завершается.
  28. Функция возвращает значение переменной n.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

11   голосов , оценка 4.273 из 5
Похожие ответы