Reputation: 33
I would like to pass the value of a double pointer to certain members of a struct. I ve function which returns a double pointer. Basically I can access and print the different values of the pointer. The external function parse_csv which delivers the double pointer is from this github repo [repo][1] But I can't parse it into my struct. If I m trying to print the value of the struct with printf. I doesn't print anything. The program just stops at this point.
struct.h. is where I ve defined my struct
#ifndef STRUCT_H
#define STRUCT_H
extern struct data* {
char* value1;
int value2;
int value3;
float value4;
}
#endif
readcsv.c
#include "struct.h"
struct data* data1;
char **parse_csv( const char *line ) {
char **buf, **bptr, *tmp, *tptr;
const char *ptr;
int fieldcnt, fQuote, fEnd;
fieldcnt = count_fields( line );
if ( fieldcnt == -1 ) {
return NULL;
}
buf = malloc( sizeof(char*) * (fieldcnt+1) );
if ( !buf ) {
return NULL;
}
tmp = malloc( strlen(line) + 1 );
if ( !tmp ) {
free( buf );
return NULL;
}
bptr = buf;
for ( ptr = line, fQuote = 0, *tmp = '\0', tptr = tmp, fEnd = 0; ; ptr++ ) { if ( fQuote ) {
if ( !*ptr ) {
break;
}
if ( *ptr == '\"' ) {
if ( ptr[1] == '\"' ) {
*tptr++ = '\"';
ptr++;
continue;
}
fQuote = 0;
}
else {
*tptr++ = *ptr;
}
continue;
}
switch( *ptr ) {
case '\"':
fQuote = 1;
continue;
case '\0':
fEnd = 1;
case ',':
*tptr = '\0';
*bptr = strdup( tmp );
if ( !*bptr ) {
for ( bptr--; bptr >= buf; bptr-- ) {
free( *bptr );
}
free( buf );
free( tmp );
return NULL;
}
bptr++;
tptr = tmp;
if ( fEnd ) {
break;
} else {
continue;
}
default:
*tptr++ = *ptr;
continue;
}
if ( fEnd ) {
break;
}
}
*bptr = NULL;
free( tmp );
return buf;
}
char *fread_csv_line(FILE *fp, int max_line_size, int *done, int *err) {
static FILE *bookmark;
static char read_buf[READ_BLOCK_SIZE], *read_ptr, *read_end;
static int fread_len, prev_max_line_size = -1;
static char *buf;
char *bptr, *limit;
char ch;
int fQuote;
if ( max_line_size > prev_max_line_size ) {
if ( prev_max_line_size != -1 ) {
free( buf );
}
buf = malloc( max_line_size + 1 );
if ( !buf ) {
*err = CSV_ERR_NO_MEMORY;
prev_max_line_size = -1;
return NULL;
}
prev_max_line_size = max_line_size;
}
bptr = buf;
limit = buf + max_line_size;
if ( bookmark != fp ) {
read_ptr = read_end = read_buf + READ_BLOCK_SIZE;
bookmark = fp;
}
for ( fQuote = 0; ; ) {
QUICK_GETC(ch, fp);
if ( !ch || (ch == '\n' && !fQuote)) {
break;
}
if ( bptr >= limit ) {
free( buf );
*err = CSV_ERR_LONGLINE;
return NULL;
}
*bptr++ = ch;
if ( fQuote ) {
if ( ch == '\"' ) {
QUICK_GETC(ch, fp);
if ( ch != '\"' ) {
if ( !ch || ch == '\n' ) {
break;
}
fQuote = 0;
}
*bptr++ = ch;
}
} else if ( ch == '\"' ) {
fQuote = 1;
}
}
*done = !ch;
*bptr = '\0';
return strdup(buf);
}
static int count_fields( const char *line ) {
const char *ptr;
int cnt, fQuote;
for ( cnt = 1, fQuote = 0, ptr = line; *ptr; ptr++ ) {
if ( fQuote ) {
if ( *ptr == '\"' ) {
fQuote = 0;
}
continue;
}
switch( *ptr ) {
case '\"':
fQuote = 1;
continue;
case ',':
cnt++;
continue;
default:
continue;
}
}
if ( fQuote ) {
return -1;
}
return cnt;
}
void parse_data_to_struct(){
static char *buf1;
char **parsed_data;
FILE *f = fopen("example.csv, "r");
buf1 = fread_csv_line(f,max_amnt_char,&done,&err);
parsed_data = parse_csv(buffer);
printf("%s \n",parsed_data[2]);
strcpy(data1[i].value1, parsed_data[1]);
printf("%s \n",data1[i].value1);//this actually doesn t print anything
data1[i].value2=atoi(parsed_data[0]);
}
#include readcsv.c
int app_main(void){
parse_data_to_struct();
return 0;
}
Here is an example csv
Index,User Id,First Name,Last Name,Sex,Email,Phone,Date of birth,Job Title 1,88F7B33d2bcf9f5,Shelby,Terrell,Male,[email protected],001-084-906-7849x73518,1945-10-26,Games developer,\n 2,f90cD3E76f1A9b9,Phillip,Summers,Female,[email protected],214.112.6044x4913,1910-03-24,Phytotherapist,\n 3,DbeAb8CcdfeFC2c,Kristine,Travis,Male,[email protected],277.609.7938,1992-07-02,Homeopath,\n
[1]: https://github.com/semitrivial/csv_parser
Upvotes: 1
Views: 48
Reputation: 807
Here is a much simpler csv parser that returns a null terminated array of tokens split from the line of text passed in.
char **parse_csv( const char *line )
{
char* data = malloc(strlen(line) + 1);
strcpy(data, line);
char** fields;
int field_count = 0;
for (int i = 0; data[i] != '\0'; ++i)
{
if (data[i] == ',')
field_count += 1;
}
fields = malloc(sizeof(char*) * (field_count + 1));
char* token;
char* context;
token = strtok_s(data, ",\n", &context);
int field_index = 0;
while (token != NULL)
{
fields[field_index] = (char*)malloc(strlen(token) + 1);
strcpy(fields[field_index], token);
field_index++;
fields[field_index] = NULL;
token = strtok_s(NULL, ",\n", &context);
}
return fields;
}
You can test it with the following code:
int main()
{
char** stuff = parse_csv("1,88F7B33d2bcf9f5,Shelby,Terrell,Male,[email protected],001-084-906-7849x73518,1945-10-26,Games developer,\n");
while (*stuff != NULL)
{
printf("Item: %s\n", *stuff);
stuff++;
}
}
So in your real application you need to pass each line from the csv file and process the returned tokens as appropriate. I have deliberately not handled double quotes as they do not appear in your sample data, but additional code to process them can be added later.
Upvotes: 0