【问题标题】:constructor does not work correctly while reading variables from txt file从 txt 文件中读取变量时构造函数无法正常工作
【发布时间】:2021-04-04 07:13:24
【问题描述】:

我有一个关于我的构造函数不能正常工作的问题。每当我运行程序时,我的重载运算符可能无法正确执行,因为当我使用 cout 获得输出时,我总是得到默认的构造函数值。

我相信我的构造函数声明做得很好,但是我的所有对象都被 0Unknown

这是我的 txt 文件:

1 Prince Heins 25
2 Lady Bridgette 29
3 Tony Ann 223
4 Lucy Phoenix 35

这是我的代码;

#include <iostream>
#include <string>
#include <conio.h>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#include <istream>
#include <iomanip>
#include <cstring>
#include <ostream>

    using namespace std;
    
    class contact{
    private:
    
        int listno;
        string name;
        string surname;
        string phonenumber;
            
    public:
        contact(){
            this->name="Unknown";
            this->surname="Unknown";
            this->phonenumber="Unknown";
            this->listno=0;
        }
        contact (string name,string surname,string phonenumber){
            this->name=name;
            this->surname=surname;
            this->phonenumber=phonenumber;
        }
        contact(int listno,string name,string surname,string phonenumber){
            
            this->name=name;
            this->surname=surname;
            this->listno=listno;
            this->phonenumber=phonenumber;
        }
    
        friend ostream & operator<< (ostream &out, const contact &con){
            out << con.listno << con.name << con.surname << con.phonenumber;
            return out;
        }
        
        friend istream & operator>> (istream &in, contact &con){
            in >> con.listno >> con.name >> con.surname >> con.phonenumber;
            return in;
        } 
    
    };
    
    
    
    
    
    int main(){
        ifstream pbin("phoneData2.txt");
        string line;
        long linecount;
        for(linecount=0;getline(pbin,line);linecount++);
        contact* myArray = new contact[linecount];
        pbin.seekg(0);
        if(pbin.is_open()){
            int i;
            for(i=0;i<linecount;i++){
                if(pbin!=NULL){
                    while(pbin>>myArray[i]);
                }
                
        }
        pbin.close();
        
        cout << myArray[2]; // try attempt
        
        return 0;
        }
    }

这是我对 cout 的输出

OutputArray2

【问题讨论】:

  • 您错过了将文件的读取指针重置为第一个之后的开头。环形。另外你不需要提前知道行数,只需使用std::getline()std::istringstream根据需要提取值。
  • 在第一个循环之后,pbin 仍然设置了eof 标志。所有读取操作都失败。事实上,我认为if(pbin!=NULL) 检查是错误的,所以代码甚至没有调用你的operator&gt;&gt;
  • 使用调试器。
  • 请不要在此处发布文字图片。您可以轻松复制终端输出。
  • @πάνταῥεῖ 我怎样才能重置读取指针,你能更具体一点吗?感谢您提供有关 istringstream 的信息!我不知道=)

标签: c++ class oop object overloading


【解决方案1】:

问题是由错误使用的算法和错误放置的语句引起的。

那么,让我们看看下面发生了什么:

long linecount;
for(linecount=0;getline(pbin,line);linecount++)
    ;
contact* myArray = new contact[linecount];
pbin.seekg(0);
if(pbin.is_open()){
    int i;
    for(i=0;i<linecount;i++){
        if(pbin!=NULL) {
            while(pbin>>myArray[i]);
        }
    }
    pbin.close();

您想计算行数。因此,您阅读所有行,直到设置了eofstate。但是,另外,fail 位也将被设置。另见here

如果您使用调试器,您会在_Mystate 中找到一个 3。

然后你执行seekg。这将重置eof 位,但保留fail 位。然后调试器显示

您可以看到fail 位仍然设置。

所以,这将导致主要问题。如果你写的if(pbin!=NULL) 肯定是错误的(在我的机器上甚至没有编译),或者如果你最好写if(pbin) 失败位仍然会被设置。并且由于流的bool! 运算符被覆盖(请参阅here),ifwhile 的结果将为假,您的pbin&gt;&gt;myArray[i] 将永远不会被执行。

所以,pbin.clear() 会有所帮助。

但是,尽管您的类定义已经非常好,插入器和提取器被覆盖,您并没有使用完整的 C++ 功能来读取数据。

一个基本的建议是永远不要对拥有的内存使用原始指针。最好不要new。为您的目的使用专用容器。例如。 std::vector。您可以将std::vectors 构造函数no 5std::istream_iterator 一起使用。请阅读herestd::vector 的基于范围的构造函数将从给定范围复制数据,由开始和结束迭代器表示。如果您使用std::istream_iterator,它将调用您覆盖的提取器运算符,直到读取所有数据。

所以你的主要缩小到:

int main() {

    // Open source file and check, if it could be opened
    if (ifstream pbin("r:\\phoneData2.txt");pbin) {

        // Read complete source file
        std::vector data(std::istream_iterator<contact>(pbin), {});

        // Show data on console
        std::copy(data.begin(), data.end(), std::ostream_iterator<contact>(std::cout, "\n"));
    }
    return 0;
}

这看起来更紧凑,更易于阅读。我们从if-statement with initializer 开始。初始化部分定义了变量,构造函数将为我们打开文件。在条件部分,我们简单的写成pbin。而且,如上所述,它的bool 运算符将被调用,以检查一切是否正常。

请注意:

  1. 我们不需要close 语句,因为 std::ifstream 将为我们关闭文件。
  2. 外部命名空间不会被变量名pbin 污染。这就是为什么应该使用带有初始化程序的ifstatement 的原因之一。

我们已经描述了std::vector 及其范围构造函数。所以阅读完整的文件很简单,很简单的语句就可以完成

std::vector data(std::istream_iterator<contact>(pbin), {});

请注意:

  1. 我们没有定义std::vector 的类型。这将由编译器通过CTAD自动推导出来
  2. 我们使用默认初始化器 {} 作为结束迭代器,如在构造函数 1 中的 here 所示。

然后整个程序可以重写为:

#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <algorithm>
#include <iterator>

using namespace std;

class contact {
private:

    int listno;
    string name;
    string surname;
    string phonenumber;

public:
    contact() {
        this->name = "Unknown";
        this->surname = "Unknown";
        this->phonenumber = "Unknown";
        this->listno = 0;
    }
    contact(string name, string surname, string phonenumber) {
        this->name = name;
        this->surname = surname;
        this->phonenumber = phonenumber;
    }
    contact(int listno, string name, string surname, string phonenumber) {

        this->name = name;
        this->surname = surname;
        this->listno = listno;
        this->phonenumber = phonenumber;
    }

    friend ostream& operator<< (ostream& out, const contact& con) {
        out << con.listno << '\t' << con.name << '\t' << con.surname << '\t' << con.phonenumber;
        return out;
    }

    friend istream& operator>> (istream& in, contact& con) {
        in >> con.listno >> con.name >> con.surname >> con.phonenumber;
        return in;
    }
};

int main() {

    // Open source file and check, if it could be opened
    if (ifstream pbin("r:\\phoneData2.txt");pbin) {

        // Read complete source file
        std::vector data(std::istream_iterator<contact>(pbin), {});

        // Show data on console
        std::copy(data.begin(), data.end(), std::ostream_iterator<contact>(std::cout, "\n"));
    }
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-10
    • 1970-01-01
    • 2022-01-18
    • 2021-06-13
    相关资源
    最近更新 更多