将数据从csv文件读入struct,得到错误

时间:2014-11-30 07:19:10

标签: c csv struct

我正在尝试将csv文件中的数据读入结构中。该结构包含int,char和float成员。我收到错误,除了char成员。我对C很新,所以感谢你的帮助!

来自csv文件的数据“订单”:

0, cafe, 3.90, 0
0, espresso, 3.50, 0
...

我的结构:

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

3 个答案:

答案 0 :(得分:1)

  1. 错误的副本。
  2. 请勿使用strcpy()将字符串复制到int。而是转换它。

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

    (注意:省略了各种错误检查)

    1. 启用所有编译器警告。这将节省您的时间,因为您的编译器应该抓住它。
    2. 如果您收到错误,编译时间或运行时间,请发布错误 而不是简单地将错误描述为"得到错误"。

答案 1 :(得分:0)

您没有正确使用strcpy。 你应该只使用char缓冲区,而不是整数和浮点数。

阅读man strcpy了解有关它的更多信息。

答案 2 :(得分:0)

// 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
相关问题