2010-04-19 96 views
13

我可以使用__LINE__作为方法参数,但我想要一个简单的方法在使用字符串的函数中使用它。如何在字符串中使用编译时间常量__LINE__?

例如说我有这样的:

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

而且我想要的函数的结果是:

“MYTEST线14:testcondition失败”

如何我可以写logError吗?它是否必须是一个宏观的怪物?

回答

27

为什么你甚至需要它作为一个字符串?整数有什么问题?这里有两种方法,你可以写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__",这不是您想要的。

+3

虽然这是一个旧的线程,但您希望它作为字符串的原因是您不能使用fprintf()的实例。一个这样的地方是在一个信号处理程序中,因为在write()时,fprintf()在信号处理程序中不安全。 – Bob9630 2014-04-11 18:43:20

3

格式化一个数字,字符串通常选项适用:升压lexical_cast的,ostringstream,sprintf的或的snprintf等

下面是关于该主题的我最喜欢的环节之一:http://www.gotw.ca/publications/mill19.htm

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

应该做c风格。我知道用C++字符串库做这件事的方式和方法。

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

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

也可以工作。

+0

目标不是输出到屏幕,而是返回一个字符串,其中写入数据。 – 2010-04-19 21:04:33

+1

为什么不只是'cout <<“String”<< __LINE__ <<“另一个字符串”;'?无需铸造或连接。 – 2010-04-19 21:04:37

+0

@John:从你的问题不清楚。 – 2010-04-19 21:05:43

2

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

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

现在,您可以生成的字符串:

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

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

#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) 

如果你是一个像詹姆斯一样酷的人。

+7

或者,如果你鄙视'STRINGIZE'这个词,你可以使用'STRINGIFICATE'并享受同事的奇怪目光。 – 2010-04-19 21:15:25

+2

@詹姆斯:正式指出。 – GManNickG 2010-04-19 21:23:59

+1

我使用“stringify”这个词:) :) – 2014-03-11 03:34:02

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"); 
-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; 
} 
+0

您的logError不会返回一个字符串。 – 2010-04-19 21:48:17

6

他的目标是创建一个宏(名为LOGERROR),将自动包含符号必要做预处理中的字符串连接,只用字符串文字。

因此,结合基本-正确答案回答迄今为止,让我们写的宏:

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

然后,您可以使用此宏随时随地在编译时创建的字符串文字格式的一般错误消息代码。

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

相关问题