Reputation: 11
I'm trying to read data from a csv file into a struct. The struct contains int, char and float members. I'm getting errors back except for the char member. I'm fairly new to C so I appreciate your help!
Data from csv file "Order":
0, cafe, 3.90, 0
0, espresso, 3.50, 0
...
My struct:
typedef struct {
int position;
char name[20];
float price;
int counter;
}drink;
void init(drink *pt)
{
FILE *fp;
char buf[50];
int i = 0, j;
fp=fopen("Order", "r");
while( fgets(buf,sizeof(buf),fp) != NULL)
{
strcpy(pt[i].position, strtok(buf,","));
strcpy(pt[i].name, strtok(NULL,","));
strcpy(pt[i].price, strtok(NULL,","));
strcpy(pt[i].counter, strtok(NULL,","));
++i;
}
}
int main()
{
int number = NR;
int d=0;
drink bar[number];
drink *pt = &bar[0];
welcome();
init(pt);
...
return 0;
}
Upvotes: 0
Views: 684
Reputation: 16550
// to extract a integer from a char buffer into a int value, use atoi() not strcpy
// to extract a float from a char buffer into a float value, use atof(), not strcpy
// the last field in a line probably does not have a trailing ','
// and the last field should already be '\0' terminated by the fgets
// so the code should use something else to get a pointer to the last field
// the calls to strtok() should be setting a char* field from the returned value
// then
// 1) that value can be checked for NULL
// 2) getting a pointer to the last field would be
// returnedValue+=2;
// (the 2 to skip over the intervening ' ' after the converted comma
// all the copying/converting of the fields need to advance the
// returnedValue by 1 to skip over the leading ' ',
// except the first field, which has no leading ' '
// the #define for 'NR' should be used in the function so as to
// not overflow the available number of input fields
// for most of the break; statements, you may want to add a printf
// so the user knows what happened
// suggest:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NR (20)
#define MAX_NAME_LEN (20)
typedef struct
{
int position;
char name[MAX_NAME_LEN];
float price;
int counter;
} drink;
void init(drink *pt)
{
char buf[50];
int i = 0; // loop counter
//int j = 0; // comment out or compiler will raise a warning about unused variable
char * returnFromStrtok = NULL;
FILE *fp = NULL;
if( NULL == (fp=fopen("Order", "r")) )
{ // then, fopen failed
perror( "fopen failed for: Order" );
exit( EXIT_FAILURE );
}
// implied else, fopen successful
for( i = 0; i<NR; i++)
{
if( NULL == fgets(buf,sizeof(buf),fp) ) break;
returnFromStrtok = strtok(buf, ",");
if( NULL == returnFromStrtok ) break;
pt[i].position = atoi(returnFromStrtok);
returnFromStrtok = strtok(NULL, ",");
if( NULL == returnFromStrtok ) break;
// step past leading ' '
returnFromStrtok++;
if( MAX_NAME_LEN <= strlen( returnFromStrtok ) )
{ // bad field, too long
memset( pt[i].name, '*', MAX_NAME_LEN ); // indicate invalid field
}
else
{
strcpy(pt[i].name, returnFromStrtok );
}
returnFromStrtok = strtok(NULL, ",");
if( NULL == returnFromStrtok ) break;
// step past leading ' '
returnFromStrtok++;
pt[i].price = atof(returnFromStrtok);
// +2 steps by '\0' and ','
returnFromStrtok += strlen(returnFromStrtok)+2;
pt[i].counter = atoi(returnFromStrtok);
} // end for
} // end function: init
Upvotes: 0
Reputation: 154602
Do not use strcpy()
to copy a string to an int
. Rather convert it.
// strcpy(pt[i].position, strtok(buf,","));
char *endptr;
pt[i].position = strtol(strtok(buf,","), &endptr, 10);
// or
pt[i].position = atoi(strtok(buf,","));
...
pt[i].price = strtod(strtok(NULL,","), &endptr);
(Note: Various error checking omitted)
Upvotes: 1
Reputation: 165
You are not using strcpy correct. You should only use it with char buffers, not with integers and floats.
Read man strcpy for more information about it.
Upvotes: 0