954,499 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

.csv into array problem :(

I bet the answer to my problem is hidden somewhere in these forums as this seems to be a fairly common question, yet after literally 2 days of searching for an answer I can't find it so please bare with me.

What I'm trying to do here is to read a .csv file, 200 rows, 2 columns, standard formation, comma separated. Then I want to store the contents of the file in an array and be able to manipulate data from that point on. This is the code I've come up with so far.

#include "stdafx.h"
#include "conio.h."
#include "stdlib.h"
#include "string.h"

int _tmain(int argc, _TCHAR* argv[])
{
	struct
	{
		char grade[10];
		char name[15];
	}	student[200];

	FILE *fp;
	char count[200];

    int i=0,j;

    fp=fopen("students.csv","r");
	if(fp==NULL)
		{
			printf("Could not properly load file!\n");
			getch();
			exit(8);
		}
	else
		{
			printf("File openned and loaded properly\n\n");
		}

    while(fgets(count,20,fp)!=NULL)
			 {
			 strcpy(student[i].grade,strtok(count,","));
                         strcpy(student[i].name,strtok(count,","));
                         ++i;
			 }
			 
    for(j=0;j<200;j++)
			 {
				 printf("%s\t",&student[j]);
				
			 }

	printf("\nClosing file\n");
    fclose (fp);


	getch();
	return 0;
}


The csv file looks pretty much like this:

15.1,John
17.34,Angella
23.31,Jake
82.49,Christy

I know my problem should pretty much be in line 34. At the moment the program does compile and properly outputs the data contained on the first column which is numerical (float). I just have no clue how to parse second column data (the names) into student[].name

Assuming I get to the point that data is properly separated in student[].grade and student[].name I'd like to convert the numerical data from char strings into float numerical data. I understand atof is the way to do but after experimenting with it I can't get it to work, getting strange results no matter how much I tried.

Thanks in advance, please ignore the fact that my code most likely sucks, I'm a complete newbie when it comes to C and programming in general. Also please note that C++ is not an option, only ANSI C is allowed.

Maelstrom80
Newbie Poster
4 posts since Jan 2008
Reputation Points: 10
Solved Threads: 0
 

line 34: the first parameter to strtok() is supposed to be NULL. It should be a valid string only the first time strtok() is called, which was on line 33.

Ancient Dragon
Retired & Loving It
Team Colleague
30,049 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 

Ok thats understandable. But how exactly can I parse the second column of the file into the array? (the names part). Was my approach to the problem completely wrong? :S

Maelstrom80
Newbie Poster
4 posts since Jan 2008
Reputation Points: 10
Solved Threads: 0
 

If you run the program with that change I suggested it should work ok.

Ancient Dragon
Retired & Loving It
Team Colleague
30,049 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 

You're absolutely right and your help is greatly appreciated :)

Maelstrom80
Newbie Poster
4 posts since Jan 2008
Reputation Points: 10
Solved Threads: 0
 
I understand atof is the way to do but after experimenting with it I can't get it to work, getting strange results no matter how much I tried.

Hi, char array is not string, atof take string as param, put '\0' in the last of char array, probably then it will work
like:
char abc[]={'3','.','5','\0'};
printf("no. is %f",atof(abc));

DangerDev
Posting Pro in Training
485 posts since Jan 2008
Reputation Points: 165
Solved Threads: 59
 

I decided to rewrite the code, this time instead of playing around with strcpy and strtok I wanted to try fscanf which (from my newbie point of view) would make my life easier dealing with first columns numerical floating point data.

int _tmain(int argc, _TCHAR* argv[])
{
	FILE *fp;
	float numbers[200];
	char name[200];
	int i=0;
	int j=0;
		
	fp=fopen("students.csv","r");


	while(!feof(fp)) 
		{ 
			fscanf(fp, "%f", &numbers[i]);
			fscanf(fp, "%s", &name[i]);
			i++;
		}

	for(j=0;j<200;j++)
		{	
			printf("%f\n",numbers[j]);
			printf("%s\n",name[j]);
		}
	getch();
	return 0;
}


Obviously line15 is wrong, I can tell that much. I just don't know how to fix it :S
Keep in mind data on file is populated in the follow style:

15.1,John
17.34,Angella
23.31,Jake
82.49,Christy
.....

So how should that fscanf look like in order for it to catch the names? I guess somehow reading from comma to carriage return. Or did I completely misunderstood fscanf and doesnt work for char data?

Last little problem, when parsing numbers, I get somewhat strange results, for example 17.34 turns into 17.340001 or 23.31 turns into 23.309998 , why is this happening?

Sorry for my newbish questions and thanks in advance for your answers and patience.

Maelstrom80
Newbie Poster
4 posts since Jan 2008
Reputation Points: 10
Solved Threads: 0
 

lines 14 and 22: names[i] is not a valid pointer because names is declared wrong on line 5. What you want is this: char name[200][20]; and assume the length of a name will never be more than 20 characters.

I think you can combine lines 14 and 15 like this (untested): fscanf(fp, "%f,%s", &numbers[i], names[i]);

>Last little problem, when parsing numbers, I get somewhat strange results, for example 17.34 turns into 17.340001 or 23.31 turns into 23.309998 , why is this happening?

That's the nature of floting point numbers and has to do with powers of 2. Many numbers can not be represented exactly with floats and doubles, which is why you can't test them for equality with the == operator. To get an in-depth explaination you would have to read the IEEE standards, available free on the net.

Ancient Dragon
Retired & Loving It
Team Colleague
30,049 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You