2

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).

6
  • i don't import files for input but the problem "A problem caused this program to stop working" happens usually when there is segmentation fault..that is you are accessing something that is not within memory..here you will find details on this en.wikipedia.org/wiki/Segmentation_fault Commented Jun 17, 2014 at 14:29
  • @rock321987 Thanks for helping out! The thing which has got me stumped is: why isn't the problem occurring for smaller CSV's. Why is it happening for a 320x238 CSV. I know that the error is happening because of segmentation fault as the program is trying to access array[320][0] which is not possible, since array has been declared as array[320][238]. The iteration should not have gone to i=320 at all, which does not happen for smaller CSV's, but appens for examples such as above. Commented Jun 17, 2014 at 15:27
  • @user3748848: Check for i < ARRAYSIZE(array) in your outer for loop… Commented Jun 17, 2014 at 15:58
  • @mafso Have done that. This problem gets rectified, but a bigger problem arises. The number of columns is not 238 when the array gets printed; and the last row does not have the column elements of the last row of CSV file. The last row gets filled with elements from the CSV file in an apparently random fashion (neither row-wise nor column-wise) followed by a trail of zeroes. Here is the output: array[237]: 192 138 .......(37 or 38 numbers).. 0 0 0 0 0 0 0 0 0 0 I want to re-iterate that the code works for CSV's even with dimensions 110x90. Commented Jun 17, 2014 at 16:13
  • @mafso Can you please help by running the code with any sample CSV file made from excel having 320 filled rows and 238 filled columns (of integers)? Commented Jun 17, 2014 at 16:15

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

13 Comments

nice observation..i didn't paid attention on the size
@David C. Rankin Thanks for helping out! The thing which has got me stumped is: why isn't the problem occurring for smaller CSV's. Why is it happening for a 320x238 CSV. I know that the error is happening because of segmentation fault as the program is trying to access array[320][0] which is not possible, since array has been declared as array[320][238]. The iteration should not have gone to i=320 at all, which does not happen for smaller CSV's, but happens for examples such as above.
@David C. Rankin Also if I try to allocate array dynamically, would it not be problematic if the array size does not stop at array[319][xx] and goes on increasing since the "for loop of i" is obviously not stopping at i=319?
@rock321987 Can you please help by running the code with any sample CSV file made from excel having 320 filled rows and 238 filled columns (of integers)?
@user3748848 Take a look at the code I posted. It fits your case of 320 integer rows of data and will read and allocate memory for any number of rows of data. If your width becomes variable, you can simply remove the fixed width, then allocate for each member of a row as needed.
|
1
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] 

2 Comments

Yes, that was quite a surprise when I downloaded the csv file and tried if (*ptr == ',') cnt++; printf ("width = %d\n", cnt + 1); and ended up with 320.
@BLUEPIXY Thank you. Your suggestion worked with my code. I made such an embarrassing mistake!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.