Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 修改日志类以接受字符串-C++;_C++_Io_Logging - Fatal编程技术网

C++ 修改日志类以接受字符串-C++;

C++ 修改日志类以接受字符串-C++;,c++,io,logging,C++,Io,Logging,我试图修改日志类以接受字符串中的变量。例如,如果我想输出一个区域中有7名玩家 以下是我的写入日志功能: void Log::writeSuccess(string text,...) { // Write the sucessfull operation to the logfile logfile << "<---> " << text << endl; } 它只会输出到文件:该区域有%i名玩家 有办法解决这个问题吗?我想知道你

我试图修改日志类以接受字符串中的变量。例如,如果我想输出一个区域中有7名玩家

以下是我的写入日志功能:

void Log::writeSuccess(string text,...)
{
    // Write the sucessfull operation to the logfile
    logfile << "<---> " << text << endl;
}
它只会输出到文件:该区域有%i名玩家


有办法解决这个问题吗?

我想知道你的程序到底是怎么编译的?! 您使用两个参数调用
writeSuccess
,而它被声明为只接受一个参数


您应该查看标准库。它允许您处理不同数量的参数。

如果您不能或不想使用boost:

void Log::writeSuccess(const char* const fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    char buff[1024];
    vsnprintf(buff, sizeof(buff), fmt, ap);
    logfile << buff;
}

信息。注意:这是一个警告,不是编译错误。如果忽略警告,那就是您的问题。:)

使用
printf
样式的格式字符串的问题是这些字符串

  • 取决于所提供参数的类型,以及
  • 取决于所提供参数的顺序 写这些行时,不仅容易出错。根据我的经验,在积极维护和扩展的软件中,参数的类型和顺序很容易改变,而且与最初编写代码时相比,更难使格式字符串与以后应用的更改保持同步

    需要“<强”>手动保存参数类型为同步< /强>,格式字符串在C++中很容易解决,<强>流已在25年前证明。strong>甚至可以将格式字符串与类型安全性结合起来

    我看到的一些日志库采用了一种不同的方法来解决这两个问题:它们使用一种语法,您可以通过使用参数的名称来指定要在字符串中的特定位置插入的参数,通过在插入参数之前将所有参数单独转换为字符串,您无需再考虑参数的类型

    log( "i now has the value of @(i), current size is @(x.get_size(y))", 
         LOG_PARAM(i) + LOG_PARAM(x.get_size(y)) );
    

    <如果你不想使用StDARG.H,在C++ IMO中看起来不好,你可以这样做。请记住,尽管这是一个很小的类(您可以添加到其中以获得更好的日志记录),但这并不是最有效的方法

    #include <iostream>
    #include <sstream>
    
    
    class Log
    {
    public:
        Log() : os()
        {
    
        }
    
        ~Log()
        {
            fprintf(stderr, "%s\n", os.str().c_str());
        }
    
        template<typename T>
        std::ostringstream &operator<<(const T &t)
        {
            os << "Log file - " << t;
            return os;
        }
    
    private:
        std::ostringstream os;
    };
    
    int main(int argc, char *argv[])
    {
        //usage
        for (int i = 0; i < 10; ++i)
            Log() << "Hello world " << i;
    
        return 0;
    }
    
    #包括
    #包括
    类日志
    {
    公众:
    Log():os()
    {
    }
    ~Log()
    {
    fprintf(stderr,“%s\n”,os.str().c_str());
    }
    模板
    
    std::ostringstream&Operator我很惊讶这不会导致编译器错误,因为您传递的参数数量错误。您的问题的答案可能是boost.log或boost.format,或者如果您有C++0x,可能是可变模板。您希望发生奇迹吗?这是一个日志库,您通过价值?@sbi不要表现得很惊讶,请向我解释为什么这是不明智的…@Publeus:无意冒犯,但你为什么要在不知道传递论点的情况下这样做?这是家庭作业吗?一份工作吗?一个爱好项目吗?我打赌他还没有编译:)对不起,是在摆弄它。我恢复了我之前编译的东西泰德。我不明白为什么这仍然会被提高投票率。它显然不再适用于问题中的代码。你们在投票前都不看它吗?这是printf之类使用的解决方案,但它是出了名的类型不安全。IMO boost格式更好。数字会让小狗哭出他们有多糟糕。永远不要写c红色警报,红色警报,魔法数字在一个简单的示例中,“魔法数字”指的是
    charbuff[1024]中的1024。这可以在字符串中输出硬编码的最大长度,但是没有什么可以阻止更长的字符串作为参数传递。<代码> VSNPROTFF < /C>不是C++安全的,不应该在C++中使用,我们有更好的替代方案。对他们来说是一回事,但说明完全错误的事情是另一回事。你应该计算所需的空间并动态分配,然后输出。
    
    log( "i now has the value of @(i), current size is @(x.get_size(y))", 
         LOG_PARAM(i) + LOG_PARAM(x.get_size(y)) );
    
    #include <iostream>
    #include <sstream>
    
    
    class Log
    {
    public:
        Log() : os()
        {
    
        }
    
        ~Log()
        {
            fprintf(stderr, "%s\n", os.str().c_str());
        }
    
        template<typename T>
        std::ostringstream &operator<<(const T &t)
        {
            os << "Log file - " << t;
            return os;
        }
    
    private:
        std::ostringstream os;
    };
    
    int main(int argc, char *argv[])
    {
        //usage
        for (int i = 0; i < 10; ++i)
            Log() << "Hello world " << i;
    
        return 0;
    }