我有一个来自我创建的视频类的DVD数组
Video dvd[10];
每个视频都有属性
class Video {
string _title;
string _genre;
int _available;
int _holds;
public:
Video(string title, string genre, int available, int holds);
Video();
void print();
void read(istream & is, Video dvd);
int holds();
void restock(int num);
string getTitle();
~Video();
};
我正在尝试用我的文本文件中的数据填充此数组,其中每个信息(例如标题和流派)都用逗号分隔
Legend of the seeker, Fantasy/Adventure, 3, 2
Mindy Project, Comedy, 10, 3
Orange is the new black, Drama/Comedy, 10, 9
我尝试过使用 getline(in,line,',')但我的大脑在将每一行插入dvd数组时停止了。
我还创建了一个读取方法来读取由空格分隔的每个单词,但我认为这不是我真正想要的。
我还尝试用getline读取一行,将该行存储在一个字符串中并从那里拆分,但我对此感到困惑。
**我可以从每一行获得我需要的字符串,我的困惑在于如何在while循环中将它插入到我的类数组中,尤其是当我一次只能读取一个单词时。
我需要帮助我应该采取什么方法来解决这个问题。
**我的代码
#include <iostream>
#include <fstream>
#include <cassert>
#include <vector>
#define MAX 10
using namespace std;
class Video {
string _title;
string _genre;
int _available;
int _holds;
public:
Video(string title, string genre, int available, int holds);
Video();
void print();
void read(istream & is, Video dvd);
int holds();
void restock(int num);
string getTitle();
~Video();
};
Video::Video(string title, string genre, int available, int holds){
_title = title;
_genre = genre;
_available = available;
_holds = holds;
}
void Video::read (istream & is, Video dvd)
{
is >> _title >> _genre >> _available>>_holds;
dvd = Video(_title,_genre,_available,_holds);
}
int Video::holds(){
return _holds;
}
void Video::restock(int num){
_available += 5;
}
string Video::getTitle(){
return _title;
}
Video::Video(){
}
void Video::print(){
cout<<"Video title: " <<_title<<"\n"<<
"Genre: "<<_genre<<"\n"<<
"Available: " <<_available<<"\n"<<
"Holds: " <<_holds<<endl;
}
Video::~Video(){
cout<<"DESTRUCTOR ACTIVATED"<<endl;
}
int main(int params, char **argv){
string line;
int index = 0;
vector<string> tokens;
//Video dvd = Video("23 Jump Street", "comedy", 10, 3);
//dvd.print();
Video dvd[MAX];
dvd[0].holds();
ifstream in("input.txt");
/*while (getline(in, line, ',')) {
tokens.push_back(line);
}
for (int i = 0; i < 40; ++i)
{
cout<<tokens[i]<<endl;
}*/
if(!in.fail()){
while (getline(in, line)) {
dvd[index].read(in, dvd[index]);
/*cout<<line<<endl;
token = line;
while (getline(line, token, ',')){
}
cout<<"LINE CUT@@@@@"<<endl;
cout<<line<<endl;
cout<<"TOKEN CUT@@@@@"<<endl;*/
//dvd[index] =
index++;
}
}else{
cout<<"Invalid file"<<endl;
}
for (int i = 0; i < MAX; ++i)
{
dvd[i].print();
}
}
答案 0 :(得分:1)
首先,我会将Video::read
函数更改为operator >>
的重载。这将允许Video
类在使用输入流时像其他任何类型一样使用。
此外,将read
实现为返回void
的非静态成员函数的方式并不直观,而且非常使用起来很笨拙。你会如何编写循环,同时检测到你已经到达文件的末尾(想象一下,如果只有3个项目可读 - 你怎么知道不尝试读取第四个项目)?在C ++中执行此操作的更好,直观,坦率,事实上的方法是重载>>
运算符。
(最后,我展示了如何编写使用重载read
)的>>
函数
class Video
{
//...
public:
friend std::istream& operator >> (std::istream& is, Video& vid);
//..
};
我不会过去为什么这应该是friend
函数,因为这里可以很容易地研究如何重载>>
。
所以我们需要实现这个功能。以下是一个读取单行的实现,并将信息复制到传入的vid
:
std::istream& operator >> (std::istream& is, Video& vid)
{
std::string line;
std::string theTitle, theGenre, theAvail, theHolds;
// First, we read the entire line
if (std::getline(is, line))
{
// Now we copy the line into a string stream and break
// down the individual items
std::istringstream iss(line);
// first item is the title, genre, available, and holds
std::getline(iss, theTitle, ',');
std::getline(iss, theGenre, ',');
std::getline(iss, theAvail, ',');
std::getline(iss, theHolds, ',');
// now we can create a Video and copy it to vid
vid = Video(theTitle, theGenre,
std::stoi(theAvail), // need to change to integer
std::stoi(theHolds)); // same here
}
return is; // return the input stream
}
注意vid
是一个引用参数,不是通过值传递的。您的read
函数,如果您要保留它,则需要进行相同的更改。
我们上面所做的是我们首先使用对std::getline
的“外部”调用来读取整行。一旦我们将该行作为字符串,我们使用std::istringstream
分解该字符串,并使用getline
调用的istringstream
调用分隔逗号上的每个项目。Video
}。然后,我们只需从我们从istringstream
检索到的信息中创建一个临时vid
,然后将其复制到main
。
这是一个int main()
{
Video dvd[10];
int i = 0;
while (i < 10 && std::cin >> dvd[i])
{
dvd[i].print();
++i;
}
}
函数,现在最多可读取10个项目:
cin >> dvd[i]
因此,如果你看一下循环,我们所做的只是1)确保我们不要超过10个项目,2)只使用>>
,这看起来就像你{{1}的日常使用输入项目时。这是>>
重载Video
的神奇之处。
Here is a live example, using your data。
如果您打算保留read
函数,那么如果您将返回类型更改为bool
,如果项目已被读取或true
,则返回false
会更容易}否则,只需调用operator >>
。
以下是一个例子:
bool Video::read(std::istream & is, Video& dvd)
{
if (is.good())
{
is >> dvd;
return true;
}
return false;
}
这是main
函数:
int main()
{
Video dvd[10];
int i = 0;
while (i < 10 && dvd[i].read(std::cin, dvd[i]))
{
dvd[i].print();
++i;
}
}
但是,我仍然说Video::read
使用非静态成员会使main
中的代码变得笨拙。