在构造函数中打开文件 C++

open file in constructor c++

我试图在构造函数中打开一个文件并从其他函数写入该文件,但文件没有创建。

#include<iostream>
#include<fstream>
#include<cstring>

#define BAD_FILE_NAME_PATTERN "MYFILE_"
#define BAD_FILE_PATH "$HOME/"


class A
{
        private:
        std::ofstream m_badReprtLogFilePtr;
        char *m_badReprtLogFilePtrName;

        public:
        void rechargeEventBadFileHandler();
        void writeToFile();
        A();
};

A::A()
{
        time_t     now = time(0);
        struct tm  tstruct;
        char dateTime[80];
        tstruct = *localtime(&now);
        strftime(dateTime, sizeof(dateTime), "%F_%H%M%S", &tstruct);
        m_badReprtLogFilePtrName = new char[strlen(BAD_FILE_NAME_PATTERN) + sizeof(dateTime)];
        strcpy(m_badReprtLogFilePtrName,BAD_FILE_PATH);
        strcat(m_badReprtLogFilePtrName,BAD_FILE_NAME_PATTERN);
        strncat(m_badReprtLogFilePtrName,dateTime,sizeof(dateTime));
        strcat(m_badReprtLogFilePtrName,".bad");
        std::cout<< "Bad File Name " << m_badReprtLogFilePtrName << std::endl;
        m_badReprtLogFilePtr.open(m_badReprtLogFilePtrName, std::ios::out | std::ios::app);
        if(!m_badReprtLogFilePtr.is_open())
        {
           std::cout<<"Error opening Bad file"<<std::endl;
        }
}

void A::writeToFile()
{
        m_badReprtLogFilePtr << "Writting to BAD FILE"<<std::endl;
}

/*
A::~A()
{
        m_badReprtLogFilePtr.close();
}
*/

int main()
{
        A obj;
        obj.writeToFile();
        return 0;
}

我遇到了问题,问题出在路径上,但是如何解决这个问题

问题在于:

#define BAD_FILE_PATH "$HOME/"

您可以在 Unix 上使用 getenv("HOME") 或在 Windows 上连接 getenv("HOMEDRIVE")getenv("HOMEPATH") 的结果。

例如在 Unix 上

strcpy(m_badReprtLogFilePtrName,getenv("HOME"));
strcat(m_badReprtLogFilePtrName,"/");

需要解决的问题:

  • m_badReprtLogFilePtrName数组的大小错误。 space 仅用于名称和日期(不用于路径、扩展名和空终止字符)。

  • strncat(m_badReprtLogFilePtrName,dateTime,sizeof(dateTime));.

    strncat 的大小参数是目标中已存在的字符串末尾后剩余的 space 量。 您正在使用源大小

  • 存在内存泄漏(析构函数应删除 m_badReprtLogFilePtrName)。

  • 您应该扩展 $HOME 路径 (std::getenv)。要使 getenv 起作用,BAD_FILE_PATH 应定义为:

    #define BAD_FILE_PATH "HOME"
    

    (看看getenv on cppreference.com).

  • 你应该使用std::string

所以像这样:

#include <cstdlib>
#include <cstring>
#include <iostream>
#include <fstream>
#include <string>

#define BAD_FILE_NAME_PATTERN "MYFILE_"
#define BAD_FILE_PATH "HOME"

class A
{
public:
  A();

  // ...

private:
  std::ofstream m_badReprtLogFilePtr;
  std::string m_badReprtLogFilePtrName;
};

A::A()
{
  time_t now = time(0);

  struct tm tstruct;
  char dateTime[80];
  tstruct = *localtime(&now);

  strftime(dateTime, sizeof(dateTime), "%F_%H%M%S", &tstruct);

  char *path = std::getenv(BAD_FILE_PATH);
  if (path)
    m_badReprtLogFilePtrName = std::string(path) + "/";

  m_badReprtLogFilePtrName += BAD_FILE_NAME_PATTERN;
  m_badReprtLogFilePtrName += dateTime;
  m_badReprtLogFilePtrName += ".bad";

  std::cout << "Bad File Name " << m_badReprtLogFilePtrName << "\n";

  m_badReprtLogFilePtr.open(m_badReprtLogFilePtrName.c_str(),
                            std::ios::out | std::ios::app);

  if (!m_badReprtLogFilePtr.is_open())
    std::cout << "Error opening Bad file\n";
}

大概可行(当然还有很多其他需要改进的地方)。

有些地方不对。

C 或 C++ 程序(即使您使用 C++ 编译器构建它,您的大部分代码都使用 C 技术)不解释 $HOME 的含义。这取决于 shell(在 unix 下)并且需要以其他方式扩展(例如使用 getenv())。

分配给m_badReprtLogFilePtrName的字符数等于strlen(BAD_FILE_NAME_PATTERN) + sizeof(dateTime)strcpy()strcat()strncat() 调用可能会将 strlen(BAD_FILE_PATH) + strlen(BAD_FILE_NAME_PATTERN) + min(strlen(dateTime), sizeof dateTime) + strlen(".bad") + 1 个字符写入该缓冲区。奇怪的是,写入的字符数超过了分配的长度,因此结果是未定义的行为。

与其使用运算符 new 手动分配字符数组,不如尝试使用标准 std::string class 来管理字符串。然后当对象被销毁时,字符串将被很好地清理,而不是像现在这样泄漏。

哦:"writing"拼成一个't'.