3

I have to read data from CSV file and use those values in my C function.

I am doing this using below code:

int arg1; char arg2[500]; int arg3; FILE *file; file=fopen(filename,"r"); if (file == NULL) { printf("Not able to open the file\n"); } while (fgets(line,1000, file)!=NULL) { splitline=strtok(line,","); while(splitline) { if(firstargument==1) { arg1=atoi(splitline); printf("First argument is %d ",arg1); firstargument=2; } else if(firstargument==2) { splitline[strlen(splitline)]='\0'; strcpy(arg2,splitline); printf("Second argument is %s\n",arg2); firstargument=3; } else { arg3=atoi(splitline); printf("Third argument is %d ",arg1); firstargument=1; } splitline = strtok(NULL,","); } printf("Value to insert Key:%d,Value:%s,Height:%d\n",arg1,arg2,arg3); inserth(inode,arg1,arg2,arg3); } 

But when my csv file's single column contains multiple comma separated values the parsing fails

350206,Uma,1 350207,Umika,1 350208,"Vaishavi, Vaishnodevi",1 350226,Badriprasad,1 350227,"Kanak, Kanaka",1 

Is there any way to read the csv file multiple values in single column?

3
  • it's not an error it's just that argument values get wrong input as In case I read line 350227,"Kanak, Kanaka",1 my arg1 =350277 arg2="Kanak arg3= Kanaka" So you can see arg3 gets wrong value correct should arg2=Kanak, Kanaka arg3=1 Commented Sep 4, 2015 at 1:50
  • 1
    Your parsing doesn't account for " blocks while using simple comma delimitation using strtok(). Commented Sep 4, 2015 at 1:52
  • Maybe use an open source C library such as the library + CLI at github.com/liquidaty/zsv Commented Jan 21, 2022 at 18:56

3 Answers 3

2

try this

if (file == NULL){ perror("Not able to open the file\n"); exit(EXIT_FAILURE); } while (fgets(line,1000, file)!=NULL){ if( 3==sscanf(line, "%d,\"%499[^\"]\",%d", &arg1, arg2, &arg3) || //pattern 1 3==sscanf(line, "%d,%499[^,],%d", &arg1, arg2, &arg3)){ //pattern 2 printf("Value to insert Key:%d,Value:%s,Height:%d\n",arg1,arg2,arg3); inserth(inode,arg1,arg2,arg3); } else { fprintf(stderr, "invalid format\n"); exit(EXIT_FAILURE); } } 
Sign up to request clarification or add additional context in comments.

Comments

2

One solution is to implement your own strtok that respects double-quotes. strtok by itself is a pretty simple to implement:

char * tokenise( char *str, const char *delim ) { static char *next = NULL; if( str ) next = str; if( !*next ) return NULL; str = next; while( !strchr( delim, *next ) ) next++; if( *next ) *next++ = 0; return str; } 

Now, that's the general case. You only care about commas, and in the case of double quotes, you only care about double quotes:

char * tokenise( char *str ) { static char *next = NULL; if( str ) next = str; if( !*next ) return NULL; str = next; if( *str == '"' ) { str++; next++; while( *next && *next != '"' ) next++; if( *next == '"' ) *next++ = 0; } while( *next && *next != ',' ) next++; if( *next ) *next++ = 0; return str; } 

This is pretty naive, but should do the trick. It detects " in the first character, removes it and then scans to the next ". It doesn't handle escaped quotes, whitespace between CSV fields, or syntax errors (such as non-comma characters appearing after a closing quote -- it will drop them) but you get the idea.

Comments

0

First of all, for a csv file, if a comma comes inside double quotes, it ususally means the comma should be ignored. This means that every row has only 3 values (3 columns).

Since you have only two types of rows, one with double quotes and one without double quotes, as simple if-else statement would help here

I am using strsep instead of strtok. Also I am reading from the file line by line.

#include <string.h> #include <stdio.h> int main() { FILE *file; char *splitline; char * line = NULL; size_t len = 0; ssize_t read; file=fopen(filename,"r"); if (file == NULL) { printf("Not able to open the file\n"); } while ((read = getline(&line, &len, file)) != -1) { if(strstr(line,"\"") != NULL) { printf("%s\n",line); splitline=strsep(&line,","); printf("%s : %s\n",splitline,line); line = line+1; // avoiding first doublequotes("), you may use strsep twice instead splitline = strsep(&line,"\""); printf("%s : %s\n",splitline,line); line = line+1; // removing comma and rest is the 3rd entry printf("%s",line); } else { //Routine code that expects two commas and three values } } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.