【问题标题】:C++ Vector of pointers to files指向文件的指针的 C++ 向量
【发布时间】:2016-03-05 10:36:51
【问题描述】:

我目前正在尝试从 vector 访问指向文件的指针。我面临的问题是我无法单独解决的问题是,我正在用最后创建的向量重写已经存储的指针(或者至少看起来如此)。 因此,如果我尝试访问它们,则只有最后一个可用。 也许有一个我看不到的简单解决方案,但我已经花了三天时间试图找出我做错了什么(我已经完全从头开始重写了两次代码)。

int cnt = 0;
vector<AbstractInput*> abstractFiles;
while (cnt < 6) {
    string path = "D:/tempSort_" + to_string(cnt) + ".txt";
    ofstream fileOutput(path);
    if (!fileOutput)
    {
        // todo error 
        exit(1);
    }
    AbstractOutput* tmp = new FileOutput(fileOutput, kernel);
    tmp->WriteLine(to_string(cnt) + " zkouska");
    tmp->WriteLine(to_string(cnt) + " zkouska2");
    tmp->WriteLine(to_string(cnt) + " zkouska3");
    tmp->Close();
    delete(tmp);

    ifstream fileInput(path);
    if (!fileInput)
    {
        exit(1);
    }       

    abstractFiles.push_back(&(FileInput(fileInput, kernel)));

    output->WriteLine("CNT = " + to_string(cnt));
    for (AbstractInput* it : abstractFiles)
    {
        bool succes;
        output->WriteLine((it)->ReadLine(succes));
    }       


    cnt++;

} 

文件输入:

using namespace std;

class FileInput : public AbstractInput
{
    using AbstractInput::AbstractInput;


private:
    ifstream& inputFile;
    bool closed;

public:
    FileInput::FileInput(ifstream& inputFile, Kernel* kernel) : 

    AbstractInput(kernel), inputFile{ inputFile }, closed(false)
    {   

    }

    int FileInput::Close()
    {
        inputFile.close();
        closed = true;
        return 0;
    }

    bool FileInput::HasNext()
    {
        return !closed;
    }
    string FileInput::Read()
    {
        return GetKernel()->ReadFromKeyboard();
    }
    string FileInput::ReadLine(bool& success)
    {
        string line = GetKernel()->ReadLineFromFile(inputFile, success);

        closed = !success;
        return line;    
    }

};

内核函数:

string Kernel::ReadLine(istream& stream, bool& success)
{
    string line;
    if (getline(stream, line))
    {
        success = true;
        return line;
    }
    success = false;
    return "";
}

string Kernel::ReadLineFromFile(ifstream& stream, bool& success)
{   
    return ReadLine(stream, success);
}

编辑:添加整个代码 + FileInput 类

EDIT2:添加内核函数

EDIT3:我尝试使用&amp;(FileInput(inputFile, kernel))new FileInput(inputFile, kernel) 创建新指针。两者都以相同的结果结束 -> 只有最后添加的指针有效,其他指针指向同一个文件。

EDIT4:当前输出 + 预期输出

当前版本的输出:

CNT = 0
0 zkouska
CNT = 1
1 zkouska
1 zkouska2
CNT = 2
2 zkouska
2 zkouska2
2 zkouska3
CNT = 3
3 zkouska
3 zkouska2
3 zkouska3

CNT = 4
4 zkouska
4 zkouska2
4 zkouska3


CNT = 5
5 zkouska
5 zkouska2
5 zkouska3



.

预期结果是:

CNT = 0
0 zkouska
CNT = 1
0 zkouska
1 zkouska
CNT = 2
0 zkouska
1 zkouska
2 zkouska

还有更多……因为我只读取每个文件的第一行,所以 zkouska1、zkouska2、……不应该被写入输出。

【问题讨论】:

  • 您正在获取一个临时地址,该地址将立即超出范围,因此您的向量有一个悬空指针。
  • 附加问题:似乎在(while 循环的)每个循环中,您总是打开同一个文件,因为变量 path 没有改变。
  • 你能编辑你的问题并附加FileInput的定义吗?
  • 对不起,我没有发布整个代码,我会编辑它。
  • 您仍然缺少一些代码。什么是kernel

标签: c++ pointers c++11 vector


【解决方案1】:

&amp;(FileInput(fileInput)) 是保存对变量的引用的临时地址。

  1. 用悬空指针填充向量。
  2. 您的类包含对在循环结束时超出范围的变量的引用。

您想在堆上创建非临时对象并存储它们的地址。

auto fileInput = new std::ifstream(path);
abstractFiles.push_back(new FileInput(*fileInput));

记得在之后正确删除这些指针(ifstream 和 FileInput)。

注意:for 循环应该做什么?在每次 while 迭代中,您从 abstractFiles 的每个有效条目中读取一行。

我期望的输出是:

CNT = 0
0 zkouska
CNT = 1
0 zkouska2
1 zkouska
CNT = 2
0 zkouska3
1 zkouska2
2 zkouska
CNT = 3

1 zkouska3
2 zkouska2
3 zkouska
CNT = 4


2 zkouska3
3 zkouska2
4 zkouska

【讨论】:

  • 在我发布这个问题之前,我尝试用new FileInput(fileInput) 添加指针,结果同样失败,我也应该这么写。
  • 了解FileInput 类对ifstream 对象的作用也很重要,因为它超出了范围。
  • @Chlebnik 所以你需要添加一个完整的程序来显示testpathFileInput 的定义会发生什么。
  • 添加了其余代码 + 输出示例。仍然缺少答案:-/
  • @Chlebnik 您的fileInput 是当前循环迭代的本地。您不能存储任何持有对该变量的引用的对象,并期望它们在下一次迭代中可以访问。
【解决方案2】:

替换

ifstream fileInput(path);
if (!fileInput)
{
    exit(1);
}       

std::shared_ptr<ifstream> fileInput(new ifstream(path) );
if (*fileInput)
{
    exit(1);
}       

然后将ifstream&amp; 的所有其他实例替换为std::shared_ptr&lt;ifstream&gt;(当实际使用流从文件中读取时,您还必须将stream 引用为*stream)。这将防止您的文件流对象超出范围,并在程序结束时负责销毁和释放您的对象。 (只要您注意销毁 AbstractFiles 向量中的对象;事实上,您应该考虑在那里使用unique_ptr

关于您的预期输出...好吧,如果您打开一个文件,读取一行,然后在下一个循环中读取具有相同文件描述符的另一行,则必须读取后续行,除非您重置流fileStream-&gt;Seek( 0, SeekOrigin::Begin ); 之类的东西,正如 here 所解释的那样。

【讨论】:

  • 是的,成功了!非常感谢,至少可以解决我的问题:)
  • @Chlebnik 阅读我的答案也可以解决问题。 :)
  • @Pixelchemist 好吧,现在你提到它,那是因为我看错了:-X。我没有注意到auto fileInput = new std::ifstream(path); 部分,并认为您只是建议我使用new 指向FileInput 的指针创建。我的错,我很抱歉。
  • @Pixelchemist 使用您提出的方法,将fileInput 指针存储在局部变量中,您打算如何删除您创建的对象?考虑到 OP 是初学者,我认为给他指出智能指针的方向很重要。
  • @Antonio 例如在~FileInput() 中使用delete std::addressof(inputFile);
猜你喜欢
  • 2019-09-10
  • 2011-08-04
  • 1970-01-01
  • 2020-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-06
  • 2017-04-27
相关资源
最近更新 更多