Reading and Saving Values from a CSV using C with Dynamic Allocation

后端 未结 1 1323
时光取名叫无心
时光取名叫无心 2020-12-20 09:38

EDITS ON THE BOTTOM (I wrote this as an edit rather than its own question because it is so related):

I am writing a CSV reader that should save all the values as ch

相关标签:
1条回答
  • 2020-12-20 10:07

    try this

    #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 讨论(0)
提交回复
热议问题