指向文件的指针的C++矢量

C++ Vector of pointers to files

本文关键字:C++ 矢量 指针 文件      更新时间:2023-10-16

我目前正在尝试从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);
}

EDIT:添加了完整代码+FileInput类

EDIT2:添加了内核功能

第三版:我尝试用&(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,zkouska 2。。。不应写入输出。

&(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

更换

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

带有

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

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

关于您的预期输出。。。好吧,如果你打开一个文件,读一行,在下一个循环中,你用相同的文件描述符读另一行,你一定会读下一行,除非你像这里解释的那样用fileStream->Seek( 0, SeekOrigin::Begin );重置流。