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

发布于 2024-08-29 03:27:09 字数 329 浏览 8 评论 0原文

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

例如,假设我有这个:

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

我希望函数的结果是:

“myTest 第 14 行:测试条件失败”

如何编写 logError?它一定是某种怪物般的宏吗?

I can use __LINE__ as a method parameter just fine, but I would like an easy way to use it in a function that uses strings.

For instance say I have this:

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

And I want the result of the function to be:

"myTest line 14: testcondition failed"

How can I write logError? Does it have to be some monstrosity of a macro?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

缱倦旧时光 2024-09-05 03:27:10

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

Why do you even need it as a string? What's wrong with an integer? Here are two ways you could write 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);

If you really need the line as a string, you can use the stringizing operator #, but because of the way macros work, you'll need to wrap it in two macros:

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

And now LINE_STRING is a macro that will expand to a string containing the current line number wherever it is expanded. If you only had one level of macros (i.e. if you had #define STRINGIZE(x) #x), then you would get the literal string "__LINE__" every time you expanded it, which is not what you want.

饭团 2024-09-05 03:27:10

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

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

如果您是像詹姆斯这样的酷人。

There's no reason to do any run-time work for this:

#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__) ".");
}

Or:

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

If you're a cool person like James.

嗼ふ静 2024-09-05 03:27:10

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

因此,结合到目前为止基本正确的答案,让我们编写宏:

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

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

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

His goal is to create a macro (named logError) that will automatically include the symbols necessary and do the string concatenation within the preprocessor, only using string literals.

So, combining the basically-correct answers answers thus far, let's write the macro:

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

You can then use this macro anywhere to create a generic error message code in string literal format at compile time.

Note: You can also use __FUNCTION__ (or an equivalent, it varies by compiler) instead of __FILE__, if you prefer, to keep track of the function name instead of the file name.

葬心 2024-09-05 03:27:10

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

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

The usual options for formatting a number into a string apply: Boost lexical_cast, ostringstream, sprintf or snprintf, etc.

Here is one of my favorite links on the topic: http://www.gotw.ca/publications/mill19.htm

魔法唧唧 2024-09-05 03:27:10

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

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

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

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

Yes, it's ugly. You need a combination of macros. Converting an integer to a string is a two-step process - here's Boost's implementation:

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

Now you can generate a string:

logError(__FILE__ BOOST_STRINGIZE(__LINE__) "testcondition failed");   
少女的英雄梦 2024-09-05 03:27:10
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");
std::string logError(const char* file, int line, const char* msg)
{
   std::ostringstream os;
   os << file << ' ' << line << ':' << msg;
   return os.str();
}

Usage:

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

You could then make a macro for this if you were so inclined:

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

And then the usage would be:

return LOG_ERROR("my error message");
帅气称霸 2024-09-05 03:27:10
sprintf(newStringBuffer, "myTest line %d: testcondition failed\n", __LINE__);

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

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

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

也会起作用。

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

should do it c style. I know that there are ways and ways of doing this with the C++ string libraries.

You could also use strcat() or strncat or any other number of C libs to do this.

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

will work as well.

乞讨 2024-09-05 03:27:10

试试这个?

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

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

Try this?

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

void logError (string msg, const int lineno)
{
  clog << "line " << lineno << ": " << msg << endl;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文