-
how to read csv file ?
hi all..
i'm creating program that will read a csv file..
let say,,the csv file content 10 rows of data like this..
Code:
10,23,444,-33,45,33,22,445,44,34
1,23,444,-33,45,33,22,445,44,34
-120,23,444,-33,45,33,22,445,44,34
10,23,44,-33,45,33,22,445,4,34
10,23,4,-33,45,33,22,445,44,34
10,23,-44,-33,145,33,22,4,44,34
10,23,444,-33,45,33,22,445,44,34
10,23,444,-33,45,233,22,445,44,34
10,23,444,-33,45,33,22,-45,44,34
10,23,444,-33,45,323,22,445,44,34
now, algorithm that i'm using is,
1) read the data line by line using fgets() and save it to
a char array , let say
szLine_data[256]
2) then seperate and throw out comma
3) the problem now is,, i'm doing processing character by character.
so,, after throw out comma, i dont know how to put let say character 4, 4, 4 to a char array..
what i'm doing now is,,
Code:
while(szLine_data[l] != ',')
{
szTmp[l] = szLine_data[l];
l++;
}
it means that szTmp content comma also at the last element..
how to throw the comma and the balance of the element..
??
-
CSV is a convoluted design, it's not as simple as just looking for commas if you're using real CSV files:
Code:
int csv_parse ( char *line, char *list[], int size )
{
char *p;
char *dp;
int inquote;
int na;
char prevc = ',';
dp = NULL;
inquote = 0;
na = 0;
prevc = ',';
for ( p = line; *p != '\0'; prevc = *p, p++ ) {
if ( prevc == ',' && !inquote ) {
if ( dp != NULL )
*dp = '\0';
if ( na >= size )
return na;
list[na++] = p;
dp = p;
if ( *p == '"' ) {
inquote = 1;
continue;
}
}
if ( inquote && *p == '"' ) {
if ( p[1] != '"' )
inquote = 0;
p++;
}
if ( *p != ',' || inquote )
*dp++ = *p;
}
if ( dp != NULL )
*dp = '\0';
if ( na < size )
list[na] = NULL;
return na;
}
Of course, if you don't worry about the quoting rules, you can shorten the code considerably.
-
See the thread - Simple Question - by Amazing Rando
I posted an 4 line algorithm (no quotes) for decomposing
a known line of csv data into a struct. The length of the algorithm is unaffected by the number of fields, but does have a set-up algorithm that executes once - which IS affected by the number of fields.
Prelude is right, full-blown CSV is a lot harder to parse.
-
thank you for your reply...
I still dont understand your code.. to difficult for me...
i dont understand why we need NULL....
so,, i shorterned your code...
Code:
while(!feof(ptrDat_file))
{
fgets(szLine_dat,LINE_SIZE,ptrDat_file);
nSize = strlen(szLine_dat);
nReturn = csv_parse( szLine_dat, nSize );
printf("%s\n", szTmp_data);
}
return 0;
}
int csv_parse ( char *line, int size )
{
char *p;
char *dp;
int inquote;
int na;
int nTo_comma;
char prevc = ',';
char *list[256];
dp = NULL;
// inquote = 0;
na = 0;
prevc = ',';
nTo_comma=0;
for ( p = line; *p != '\n'; p++ )
{
nTo_comma++;
list[nTo_comma] = p;
if(*p == prevc)
{
printf("%s\t", list);
return na;
}
}
printf("\n");
return na;
}
in while{} looping,,
i get a line of data from csv file and pass to csv_parse() function..
in csv_parse() function,, what i hope is,,,
it should print the 1st data in that line with comma..
ex:
Code:
10,23,444,-33,45,33,22,445,44,34
will print
am I wrong??
if i can do this, after i can up my code 1 step,, to print every data separated by comma..
thank you for your kind help
-
>while(!feof(ptrDat_file))
Why it's bad to use feof() to control a loop
Just a thought...
Code:
#include <stdio.h>
#include <stdlib.h>
#define ARRAYSIZE(x) (sizeof(x)/sizeof(*(x)))
int main(void)
{
const char filename[] = "file.csv";
/*
* Open the file.
*/
FILE *file = fopen(filename, "r");
if ( file )
{
int array[10][10];
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);
}
}
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;
}
/* my output
array[0]: 10 23 444 -33 45 33 22 445 44 34
array[1]: 1 23 444 -33 45 33 22 445 44 34
array[2]: -120 23 444 -33 45 33 22 445 44 34
array[3]: 10 23 44 -33 45 33 22 445 4 34
array[4]: 10 23 4 -33 45 33 22 445 44 34
array[5]: 10 23 -44 -33 145 33 22 4 44 34
array[6]: 10 23 444 -33 45 33 22 445 44 34
array[7]: 10 23 444 -33 45 233 22 445 44 34
array[8]: 10 23 444 -33 45 33 22 -45 44 34
array[9]: 10 23 444 -33 45 323 22 445 44 34
*/
-
Maybe this will be more to your liking:
Code:
#include <stdio.h>
size_t comma_parse ( char *line, char *list[], size_t size );
int main ( void )
{
char *p = "10,23,444,-33,45,33,22,445,44,34";
char *list[11];
size_t n;
size_t i;
n = comma_parse ( p, list, sizeof list );
for ( i = 0; i < n; i++ )
puts ( list[i] );
return 0;
}
size_t comma_parse ( char *line, char *list[], size_t size )
{
char *p;
size_t n;
p = line;
n = 0;
for ( ; ; ) {
/* Ditch leading commas */
while ( *p == ',' )
p++;
/* Nothing of use */
if ( *p == '\0' )
return n;
/* Save the string */
list[n++] = p;
/* Find the next field */
while ( *p != ',' && *p != '\0' )
p++;
/* Nothing else of use or too many fields */
if ( *p == '\0' || n >= size )
return n;
/* Split the field */
*p++ = '\0';
}
}