如何在字符串中使用编译时常量__LINE__?

时间:2010-04-19 20:56:19

标签: c++ testing c-preprocessor

我可以使用__LINE__作为方法参数,但我希望在使用字符串的函数中使用它是一种简单的方法。

例如说我有这个:

11    string myTest()
12    {
13     if(!testCondition)
14       return logError("testcondition failed");
15    }

我希望函数的结果是:

  

“myTest第14行:testcondition失败”

如何编写logError?它是否必须是一个宏观的怪物?

8 个答案:

答案 0 :(得分:29)

为什么你甚至需要它作为一个字符串?整数有什么问题?您可以通过以下两种方式撰写logError()

#define logError(str) fprintf(stderr, "%s line %d: %s\n", __FILE__, __LINE__, str)

// Or, forward to a more powerful function
#define logError(str) logError2(__FILE__, __LINE__, str)
void logError2(const char *file, int line, const char *str);

如果您确实需要将该行作为字符串,则可以使用字符串化运算符#,但由于宏的工作方式,您需要将其包装在两个宏中:

#define STRINGIZE(x) STRINGIZE2(x)
#define STRINGIZE2(x) #x
#define LINE_STRING STRINGIZE(__LINE__)

现在LINE_STRING是一个宏,它将扩展为包含当前行号的字符串,无论它在哪里展开。如果你只有一个级别的宏(即如果你有#define STRINGIZE(x) #x),那么每次展开它时你都会得到文字字符串"__LINE__",这不是你想要的。

答案 1 :(得分:28)

没有理由为此做任何运行时工作:

#include <iostream>

// two macros ensures any macro passed will
// be expanded before being stringified
#define STRINGIZE_DETAIL(x) #x
#define STRINGIZE(x) STRINGIZE_DETAIL(x)

// test
void print(const char* pStr)
{
    std::cout << pStr << std::endl;
}

int main(void)
{
    // adjacent strings are concatenated
    print("This is on line #" STRINGIZE(__LINE__) ".");
}

或者:

#define STOP_HAMMER_TIME(x) #x
#define STRINGIFICATE(x) STOP_HAMMER_TIME(x)

如果你像詹姆斯一样很酷。

答案 2 :(得分:8)

他的目标是创建一个宏(名为 logError ),该宏将自动包含必要的符号,并在预处理器中执行字符串连接,仅使用字符串文字。

所以,到目前为止,结合基本正确的答案答案,让我们写下宏:

#define STRINGIZE_DETAIL(x) #x
#define STRINGIZE(x) STRINGIZE_DETAIL(x)
#define logError(msg) (__FILE__ " line " STRINGIZE(__LINE__) ": " msg)

然后,您可以在任何位置使用此宏在编译时以字符串文字格式创建通用错误消息代码。

注意:如果您愿意,也可以使用__FUNCTION__(或等效的,因编译器而异)而不是__FILE__来跟踪函数名称而不是文件名。

答案 3 :(得分:3)

将数字格式化为字符串的常用选项适用:Boost lexical_cast,ostringstream,sprintf或snprintf等。

以下是我最喜欢的主题之一:http://www.gotw.ca/publications/mill19.htm

答案 4 :(得分:3)

是的,这很难看。您需要组合宏。将整数转换为字符串是一个两步的过程 - 这是Boost的实现:

#define BOOST_STRINGIZE(X) BOOST_DO_STRINGIZE(X)
#define BOOST_DO_STRINGIZE(X) #X

现在你可以生成一个字符串:

logError(__FILE__ BOOST_STRINGIZE(__LINE__) "testcondition failed");   

答案 5 :(得分:1)

std::string logError(const char* file, int line, const char* msg)
{
   std::ostringstream os;
   os << file << ' ' << line << ':' << msg;
   return os.str();
}

用法:

return logError(__FILE__, __LINE__, "my error message");

如果您愿意,可以为此制作一个宏:

#define LOG_ERROR(x) logError(__FILE__, __LINE__, (x))

然后用法是:

return LOG_ERROR("my error message");

答案 6 :(得分:0)

sprintf(newStringBuffer, "myTest line %d: testcondition failed\n", __LINE__);

应该做c风格。我知道有很多方法和方法可以使用C ++字符串库。

您也可以使用strcat()或strncat或任何其他数量的C lib来执行此操作。

cout <<"String" + __LINE__ + " another string" 

也可以。

答案 7 :(得分:-2)

试试这个?

string myTest(const int lineno)
{
  if(!testCondition)
    return logError ("testcondition failed", lineno);
}

void logError (string msg, const int lineno)
{
  clog << "line " << lineno << ": " << msg << endl;
}