简体   繁体   中英

Import CSV elements into a 2D array in C

I am pretty new to C. I have been trying to import integer elements from a csv file into array in C. The code works fine when I have to import CSV files having lesser rows and columns; for example, I have tried it successfully with a CSV file having 90 rows and 80 columns. However, the problem begins when the CSV has more number of rows/columns. To be specific, I am trying to import a CSV file containing 238 rows and 320 columns. However the program terminates showing "A problem caused this program to stop working". I have mentioned in the code where the program goes wrong. Please help me as I am unable to know the reason behind this problem.

I have searched elsewhere, but did not find answers specific to C. Also, there is a similiar question on Stackoverflow here: (Since, it is for 1D array, and my approach is somewhat different, I have decided to ask a new question here.) CSV into array in C

Here is the specific link for CSV file: https://drive.google.com/file/d/0BxnaWIgBd3AjbGVrY1FTdFpxemM/edit?usp=sharing

Here is my code:

#include <stdio.h>
#include <stdlib.h>
#define ARRAYSIZE(x)  (sizeof(x)/sizeof(*(x)))

int main(void)
{
   const char filename[] = "1.csv";
   /*
    * Open the file.
    */
   FILE *file = fopen(filename, "r");
   if ( file )
   {
      int array[320][238];
      size_t i, j, k;
      char buffer[BUFSIZ], *ptr;
      /*
       * Read each line from the file.
       */
      for ( i = 0; fgets(buffer, sizeof buffer, file); ++i )
      {
         /*
          * Parse the comma-separated values from each line into 'array'.
          */
         for ( j = 0, ptr = buffer; j < ARRAYSIZE(*array); ++j, ++ptr )
         {
            array[i][j] = (int)strtol(ptr, &ptr, 10);
         }
         /* The problem seems to occur here..after the 237th iteration...
         "i" begins to advance the iteration to 238 after it has done upto
         237 iterations which is making the program hang.....THIS ERROR NEVER
         OCCURS FOR CSV FILES OF SMALLER DIMENSIONS, SPECIFICALLY SAY 99 rows
         and 79 columns*/
      }

      fclose(file);
      /*
       * Print the data in 'array'.
       */
      for ( j = 0; j < i; ++j )
      {
         printf("array[%lu]: ", (long unsigned)j);
         for ( k = 0; k < ARRAYSIZE(*array); ++k )
         {
            printf("%4d ", array[j][k]);
         }
         putchar('\n');
      }
   }
   else /* fopen() returned NULL */
   {
      perror(filename);
   }
   return 0;
}

Also, I would like to stress upon the fact that the code works perfectly well for smaller CSV's like [110]x[90] and the iteration stops exactly at i=109. However, for bigger arrays like these, "i" is not stopping at 237. Also, I know the exact number of rows and columns beforehand. It's not a problem with allocation, it's the problem with the loop (which is leading to segmentation fault).

You are attempting to add more rows of data than your array can hold. You declared the array as int array[320][238]; -- that is 320 rows, by 238 columns. Arrays are 0 based meaning the elements of the array runs [0-319] and [0-237] . That is why up to 319 works, but fails on 320. Try increasing your array size, or just declare the array columns and then dynamically allocate rows as needed.

I tested your csv file and the following works. I also found your data was actually 238 rows x 320 columns as shown in the additional answer. So yes, your array should actually be array[238][320] . Allocating dynamically has its advantages:

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

#define ARRAY_WIDTH 320

int main (int argc, char *argv[]) {

    int *array[ARRAY_WIDTH];
    int idx = 0;
    int j = 0;
    char *buffer = NULL;
    size_t len = 0;
    ssize_t read;
    char *ptr = NULL;

    FILE *fp;
    fp = fopen ("test.txt", "r");      //open file , read only
    if (!fp) {
        fprintf (stderr, "failed to open file for reading\n");
        return 1;
    }

    while ((read = getline (&buffer, &len, fp)) != -1) {

        array[idx] = malloc (sizeof (array));

        for (j = 0, ptr = buffer; j < ARRAY_WIDTH; j++, ptr++)
            array [idx][j] = (int)strtol(ptr, &ptr, 10);

        idx++;
    }

    fclose (fp);
    int i = 0;

    for (i=0; i<idx; i++) {
        printf ("\narray[%d][] =", i);

        for (j=0; j<ARRAY_WIDTH; j++)
            printf (" %d", array[i][j]);
    }

    puts ("");

    return 0;
}

This presumes you have a fixed ARRAY_WIDTH. In your case 320. Note the use of getline instead of fgets , it is the preferred method of line input.

int array[320][238];//<<- Rows <-> columns 

change to

int array[238][320];

and

char buffer[BUFSIZ] //<<- Buffer size is probably small

change to

char buffer[4096]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM