2017-03-18 2 views
1

J'écris un programme qui ouvrira le fichier csv et sauvegardera les données dans un tableau 3D. La plupart du code fonctionne plutôt bien, mais j'ai un problème avec l'assignation des enregistrements au tableau 2D.Affectation de données à un tableau 2D et affichage de celui-ci C

Voici un code:

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

#define FILE_MODE "r" 
/* 
Explode string with given token and assign result to list variable 
*/ 
int explode(const char *src, const char *tokens, char ***list, size_t *len) 
{ 
    if(src == NULL || list == NULL || len == NULL) { 
     return 0; 
    } 

    char *str, *copy, **_list = NULL, **tmp; 
    *list = NULL; 
    *len = 0; 

    copy = strdup(src); 
    if(copy == NULL) 
     return 1; 

    str = strtok(copy, tokens); 
    if(str == NULL) { 
     goto free_and_exit; 
    } 

    _list = realloc(NULL, sizeof *_list); 
    if(_list == NULL) { 
     goto free_and_exit; 
    } 

    _list[*len] = strdup(str); 
    if(_list[*len] == NULL) 
     goto free_and_exit; 
    (*len)++; 

    while((str = strtok(NULL, tokens))) 
    { 
     tmp = realloc(_list, (sizeof *_list) * (*len + 1)); 
     if(tmp == NULL) 
      goto free_and_exit; 

     _list = tmp; 

     _list[*len] = strdup(str); 
     if(_list[*len] == NULL) 
      goto free_and_exit; 
     (*len)++; 
    } 

free_and_exit: 
    *list = _list; 
    free(copy); 

    return 2; 
} 

/* 
Exploding lines in CSV file 
*/ 
const char* getfield(char* line, int num) 
{ 
    const char* tok; 
    for (tok = strtok(line, ";"); 
      tok && *tok; 
      tok = strtok(NULL, ";\n")) 
    { 
     if (!--num) 
      return tok; 
    } 
    return NULL; 
} 


int main() 
{ 
    FILE *stream; 
    char fileName[256], table[256], line[256], 
     **list, **columns, **data; 
    size_t length; 

    printf("Witaj uzytkowniku! Podaj nazwe pliku z rozszerzeniem .csv. \n"); 
    scanf("%s", fileName); 

    explode(fileName, ".", &list, &length); 
    strcpy(table, list[0]); 

    stream = fopen("file.csv", FILE_MODE); // not to write path every single time 

    if (stream == NULL) { 
     printf("Nie moge otworzyc pliku %s do odczytu!\n", fileName); 
     exit(1); 
    } 

    fgets(line, sizeof line, stream); 
    explode(line, ";", &columns, &length); 

    int recordNumber = 0 
     ,columnNumber = 0; 

    while (fgets(line, sizeof line, stream)) 
    { 
     char* tmp = strdup(line); 
     if (getfield(tmp, recordNumber) != NULL) { 
      columnNumber++; 
     } 

     recordNumber++; 
     free(tmp); 
    } 

    fseek(stream, 0, SEEK_SET); // Go to beginning of file 
    fgets(line, 1024, stream); 

    int i = 0 // Number of records 
     ,h = 0; // number of columns 

    char **records[recordNumber][columnNumber]; 
    length = 0; 
    char *tmp[recordNumber]; 

    // Here I get number of lines and columns in csv file to make 3D array?? 
    while (fgets(line, sizeof line, stream) && i < recordNumber) 
    { 
     tmp[i] = strdup(line); 
     explode(tmp[i], ";", &data, &length); 

     for (h = 0; h < columnNumber; h++) 
     { 
     memcpy(records[i][h], data[h], sizeof(data[h])); 
     } 

     i++; 
    } 

    for (i = 0; i < recordNumber; i++) 
    { 
     for (h = 0; h < columnNumber; h++) 
     { 
     printf("%s ", records[i][h][0]); 
     } 
     printf("\n"); 
    } 

    fclose(stream); 
    return EXIT_SUCCESS; 
} 

problème commence, quand j'essaie faire une boucle, qui attribue des données à un tableau:

while (fgets(line, sizeof line, stream) && i < recordNumber) 
    { 
     tmp[i] = strdup(line); 
     explode(tmp[i], ";", &data, &length); 

     for (h = 0; h < columnNumber; h++) 
     { 
     memcpy(records[i][h], data[h], sizeof(data[h])); 
     } 

     i++; 
    } 

J'ai essayé d'utiliser memcpy et strcpy, mais aucun des œuvres correctement - je suis assez sûr. Lorsque le code passe à ces lignes, il y a une erreur: défaut de segmentation (vidage du cœur). Tout ce que je veux accomplir est de remplir ce tableau avec les données du fichier csv et l'imprimer.

Merci pour votre aide! :)


EDIT:

fonction n'est pas exploser la mienne. Probablement, je l'ai trouvé quelque part sur stackoverflow.

Quand il vient au code, après peu de changement, il fonctionne

char records[recordNumber][columnNumber][1024]; 
    length = 0; 
    char *tmp[recordNumber]; 

    while (fgets(line, sizeof line, stream) && i < recordNumber) 
    { 
     tmp[i] = strdup(line); 
     explode(tmp[i], ";", &data, &length); 

     for (h = 0; h < columnNumber; h++) 
     { 
     strcpy(records[i][h], data[h]); 
     } 

     i++; 
    } 
+0

Veuillez lire [ask], en particulier le bit concernant uniquement [mcve], par opposition à l'ensemble de votre code. –

Répondre

1

Lisez chaque ligne du fichier avec fgets. strpbrk peut être utilisé pour trouver les délimiteurs. Deux pointeurs peuvent être utilisés pour obtenir le nombre de caractères entre les délimiteurs. Ensuite, allouez de la mémoire et utilisez memcpy pour copier le champ dans la mémoire allouée.

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

char ***strpdlm (char *pdelim, int skip); 
char ***freedlm (char ***ppp); 

int main() 
{ 
    char ***expld = NULL; 
    int line = 0; 
    int field = 0; 

    //last argument of 1 is skip consecutive delimiters. 0 do not skip 
    expld = strpdlm (";\n", 1);// delimiters semicolon and newline 
    //print each extracted string 
    line = 0; 
    if (expld) {//not null 
     while (expld[line]) {//not null 
      field = 0; 
      printf ("\nfields for line %d\n", line); 
      while (expld[line][field]) {//not null 
       printf ("expld[%d][%d] %s\n", line, field, expld[line][field]); 
       field++; 
      } 
      line++; 
     } 
    } 
    //free memory and set NULL 
    expld = freedlm (expld); 

    return 0; 
} 

char ***freedlm (char ***ppp) { 
    size_t each = 0; 
    size_t item = 0; 

    if (ppp) { 
     while (ppp[each]) { 
      item = 0; 
      while (ppp[each][item]) { 
       free (ppp[each][item]); 
       item++; 
      } 
      free (ppp[each]); 
      each++; 
     } 
     free (ppp); 
    } 

    return NULL; 
} 

char ***strpdlm (char *pdelim, int skip) { 
    char ***xpld = NULL; 
    char ***temprecord = NULL; 
    char **tempfield = NULL; 
    char *pnt = NULL; 
    char *cur = NULL; 
    char line[1024] = ""; 
    int span = 0; 
    int len = 0; 
    int record = 0; 
    int field = 0; 
    FILE *pf = NULL; 

    if ((pf = fopen ("file.csv", "r")) == NULL) { 
     perror ("could not open \"file.csv\""); 
     return NULL; 
    } 

    if (pdelim) { 
     while (fgets (line, sizeof line, pf)) { 
      //make sure each line ends with \n 
      len = strcspn (line, "\n"); 
      if (len + 1 < sizeof line) { 
       line[len] = '\n'; 
       line[len + 1] = '\0'; 
      } 
      //allocate record + 2 pointers 
      if ((temprecord = realloc (xpld, (record + 2) * sizeof (*xpld))) == NULL) { 
       fprintf (stderr, "problem realloc records\n"); 
       fclose (pf); 
       return xpld; 
      } 
      xpld = temprecord; 
      xpld[record] = NULL; 

      field = 0; 
      cur = line;//cur points to line 
      while ((pnt = strpbrk (cur, pdelim))) { 
       if (pnt != cur || !skip) { 
        if ((tempfield = realloc (xpld[record], (field + 2) * sizeof (**xpld))) == NULL) { 
         fprintf (stderr, "problem realloc fields\n"); 
         fclose (pf); 
         return xpld; 
        } 
        xpld[record] = tempfield; 
        xpld[record][field] = NULL; 

        if (pnt) { 
         span = pnt - cur; 
        } 
        else { 
         span = strlen (cur); 
        } 

        if ((xpld[record][field] = malloc (span + 1)) == NULL) { 
         fprintf (stderr, "problem malloc\n"); 
         fclose (pf); 
         return xpld; 
        } 
        memcpy (xpld[record][field], cur, span); 
        xpld[record][field][span] = '\0'; 
        field++; 
        xpld[record][field] = NULL;//sentinel NULL 
       } 
       cur = pnt + 1;//set cur to point to next field 
      } 
      record++; 
      xpld[record] = NULL;//sentinel NULL 
     } 
    } 
    fclose (pf); 
    return xpld; 
} 
+0

Merci beaucoup pour votre message. Bien sûr, je vais essayer votre code, cependant, il semble être beaucoup plus avancé que le mien - ce n'est pas parfait, mais c'est un programme pour mon étude :) – Franky