Reputation: 209
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).
Upvotes: 2
Views: 8987
Reputation: 84551
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.
Upvotes: 2
Reputation: 40145
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]
Upvotes: 1