错误报告仅一次

Error reporting only once

本文关键字:一次 报告 错误      更新时间:2023-10-16

我正在编写一些处理大量数据的代码。当一个错误发生时,通常会发生多次错误,所以我只想报告一次。我遇到的问题是,我想要单独的错误消息。在C中,我会使用一个带有可变参数的方法,当然这不是真正的类型安全的,所以我想知道如何在C++中使用类型安全输出来实现同样的效果。我知道我可以stringstream并创建单独的字符串,但这意味着我必须创建完整的错误消息,即使它被丢弃了,因为它已经打印出来了,字符串流也不太快。

所以目前我使用这样的代码:

    std::string key = "BT:EMPTY";
    if(mErrorReport.find(key) == mErrorReport.end())
    {
        std::cerr << "ERROR [" << Name<< "] Type is empty! " << std::endl;
        mErrorReport.insert(key);
    }
    std::string key = "UI:"+Unitcode;
    if(mErrorReport.find(key) == mErrorReport.end())
    {
        std::cerr << "ERROR [" << Name<< "] Room with the id " << Unitcode << " doesn't exist! " << std::endl;
        mErrorReport.insert(key);
    }
    ...

在C中,我会写一个这样的变差函数:

 void ErrorLog(const char *key, int nLogLevel, const char fmt, ...)
 {
      // Check if this error was already reported before.
      if(mErrorLog.find(key) == mErrorLog.end())
      {
          fprintf(stderr, fmt, ...);
          mErrorLog.insert(key);
      }
 }

所以我想知道是否有这样的最佳实践。

为什么不直接使用

void ErrorLog(const std::string& key, const std::string& name, const std::string& what)
{
    if (mErrorLog.find(key) == mErrorLog.end())
    {
        std::cerr << "ERROR[" << name << "]" << what << std::endl;
        mErrorLog.insert(key);
    }
}

并称之为

ErrorLog("BT:EMPTY", Name, "Type is empty!");
ErrorLog("UI:" + Unitcode, Name, std::string("Room with the id ") + Unitcode + " doesn't exist!");

如果Name没有更改,您可以删除该参数并将其添加到std::err调用中。

更新:替代解决方案

class ErrorLogWriter
{
public:
    ErrorLogWriter(const std::string& name, const std::string& key, std::set<std::string>& log)
        :m_name(name)
        , m_key(key)
        , m_log(log)
    {}
    ErrorLogWriter& operator<<(const std::string& msg)
    {
        if (m_log.find(m_key) == m_log.end())
        {
            std::cerr << "ERROR[" << m_name << "]" << msg << std::endl;
            m_log.insert(m_key);
        }
        return *this;
    }
private:
    std::string m_name;
    std::string m_key;
    std::set<std::string>& m_log;
};
class ErrorLog
{
public:
    ErrorLog(const std::string& name, std::set<std::string>& log)
        :m_name(name)
        ,m_log(log)
    {}
    ErrorLogWriter operator()(const std::string& key)
    {
        return ErrorLogWriter(m_name, key, m_log);
    }
private:
    std::string m_name;
    std::set<std::string>& m_log;
};
int main()
{
    std::string Name = "NAME";
    std::string Unitcode = "UNITCODE";
    std::set<std::string> mErrorLog;
    ErrorLog log(Name, mErrorLog);
    log("BT:EMPTY") << "Type is empty!";
    log("UI:" + Unitcode) << "Room with the id " << Unitcode << " doesn't exist!";
}