Reading and saving values ​​from CSV using dynamic allocation C

EDITORIALS BELOW (I wrote this as an edit, not my own question, because it is so connected):

I am writing a CSV reader which should store all values ​​as characters in a large multidimensional array. In previous posts, I was warned that I was too vague with my compressed code, so I'm going to post it more. I want to apologize for its length, as I am still trying to evaluate how the corresponding length looks on this site.

In the end, this program will become the headliner in the header file that I create to perform data analysis. The header files that I use for this program are as follows:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

The problem I am facing is that the reader is working in the read_csv () function. I know this because of the printf () statements placed in this function. When I print f () a multidimensional array of characters "buffer" in main (), the data is not displayed correctly.

In main (), the first column will print correctly, but the next three will not. In addition, my goal is to read any CSV MxN file with cells carrying MAXIMUM of 20 characters. Generating generic code using malloc () is my next goal in this task.

My main () is structured as:

int main(){

  FILE *f;
  char fname[20];
  int i, j;

  printf("enter name of csv file : ") ;
  scanf("%s",fname) ;       

  f = fopen(fname, "r");

  //find row/col
  int find_c_r[2];
  int * pfrc = &find_c_r[0];
  pfrc = find_col_row(f);
  printf("Find_c_r[0] = %d \t Find_c_r[1] = %d\n", *pfrc, *(pfrc+1));

  int numCol = *pfrc;
  int numRow = *(pfrc+1);

  char buffer[50][50][20];// ideally size buffer[numCol][numRow][20]

  //sets all values to NULL
  for(j = 0 ; j < 50 ; j++){
    for(i = 0 ; i < 10 ; i++){   
      memset(buffer[i][j],'\0', 20);
    }
  }

  read_csv(f, numCol, numRow, buffer); 
  /////
  printf("\n\n");

 for(j = 0 ; j < numRow ; j++){
    for(i = 0 ; i < numCol; i++){      
      printf("[%d][%d]",i, j);
      printf("_%s_  ",buffer[i][j]);
    } 
    printf("\n");
  }

  printf("END OF PROGRAM.\n");
 }

One part of this is the dynamic allocation of my "buffer" array. I'm not quite sure how malloc () is in this format.

main() find_col_row (FILE * f). , . int, CSV, :

int * find_col_row(FILE *f){
 //Find numCol and numRow
  int numCol, numRow;
  char c;
  int new_line= 0;
  int comma = 0;
  int z = 0;
  numCol = 0;
  numRow = 0;
  while (c != EOF) {
    c = fgetc(f) ; 
    if(c == ','){ //WORDS MUST BE SEPARATED BY COMMAS
      comma++;
    }
    if(c == ';'){ //LINES MUST BE SEPARATED BY SEMI-COLONS
      new_line++;
      if(numCol == 0){
         numCol = comma + 1;
      }
    } 
  }


  numRow = new_line - 1;

  int a[2] = {numCol, numRow};
  int * pa = &a[0];

  return pa;
}

- read_csv (...). - "" CSV "" " ":

void read_csv(FILE *f, int numCol, int numRow, char buffer[numCol][numRow][20])  //cells split by ',', row split by ';'
{
  char fname[100];
  int i = 0, j = 0;
  int c = 0,n = 0, z = 0;

  if (f == NULL) {
    printf("can't open file, %s\n", fname) ;
    exit(1) ;
  }

  n = 0 ;

  fseek(f, 0, SEEK_SET); //starts reading the file from the start
  c = fgetc(f) ;

  i = 0;
  j = 0;


  char temp[20];
  memset(temp, '\0', 20);
  int tc = 0; //temp counter
  int mv_temp = 0; //this aids in removing the first character if == ' '
  temp[tc] = c;
  while (c != EOF) {

    if(c == ','){
      if(temp[0] == ' '){
         for(mv_temp = 0 ; mv_temp < tc ; mv_temp++){
           temp[mv_temp] = temp[mv_temp + 1];
         }
      }
      strncpy(buffer[i][j], temp, 20);
      i++; 
      tc = 0;
      memset(temp, '\0', 20);
    }else if(c == ';'){
      if(temp[0] == ' '){
         for(mv_temp = 0 ; mv_temp < tc ; mv_temp++){
           temp[mv_temp] = temp[mv_temp + 1];
         }
      }
      strncpy(buffer[i][j], temp, 20);
      j++;
      i = 0;
      tc = 0;
      memset(temp, '\0', 20);
       c = fgetc(f);

    }else{
      temp[tc] = c;
      tc++;
    }
    c = fgetc(f);    
  }  /////while loop over


  for(j = 0 ; j < numRow ; j++){
    for(i = 0 ; i < numCol; i++){      
      printf("[%d][%d]",i, j);
      printf("_%s_  ",buffer[i][j]);
    } 
    printf("\n");
  }

}

CSV , CSV, . scanf() .

simp.csv

, : , , , . :

OFF_FORM,FORM_VAR, DN, DIST;
DEUCE,RIGHT, 1, 10;
DEUCE,LEFT, 2, 7;
TRIO,RIGHT, 3, 3;
TREY,LEFT, 1, 10;
TRIO,RODDY, 1, 10;
TREY,LION, 2, 3;
DEEP,LEFT, 1, 10;
DEUCE,LION, 2, 15;
DEUCE,RIGHT, 3, 4;
DEEP,RODDY, 1, 10;
TREY,RIGHT, 1, 10;
TRIO,RAM, 2, 8;
TRIO,RAM, 3, 8;
DEEP,ROCK, 1, 10;
DEUCE,LION, 1, 10;
TRIO,LOUIE, 1, 10;
TRIO,RIGHT, 2,4;
DEUCE,RIGHT, 3, 6;
DEUCE,LION, 4, 2;
TREY,LION,1,10;

, . , , . , . , , .

//////////////////////////////// ////////////////////////////////

:

, @BLUEPIXY , . , , , . , , .

#ifndef bp_csv_reader
#define bp_csv_reader    

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>

//https://tools.ietf.org/html/rfc4180
char *csv_get_field(FILE *fp, char separator, int *state)

char ***csv_read(const char *filename, size_t *rows, size_t *cols)

char *csv_trim(char *s)

#endif

csv.c :

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "csv.h"

//https://tools.ietf.org/html/rfc4180
char *csv_get_field(FILE *fp, char separator, int *state){
    int ch = fgetc(fp);

    if(ch == EOF)
        return NULL;

    size_t size = 1, index = 0;
    char *field = malloc(size);
    bool quoted_in = false;

    for(;ch != EOF; ch = fgetc(fp)){
        if(ch == '"'){
            if(quoted_in){
                int prefetch = fgetc(fp);
                if(prefetch == '"'){
                    ch = prefetch;
                } else {
                    quoted_in = false;
                    ungetc(prefetch, fp);
                    continue;
                }
            } else {
                quoted_in = true;
                continue;
            }
        } else if(!quoted_in && (ch == separator || ch == '\n')){
            break;
        }
        field[index++] = ch;
        char *temp = realloc(field, ++size);
        if(!temp){
            perror("realloc:");
            free(field);
            exit(EXIT_FAILURE);
        }
        field = temp;
    }
    field[index] = 0;
    *state = ch;
    if(quoted_in){
        fprintf(stderr, "The quotes is not closed.\n");
        free(field);
        return NULL;
    }
    return field;
}

char ***csv_read(const char *filename, size_t *rows, size_t *cols){
    *rows = *cols = 0;

    FILE *fp = fopen(filename, "r");
    if(!fp){
        fprintf(stderr, "%s can't open in %s\n", filename, __func__);
        perror("fopen");
        return NULL;
    }


    char *field;
    int state;
    size_t r = 0, c = 0;
    char ***mat = NULL;
    void *temp;

    while(field = csv_get_field(fp, ',', &state)){
        if(c == 0){
            mat = realloc(mat, (r + 1)*sizeof(*mat));
            if(!mat){
                fprintf(stderr, "realloc failed in %s\n", __func__);
                exit(EXIT_FAILURE);
            }
            mat[r] = NULL;
        }
        mat[r] = realloc(mat[r], (c + 1)*sizeof(**mat));
        if(!mat[r]){
            fprintf(stderr, "realloc failed in %s\n", __func__);
            exit(EXIT_FAILURE);
        }
        mat[r][c++] = field;
        if(state == '\n' || state == EOF){
            if(*cols == 0){
                *cols = c;
            } else if(c != *cols){
                fprintf(stderr, "line %zu doesn't match number of columns in %s\n", r, filename);
                exit(EXIT_FAILURE);
            }
            c  = 0;
            *rows = ++r;
        }
    }
    fclose(fp);

    return mat;
}

#include <ctype.h>

char *csv_trim(char *s){
    if(!s || !*s)
        return s;

    char *from, *to;

    for(from = s; *from && isspace((unsigned char)*from); ++from);
    for(to = s; *from;){
        *to++ = *from++;
    }
    *to = 0;
    while(s != to && isspace((unsigned char)to[-1])){
        *--to = 0;
    }
    return s;
}

:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <csv.h>


int main(void){
    size_t rows, cols;


    char ***mat = csv_read("simp.csv", &rows, &cols);

    size_t r, c;

    for(r = 0; r < rows; ++r){
        for(c = 0; c < cols; ++c){
            if(c)
                putchar(',');
            printf("%s", csv_trim(mat[r][c]));
            free(mat[r][c]);
        }
        puts("");
        free(mat[r]);
    }
    free(mat);
    return 0;
}

, , . , , . , . int it terminal:

 acom test_csv.c csv.c -I. csv.h

, .

In file included from test_cesv.c:5:0:
./csv.h: In function ‘csv_get_field’:
./csv.h:15:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘charchar *csv_trim(char *s)
 ^
test_cesv.c:142:1: error: expected ‘{’ at end of input
 }
 ^
In file included from csv.c:5:0:
csv.h: In function ‘csv_get_field’:
csv.h:15:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘charchar *csv_trim(char *s)
 ^
csv.c:55:67: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘{’ token
 char ***csv_read(const char *filename, size_t *rows, size_t *cols){
                                                                   ^
csv.c:105:24: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘{’ token
 char *csv_trim(char *s){
                        ^
csv.c:120:1: error: expected ‘{’ at end of input
 }
 ^
csv.h: In function ‘csv_get_field’:
csv.h:15:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘charchar *csv_trim(char *s)
 ^
0
1

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

//https://tools.ietf.org/html/rfc4180
char *getCSVField(FILE *fp, char separator, int *state){
    int ch = fgetc(fp);

    if(ch == EOF)
        return NULL;

    size_t size = 1, index = 0;
    char *field = malloc(size);
    bool quoted_in = false;

    for(;ch != EOF; ch = fgetc(fp)){
        if(ch == '"'){
            if(quoted_in){
                int prefetch = fgetc(fp);
                if(prefetch == '"'){
                    ch = prefetch;
                } else {
                    quoted_in = false;
                    ungetc(prefetch, fp);
                    continue;
                }
            } else {
                quoted_in = true;
                continue;
            }
        } else if(!quoted_in && (ch == separator || ch == '\n')){
            break;
        }
        field[index++] = ch;
        char *temp = realloc(field, ++size);
        if(!temp){
            perror("realloc:");
            free(field);
            exit(EXIT_FAILURE);
        }
        field = temp;
    }
    field[index] = 0;
    *state = ch;
    if(quoted_in){
        fprintf(stderr, "The quotes is not closed.\n");
        free(field);
        return NULL;
    }
    return field;
}

char ***read_csv(const char *filename, size_t *rows, size_t *cols){
    *rows = *cols = 0;

    FILE *fp = fopen(filename, "r");
    if(!fp){
        fprintf(stderr, "%s can't open in %s\n", filename, __func__);
        perror("fopen");
        return NULL;
    }

    char *field;
    int state;
    size_t r = 0, c = 0;
    char ***mat = NULL;
    void *temp;

    while(field = getCSVField(fp, ',', &state)){
        if(c == 0){
            mat = realloc(mat, (r + 1)*sizeof(*mat));
            if(!mat){
                fprintf(stderr, "realloc failed in %s\n", __func__);
                exit(EXIT_FAILURE);
            }
            mat[r] = NULL;
        }
        mat[r] = realloc(mat[r], (c + 1)*sizeof(**mat));
        if(!mat[r]){
            fprintf(stderr, "realloc failed in %s\n", __func__);
            exit(EXIT_FAILURE);
        }
        mat[r][c++] = field;
        if(state == '\n' || state == EOF){
            if(*cols == 0){
                *cols = c;
            } else if(c != *cols){
                fprintf(stderr, "line %zu doesn't match number of columns in %s\n", r, filename);
                exit(EXIT_FAILURE);
            }
            c  = 0;
            *rows = ++r;
        }
    }
    fclose(fp);

    return mat;
}

#include <ctype.h>

char *trim(char *s){
    if(!s || !*s)
        return s;

    char *from, *to;

    for(from = s; *from && isspace((unsigned char)*from); ++from);
    for(to = s; *from;){
        *to++ = *from++;
    }
    *to = 0;
    while(s != to && isspace((unsigned char)to[-1])){
        *--to = 0;
    }
    return s;
}

int main(void){
    size_t rows, cols;
    char ***mat = read_csv("simp.csv", &rows, &cols);
    for(size_t r = 0; r < rows; ++r){
        for(size_t c = 0; c < cols; ++c){
            if(c)
                putchar(',');
            printf("%s", trim(mat[r][c]));
            free(mat[r][c]);
        }
        puts("");
        free(mat[r]);
    }
    free(mat);
    return 0;
}
0

All Articles