使用重载<<带动态数组的运算符

时间:2015-02-21 09:42:01

标签: c++ arrays dynamic operators

我的问题如下:

我想使用重载的>>将文件中的值读入名为Voter的特定类的动态数组中。运营商。 然后,我想将我的结果导出到屏幕,以检查我的负载与另一个重载<<操作

使用普通数组后我得到了结果,但是在动态中挣扎。 我已经在论坛上看到,矢量可能是更好的方法,但我想了解我在这个问题上做错了什么。

谢谢!

详细信息:

该文件有3个“值”,由空格分隔: id(string)nr(int)(1或0)bool

代码提取:

string RollFileName = "VotersRoll.dat";
ifstream inFile_VotersRoll;
inFile_VotersRoll.open(RollFileName);

if(inFile_VotersRoll.fail())
{
    printf("The VotersRoll.dat file failed to open.\n");
    exit(1);

}
//connect to in file



int numberOfEntries = 0;
Voter testVoter;
while(inFile_VotersRoll>>testVoter)
{
    numberOfEntries++;
}
//get number of voter objects from file

typedef Voter* VoterArrayPntr;
VoterArrayPntr rollArray;
rollArray = new Voter[numberOfEntries];
//create dynamic arrray for voter objects


while (inFile_VotersRoll>>*rollArray) {
    cout << *rollArray;

}

类(摘录):

class Voter
{
public:
    friend istream& operator>>(istream &inP, Voter &voterP);
    friend ostream& operator<<(ostream &outP,const Voter &voterP);
private:
    string id;
    int nr_times_voted;
    bool voted;
}

朋友的功能:

istream& operator>>(istream &inP,Voter &voterP)
{  
   inP >> voterP.id >> voterP.nr_times_voted >> voterP.voted;
   return inP; 
}
ostream& operator<<(ostream &outP,const Voter &voterP)
{ 
   outP << voterP.id << voterP.nr_times_voted << voterP.voted;   
   return outP;
}

2 个答案:

答案 0 :(得分:1)

在C ++中,std::vector实现了动态数组的概念。这不仅仅是&#34;也许&#34;更好的方法。 请勿使用new[]delete[]

(事实上,你的示例代码中完全没有delete[]。如果你不在任何地方释放内存,只要程序运行,对象在概念上就不存在,那么&# 39;内存泄漏。)

至于为什么代码在这里不起作用,让我们首先看看这个循环:

int numberOfEntries = 0;
Voter testVoter;
while(inFile_VotersRoll>>testVoter)
{
    numberOfEntries++;
}

这很奇怪;你第一次阅读整个文件只是为了得到元素的数量,然后再次读取它以获得实际的元素?

这是多余的。你应该在一个循环中获得所有东西。

但是这里还有两个严重的错误:

  1. 在第二个循环开始之前,您已到达文件末尾
  2. 您只使用数组的第一个元素
  3. 让我们先解决第一个问题。在下一个循环中,

    typedef Voter* VoterArrayPntr;
    VoterArrayPntr rollArray;
    rollArray = new Voter[numberOfEntries];
    //create dynamic arrray for voter objects
    
    while (inFile_VotersRoll>>*rollArray) {
        cout << *rollArray;
    }
    

    循环条件永远不会成立。您的operator>>被调用一次。流从操作员返回。最后,它在循环条件中使用,导致false - 因为你已经在文件的末尾。

    一个非常快速的解决方法是为同一个文件打开一个新流来解决这个问题:

    typedef Voter* VoterArrayPntr;
    VoterArrayPntr rollArray;
    rollArray = new Voter[numberOfEntries];
    //create dynamic arrray for voter objects
    
    ifstream inFile_VotersRoll2; // ugly workaround
    inFile_VotersRoll2.open(RollFileName);
    while (inFile_VotersRoll2>>*rollArray) {
        cout << *rollArray;
    }
    

    这将读取并打印整个文件。但是,所有内容都只能从数组的第一个元素读入和写入。 *rollArray指的是第一个元素,rollArray永远不会改变。

    第二个错误修复如下:

    for (int index = 0; (index < numberOfEntries) && (inFile_VotersRoll2>>rollArray[index]); ++index) { 
        cout << rollArray[index];
    }
    

    但正如我之前所说,你的目标应该是立即阅读整个事情。这意味着随着时间的推移增加阵列的大小。幸运的是,对于std::vector,这是微不足道的,因为std::vector不仅会自动增长,而且in a clever way也是如此。内存也会自动释放。在这里,我们将您的完整示例修改为使用std::vector

    #include <string>
    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <stddef.h>
    
    using namespace std; // just for quick'n'dirty test code
    
    class Voter
    {
    public:
        friend istream& operator>>(istream &inP, Voter &voterP);
        friend ostream& operator<<(ostream &outP,const Voter &voterP);
    private:
        string id;
        int nr_times_voted;
        bool voted;
    };
    
    istream& operator>>(istream &inP,Voter &voterP)
    {  
       inP >> voterP.id >> voterP.nr_times_voted >> voterP.voted;
       return inP; 
    }
    ostream& operator<<(ostream &outP,const Voter &voterP)
    { 
       outP << voterP.id << voterP.nr_times_voted << voterP.voted;   
       return outP;
    }
    
    int main() {
    
        string RollFileName = "VotersRoll.dat";
        ifstream inFile_VotersRoll;
        inFile_VotersRoll.open(RollFileName);
    
        if(inFile_VotersRoll.fail())
        {
            std::cerr << "The VotersRoll.dat file failed to open.\n";
            return EXIT_FAILURE;
        }
    
        std::vector<Voter> voters;
    
        Voter input;
        while (inFile_VotersRoll >> input) {
            voters.push_back(input);
        }
    
        for (auto const &voter : voters) {
            std::cout << voter << "\n";
        }
    }
    

答案 1 :(得分:0)

  

“我想了解我在这个问题上做错了什么。”

你的循环

while (inFile_VotersRoll>>*rollArray) {
    cout << *rollArray;
}

只会写入数组中的第一个元素。读入后需要将指针递增到下一个元素:

inFile_VotersRoll.seekp(0); // Rewind to the beginning of inFile_VotersRoll

VoterArrayPntr curItem = rollArray;
while (inFile_VotersRoll>>*curItem) {
    cout << *curItem;
    curItem++; // <<<<<<
}