我对从文件读取输入的知识很新,所以我不知道我哪里错了 这几乎就是代码:
Reservation* res = new Reservation();
ifstream fin("data.csv");
while(!fin.eof()) {
fin >> res->ID;
fin.get();
fin.getline >> res->name;
fin.getline >> res->phone;
fin >> res->gridironID;
fin.get();
fin.getline >> res->hireDate;
fin.getline >> res->resDate;
fin.getline >> res->startTime;
fin.getline >> res->endTime;
fin >> res->isPay;
fin.get();
res->nextReservation = reservationHeader;
reservationHeader = res;
}
fin.close();
}
我的结构:
struct Reservation
{
int ID;
char name[MAX_NAME_LENGTH];
char phone[MAX_PHONE_LENGTH];
int gridironID;
char hireDate[MAX_DATE_LENGTH];
char resDate[MAX_DATE_LENGTH];
char startTime[MAX_TIME_LENGTH];
char endTime[MAX_TIME_LENGTH];
bool isPay;
Reservation *nextReservation;
};
这是data.csv文件的一个示例:
100001,khang,01283478233,1,1,1,1,1,1
100002,Christina,01283478233,1,1,1,1,1,1
100003,GuanYung,01283478233,1,1,1,1,1,1
100004,kevin,01283478233,1,1,1,1,1,1
100005,minh,01283478233,1,1,1,1,1,1
我不断得到的错误是:
Error 10 error C2297: '>>' : illegal, right operand has type 'char [12]'
Error 13 error C2297: '>>' : illegal, right operand has type 'char [12]'
Error 5 error C2297: '>>' : illegal, right operand has type 'char [15]'
//....(this pretty much the same for the other lines)
Error 1 error C3867: 'std::basic_istream<char,std::char_traits<char>>::getline': function call missing argument list; use '&std::basic_istream<char,std::char_traits<char>>::getline' to create a pointer to member
//...
请以任何可能的方式帮助我:(
答案 0 :(得分:0)
您尝试做的事情有两个直接问题:
1. std::istream >>
不知道如何将数据推送到C风格的数组中。
2. std::istream
并不知道,
是有效的分隔符。
你基本上不幸(1)。您可以切换到使用C ++ std::string
而不是C风格的字符串,或者使用>>
之外的其他内容来读取数据。当然,有充分的理由在结构中保留C风格的字符串,但值得考虑其他选择。
让我们暂时坚持使用C风格的琴弦。这是一个有用的功能:
fin.getline(res->name, MAX_NAME_LENGTH, ',');
这将从流中提取最多MAX_NAME_LENGTH - 1
个字符(或者它将提取字符,直到找到逗号,以先到者为准)。这些字符将被推入到您的字符数组中,然后将其以空值终止(因此它不会提取MAX_NAME_LENGTH
个字符)。如果找到逗号,它将从流中删除,但不会添加到您的字符串中。
现在,我注意到您在代码中检查的唯一条件是eof()
。这很好,但还不够。您还应该检查fin.fail()
。如果格式化的函数无法提取它们被要求的类型,或者getline
到达其缓冲区大小的末尾而未看到分隔符,则将设置此项。设置failbit
后,其他任何读取都不会成功。您应该处理此错误情况,可能是通过引发错误,并可能通过清除它并尝试正常读取下一条记录并希望只有一条记录已损坏。
那么分隔符呢?
默认情况下,std::istream
要求字段以空格分隔。这就是为什么如果您使用逗号分隔值,大多数人最终会使用getline
来提取每个字段。
原来,流处理文本的方式非常灵活。我从这里的文档中采用了这个示例:http://en.cppreference.com/w/cpp/locale/ctype_char
// This ctype facet classifies commas and endlines as whitespace
struct csv_whitespace : std::ctype<char> {
static const mask* make_table()
{
// make a copy of the "C" locale table
static std::vector<mask> v(classic_table(), classic_table() + table_size);
v[','] |= space; // comma will be classified as whitespace
v[' '] &= ~space; // space will not be classified as whitespace
return &v[0];
}
csv_whitespace(std::size_t refs = 0) : ctype(make_table(), false, refs) {}
};
// some function elsewhere in your code
stream.imbue(std::locale(stream.getloc(), new csv_whitespace()));
通过修改此流的区域设置,我们告诉它' '
不再是字段分隔符,而是','
。没有其他流会受到影响。
现在为了充分利用这一点,你必须从使用C风格的字符串改为C ++风格std::string
但是一旦你完成了这一点,一切开始变得更加简单:
struct Reservation
{
int ID;
std::string name;
std::string phone;
int gridironID;
std::string hireDate;
std::string resDate;
std::string startTime;
std::string endTime;
bool isPay;
Reservation *nextReservation;
};
// reading from your imbued stream elsewhere:
while(!fin.eof()) {
fin >> res->ID >> res->name >> res->phone >> res->gridironID >>
res->hireDate >> res->resDate >> res->startTime >> res->endTime >>
res->isPay;
res->nextReservation = reservationHeader;
reservationHeader = res;
}
fin.close();
简单,不是吗?换行符仍然被认为是字段分隔符,所以一切都应该&#34;只是工作&#34;。
注意:您的代码和我的代码都不支持&#34; real&#34; csv,带引号的字符串。如果您需要这种功能,请考虑查找可以为您执行此操作的类或库。正确地做csv&#34;&#34;比你想象的更棘手!