Как использовать константу времени компиляции __LINE__ в строке?
Я могу использовать __LINE__
как параметр метода просто отлично, но мне бы хотелось, чтобы он легко использовал его в функции, которая использует строки.
Например, у меня есть это:
11 string myTest()
12 {
13 if(!testCondition)
14 return logError("testcondition failed");
15 }
И я хочу, чтобы результатом функции было:
"строка myTest 14: не удалось выполнить тестовое условие"
Как написать logError? Должно ли это быть какой-то чудовищностью макроса?
Ответы
Ответ 1
Зачем вам это нужно как строка? Что не так с целым? Вот два способа написать 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__"
каждый раз, когда вы ее расширили, но это не то, что вы хотите.
Ответ 2
Нет причин для выполнения этой работы во время выполнения:
#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)
Если ты классный человек, как Джеймс.
Ответ 3
Его целью является создание макроса (с именем logError), который будет автоматически включать необходимые символы и выполнять конкатенацию строк в препроцессоре, используя только строковые литералы.
Итак, комбинируя в основном правильные ответы на ответы до сих пор, напишите макрос:
#define STRINGIZE_DETAIL(x) #x
#define STRINGIZE(x) STRINGIZE_DETAIL(x)
#define logError(msg) (__FILE__ " line " STRINGIZE(__LINE__) ": " msg)
Затем вы можете использовать этот макрос в любом месте для создания общего кода сообщения об ошибке в строковом литерале во время компиляции.
Примечание. Вы также можете использовать __FUNCTION__
(или эквивалент, он зависит от компилятора) вместо __FILE__
, если хотите, для отслеживания имени функции вместо имени файла.
Ответ 4
Применяются обычные параметры форматирования числа в строке: Boost lexical_cast, ostringstream, sprintf или snprintf и т.д.
Вот одна из моих любимых ссылок на эту тему: http://www.gotw.ca/publications/mill19.htm
Ответ 5
Да, это уродливо. Вам нужна комбинация макросов. Преобразование целого числа в строку - это двухэтапный процесс - здесь реализация Boost:
#define BOOST_STRINGIZE(X) BOOST_DO_STRINGIZE(X)
#define BOOST_DO_STRINGIZE(X) #X
Теперь вы можете сгенерировать строку:
logError(__FILE__ BOOST_STRINGIZE(__LINE__) "testcondition failed");
Ответ 6
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");
Ответ 7
sprintf(newStringBuffer, "myTest line %d: testcondition failed\n", __LINE__);
должен сделать это c style. Я знаю, что есть способы и способы сделать это с помощью строковых библиотек С++.
Вы также можете использовать strcat() или strncat или любое другое число C libs для этого.
cout <<"String" + __LINE__ + " another string"
также будет работать.
Ответ 8
Попробуйте это?
string myTest(const int lineno)
{
if(!testCondition)
return logError ("testcondition failed", lineno);
}
void logError (string msg, const int lineno)
{
clog << "line " << lineno << ": " << msg << endl;
}