[英]How to get filename from __FILE__ and concat with __LINE__ at compile time
[英]How can I use the compile time constant __LINE__ in a string?
我可以使用__LINE__
作为方法参数,但我希望在使用字符串的函数中使用它很简单。
比如说我有这个:
11 string myTest()
12 {
13 if(!testCondition)
14 return logError("testcondition failed");
15 }
我希望函数的结果是:
“myTest第14行:testcondition失败”
我怎么写logError? 它是否必须是一个宏观的怪物?
没有理由为此做任何运行时工作:
#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)
如果你像詹姆斯一样酷。
为什么你甚至需要它作为一个字符串? 整数有什么问题? 您可以通过以下两种方式编写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__"
,这不是你想要的。
他的目标是创建一个宏(名为logError ),它将自动包含必要的符号,并在预处理器中执行字符串连接,仅使用字符串文字。
所以,到目前为止,结合基本正确的答案答案,让我们写宏:
#define STRINGIZE_DETAIL(x) #x
#define STRINGIZE(x) STRINGIZE_DETAIL(x)
#define logError(msg) (__FILE__ " line " STRINGIZE(__LINE__) ": " msg)
然后,您可以在任何位置使用此宏来在编译时以字符串文字格式创建一般错误消息代码。
注意:如果您愿意,还可以使用__FUNCTION__
(或等效的,因编译器而异,而不是__FILE__
)来跟踪函数名称而不是文件名。
将数字格式化为字符串的常用选项适用:Boost lexical_cast,ostringstream,sprintf或snprintf等。
以下是我最喜欢的主题之一: http : //www.gotw.ca/publications/mill19.htm
是的,这很难看。 您需要组合宏。 将整数转换为字符串是一个两步的过程 - 这是Boost的实现:
#define BOOST_STRINGIZE(X) BOOST_DO_STRINGIZE(X)
#define BOOST_DO_STRINGIZE(X) #X
现在您可以生成一个字符串:
logError(__FILE__ BOOST_STRINGIZE(__LINE__) "testcondition failed");
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");
sprintf(newStringBuffer, "myTest line %d: testcondition failed\n", __LINE__);
应该做的风格。 我知道有很多方法和方法可以使用C ++字符串库。
您也可以使用strcat()或strncat或任何其他数量的C lib来执行此操作。
cout <<"String" + __LINE__ + " another string"
也会奏效。
试试这个?
string myTest(const int lineno)
{
if(!testCondition)
return logError ("testcondition failed", lineno);
}
void logError (string msg, const int lineno)
{
clog << "line " << lineno << ": " << msg << endl;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.