如何将字符串片段读入类数组C++
How to read pieces of string into a class array C++
我有一个我创建的视频类的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 阵列时,我的大脑会停止。
我还创建了一个 read 方法来读取由空格分隔的每个单词,但我认为这不是我真正想要的。
我还尝试使用 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();
}
}
首先,我将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
来分解该字符串,并使用适用于istringstream
的"内部"getline
调用集分隔逗号上的每个项目。 然后,我们只需根据从istringstream
检索到的信息创建一个临时Video
并将其复制到vid
.
下面是一个main
函数,现在最多可以读取 10 个项目:
int main()
{
Video dvd[10];
int i = 0;
while (i < 10 && std::cin >> dvd[i])
{
dvd[i].print();
++i;
}
}
因此,如果您查看循环,我们所做的只是 1) 确保我们不会超过 10 个项目,以及 2) 只使用cin >> dvd[i]
,这看起来就像您在输入项目时日常使用>>
。 这就是超载>>
的魔力Video
.
下面是一个使用您的数据的实时示例。
如果您打算保留read
函数,那么如果将返回类型更改为返回true
的返回bool
会更容易,如果读取或以其他方式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;
}
}
现场示例 #2
但是,我仍然说,将Video::read
设置为非静态成员会使代码main
笨拙。
- Mongodb c++驱动程序:如何查询元素的数组
- 将数组的地址分配给变量并删除
- 从C++本机插件更新Vector3数组
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 数组索引的值没有增加
- 将对象数组的引用传递给函数
- 为char数组调整zlib-zpipe
- 2D数组来自文本输入,中间有空格
- std::向量与传递值的动态数组
- 在c++中用vector填充一个简单的动态数组
- 使用strcpy将char数组的元素复制到另一个数组
- 使用指针从C++中的数组中获取最大值
- C++使用整数的压缩数组初始化对象
- 告诉一个 const char 数组,除了编译时 C 样式的字符串外,它不以 '