读取文件以istream替换类变量



我知道如何实现重载的ostream运算符,但我对重载的istream运算符有点困惑。所有在线示例只显示了一个简短的演示(即is>>val;(,这对我在上下文中使用类变量和方法没有帮助。总的来说,我正在尝试读入一个文件,并用文件内容替换指针内容。我有一个工厂方法和读取方法已经做到了,但我正试图重载我的istream运算符来做同样的事情然而,尽管指针的内容被替换了,我仍然收到下面的cerr消息。我应该在>>函数中向if传递一些东西吗

这是我的主要

int main() {
// factory method instantiates all class variables
Base *aa = Base::create(file);     // it works
ifstream in(file2);
if((in >> *aa).fail())             // Read file contents
cerr << "Read failed" << 'n'; 
cout << *aa;                       // prints vector contents
}

打印

// file     // file2      cout << *aa     SupposedToBe
555         111           Read Failed     111
555         222           111             222
555         333           222             333
333

到目前为止我有什么(.cpp(

istream &operator>>(istream &ifs, Base &val) {
string line;
getline(ifs, line); // type of file
if(line == "type1") 
val.filetype = "type1";
if(line == "type2")
val.filetype = "type2";
val.vec.clear();    // clear old vector
vector<int> inner;  // inner vec to push onto main vec
// read remaining contents
while(getline(ifs, line)) {
for(size_t i = 0; i < line.length(); i++) 
inner.push_back(line[i]);
val.vec.push_back(inner);
inner.clear();
}
val.height = val.vec.size();
val.width = val.vec[0].size();
val.max = val.vec[height-1][width-1];
return ifs;
}

我的重载ostream函数看起来与上面显示的有很大不同(即大量的os<<值(。但是,每当我执行ifs>>值时,我都会遇到各种编译器错误(即,我只尝试执行ifs>>val.image;ifs>>val.height;等等,但我得到的只是编译器错误(。我应该把什么传递给istream(在上面的函数中(,这样上面的错误(在main下面(就不会显示了。

用于参考的.h文件

class Base 
{
protected:
std::vector<std::vector<int> > vec;
std::string filetype;
int width, height, max;
Base() = default;
Base &operator=(const Base &) = default;
public:
static Base* create(std::string filename);
virtual ~Base();
// read by derived class
virtual void read(std::string filename) = 0;
friend std::istream &operator>>(std::istream &, Base &);
friend std::ostream &operator<<(std::ostream &, const Image &);
};

的使用

if((in >> *aa).fail())             // Read file contents
cerr << "Read failed" << 'n';

是个问题。按照您实现operator>>(std::istream &, Base &)的方式,该逻辑每次都注定会失败。

函数中有一个循环

while(getline(ifs, line)) {
...
}

只有当没有任何内容可从文件中读取或在读取文件内容时出错时,该循环才会中断。当该循环退出时,ifs.fail()将始终为true。

您应该将if语句替换为:

in >> *aa;

如果您需要进行任何错误检查并打印适当的错误消息,则必须在operator>>(std::istream &, Base &)中进行。

更新,以回应OP的评论

确保istream不会达到ifs.fail()总是true的程度的一种方法是提前知道预期的内容。

如果文件中预期的行数是第一个输入,则可以读取所有数据并从函数返回,使得ifs.fail()false

样本输入:

type1
3
111
222
333

然后,oprator>>函数可以定义为:

std::stream& operator>>(std::istream& ifs, Base& val) 
{
std::string line;
if ( !getline(ifs, line) ) // type of file
{
// Problem reading. No point trying to read more.
return ifs;
}
if(line == "type1") 
val.filetype = "type1";
if(line == "type2")
val.filetype = "type2";
// read remaining contents
int numLines = 0;
if ( !(ifs >> numLines) )
{
// Problem reading. No point trying to read more.
return ifs;
}
val.vec.clear();    // clear old vector
vector<int> inner;  // inner vec to push onto main vec
for ( int n = 0; n < numLines; ++n )
{
if ( !getline(ifs, line))
{
// Problem reading. No point trying to read more.
return ifs;
}
for(size_t i = 0; i < line.length(); i++) 
{
inner.push_back(line[i]);
}
val.vec.push_back(inner);
inner.clear();
}
val.height = val.vec.size();
val.width = val.vec[0].size();
val.max = val.vec[height-1][width-1];
return ifs;
}

最新更新