Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How do I read a csv file with missing values 1

Status
Not open for further replies.

gismo

Technical User
Jul 24, 2002
35
US
I need to read a csv file that has missing values. The program is suppose to assign the values from the csv to 5 arrays. The program works fine when all fields have values. The problem is when the program encounters ,, instead of a value it skips the pointer assignment. When it encounters a missing value it is suppose to assign -9 as a value. I'm using vc 6.0 to build a console application, below is the code, the input file and the current output.
Code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <ctype.h>


void main (void)
{
	int i,one[4],three[4],five[4];
	float two[4],four[4];
	char line[25];
	char sx[]=",",*s1;

	FILE *ifp;
	ifp=fopen ("test.csv","r");
	i=0;
	while(fgets(line, sizeof line, ifp))
	{
		s1=strtok(line,sx);
		if (s1==NULL) one[i]=-9;else
		one[i]=atoi(s1);

		s1=strtok(NULL,sx);
		if (s1==NULL) two[i]=-9.0;else
		two[i]=atof(s1);

		s1=strtok(NULL,sx);
		if (s1==NULL) three[i]=-9;else
		three[i]=atoi(s1);
		
		s1=strtok(NULL,sx);	
		if (s1==NULL) four[i]=-9.0;else
		four[i]=atof(s1);
	
		s1=strtok(NULL,sx);	
		if (s1==NULL) five[i]=-9;else
		five[i]=atoi(s1);
		

		
		printf("%d %f %d %f %d\n", one[i], two[i],three[i],four[i],five[i]);
	
	  }++i;
}

input file test.csv
1,2.0,3,4.0,5,
1,,3,,5,
1,2.0,,4.0,,

output

1 2.000000 3 4.000000 5
1 3.000000 5 0.000000 -9
1 2.000000 4 -9.000000 -9
 
Maybe strtok returns "" instead of NULL when no values, I'd check that

Cheers,
Dian
 
Dian, thanks for your reply. I took the NULL return into consideration as you can see, I check to see
if (s1 == NULL)one=-9;

Code:
  s1=strtok(line,sx);
        if (s1==NULL) one[i]=-9;else
        one[i]=atoi(s1);
I have since moved on to trying to use strsep instead of strtok. Its not a standard function in the VC string.h, but the source code can be found on the web. I'm pretty sure I'll get it done with strsep. Thanks again but I think I've got it from here.
 
Dian is on the right track. Looking for a NULL return won't work. I just did a quick experiment with strtok, that parses a string using space, comma, and period for tokens. When you have an empty token such as "this is a,, string.", strtok completely skips over the empty set in the ,, without even returning a value.

Gismo, if you aren't already, you should get in the habit of consulting the Clib reference. According to the reference, strtok returns NULL only when there are no further tokens to parse. It does not return NULL on an empty token.

 
I avoid [tt]strtok[/tt] when dealing with empty fields.
A few reasons why, and an alternative:

Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
   static const char filename[] = "file.csv"; /* the name of a file to open */
   FILE *file = fopen(filename, "r"); /* try to open the file */
   if ( file )
   {
      char line[BUFSIZ]; /* space to read a line into */
      while ( fgets(line, sizeof line, file) ) /* read each line */
      {
         int     one, three, five;
         double  two, four;
         char   *ptr = line, *end;

         [COLOR=red]one = strtol(ptr, &end, 10);
         if ( end && *end == ',' )
         {
            if ( ptr != end )
            {
               printf("one = %d, ", one);
            }
            ptr = end + 1;
         }[/color]

         [COLOR=blue]two = strtod(ptr, &end);
         if ( end && *end == ',' )
         {
            if ( ptr != end )
            {
               printf("two = %g, ", two);
            }
            ptr = end + 1;
         }[/color]

         [COLOR=red]three   = strtol(ptr, &end, 10);
         if ( end && *end == ',' )
         {
            if ( ptr != end )
            {
               printf("three = %d, ", three);
            }
            ptr = end + 1;
         }[/color]

         [COLOR=blue]four = strtod(ptr, &end);
         if ( end && *end == ',' )
         {
            if ( ptr != end )
            {
               printf("four = %g, ", four);
            }
            ptr = end + 1;
         }[/color]

         [COLOR=red]five   = strtol(ptr, &end, 10);
         if ( end && *end == ',' )
         {
            if ( ptr != end )
            {
               printf("five = %d, ", five);
            }
            ptr = end + 1;
         }[/color]
         [COLOR=blue]putchar('\n');[/color]
      }
      fclose(file);
   }
   return 0;
}

/* file.txt
1,2.0,3,4.0,5,
1,,3,,5,
1,2.0,,4.0,,
,,,,,
1,,,,,
,2,,,,
,,3,,,
,,,4,,
,,,,5,
*/

/* my output
one = 1, two = 2, three = 3, four = 4, five = 5, 
one = 1, three = 3, five = 5, 
one = 1, two = 2, four = 4, 

one = 1, 
two = 2, 
three = 3, 
four = 4, 
five = 5, 
*/
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top