Как я могу использовать время компиляции, постоянное __ СТРОКА __ в строке?

Я могу использовать __LINE__ как параметр метода очень хорошо, но я хотел бы простой способ использовать его в функции, которая использует строки.

Например, скажите, что у меня есть это:

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

И я хочу, чтобы результат функции был:

"строка myTest 14: testcondition перестал работать"

Как я могу записать logError? Это должно быть некоторое чудовище макроса?

16
задан Brian Tompsett - 汤莱恩 13 June 2016 в 14:40
поделиться

8 ответов

Зачем он вообще нужен в виде струны? Что не так с целым числом? Вот два способа записать 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 __» каждый раз, когда расширяли его. , а это не то, что вам нужно.

29
ответ дан 30 November 2019 в 15:08
поделиться

Нет причин выполнять какую-либо работу во время выполнения для этого:

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

Если ты такой крутой человек, как Джеймс.

29
ответ дан 30 November 2019 в 15:08
поделиться

Да, это некрасиво. Вам нужна комбинация макросов. Преобразование целого числа в строку - это двухэтапный процесс - здесь реализация Boost:

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

Теперь вы можете сгенерировать строку:

logError(__FILE__ BOOST_STRINGIZE(__LINE__) "testcondition failed");   
3
ответ дан 30 November 2019 в 15:08
поделиться

Попробовать?

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

void logError (string msg, const int lineno)
{
  clog << "line " << lineno << ": " << msg << endl;
}
-2
ответ дан 30 November 2019 в 15:08
поделиться
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");
1
ответ дан 30 November 2019 в 15:08
поделиться

Применяются обычные варианты форматирования числа в строку: Boost lexical_cast, ostringstream, sprintf или snprintf и т. Д.

Вот одна из моих любимых ссылок по теме: http: //www.gotw .ca / публикации / mill19.htm

3
ответ дан 30 November 2019 в 15:08
поделиться
sprintf(newStringBuffer, "myTest line %d: testcondition failed\n", __LINE__);

должен делать это в стиле c. Я знаю, что есть способы и способы сделать это с помощью строковых библиотек C ++.

Вы также можете использовать strcat () или strncat или любое другое количество библиотек C для этого.

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

также будет работать.

0
ответ дан 30 November 2019 в 15:08
поделиться

Его цель - создать макрос (с именем logError ), который будет автоматически включать необходимые символы и выполнять конкатенацию строк в препроцессоре. , используя только строковые литералы.

Итак, объединив до сих пор в основном правильные ответы, давайте напишем макрос:

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

Затем вы можете использовать этот макрос где угодно, чтобы создать общий код сообщения об ошибке в формате строкового литерала во время компиляции.

Примечание. Вы также можете использовать __ FUNCTION __ (или эквивалент, зависит от компилятора) вместо __ FILE __ , если хотите, чтобы отслеживать имя функции вместо имя файла.

9
ответ дан 30 November 2019 в 15:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: