Reading data from csv file into struct, getting er

2019-09-15 18:34发布

问题:

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;
 }

回答1:

  1. Wrong copy.

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)

  1. Enable all compiler warnings. This will save you time as your compiler should have caught this.
  2. If you were getting errors, compile time or run time, post the error rather than weakly describe the error as "getting errors back".


回答2:

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.



回答3:

// 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


标签: c csv struct