Я работаю над проектом C++, в котором используется макрос C строковая. На данный момент все довольно просто, но теперь мне нужно добавить строку, содержащую одну кавычку '
. У меня возникли проблемы с тем, чтобы заставить это работать должным образом. Вот минимальная демонстрация проблемы:
#include <stdio.h>
#define myprint(s) \
printf("passed string: %s", #s)
int main ()
{
myprint(print this); // <-- works fine, no quotes.
printf("\n");
//myprint(I'm happy); // <-- ' trips things up
myprint("I'm happy"); // <-- This works, but double
// quotes are in the output.
return 0;
}
В богболте: https://godbolt.org/z/oWGxovnPT
Я хочу myprint
сделать вывод следующим образом:
I'm happy
Может ли кто-нибудь помочь мне сделать это?
Я привел минимальный пример выше. Если это полезно, именное изменение, которое я пытаюсь внести, — это добавить поддержку 418 I'm a teapot
к серверу трафика Apache:
Цитаты — не единственная ваша проблема. Последовательности длиной > 1 пробела будут свернуты в один пробел, символы новой строки удалены, боковые пробелы обрезаны.
Почему myprint
обычная функция не принимает const char*
?
Это не работает так: препроцессор не обрабатывает произвольный набор байтов; скорее, у него есть свой собственный язык вещей («токены»), который он понимает. И I'm
не входит в их число. Язык препроцессора слабо соответствует потребностям «реальных» языков, возникающих в результате предварительной обработки (C, C++ и т. д.).
@Someprogrammerdude: добавлена конкретная проблема, над которой я работаю.
Почему нельзя просто "
-заключить строку в кавычки?
Зачем использовать макрос, а не правильную функцию (и необработанные строковые литералы)? Макросов вообще следует избегать.
@HolyBlackCat: строковая обработка добавит к строке буквальные кавычки "
.
Вы просите, чтобы myprint(print this);
работало (без кавычек) и myprint("I'm happy");
работало (без кавычек)?
«Строковка добавит к строке буквальные "
кавычки». Если вы просто заключаете в кавычки каждую строку, вам не нужна строковая обработка.
'
начинает символьную константу, но она не завершается, что приводит к синтаксической ошибке.
Макросы работают с правильными токенами предварительной обработки, одинарная кавычка без соответствия одинарной кавычке не является допустимым токеном предварительной обработки. Либо вы переименовываете его в I am a teapot
, либо вам придется отказаться от стиля этой функции и добавить еще один макрос, либо написать case
вручную (я, честно говоря, не понимаю необходимости в макросах здесь, это не значит, что они добавляют больше читаемости по сравнению с обычными case 100: return "Continue";
цепочка...)
«Строковка добавит буквальные «кавычки». Да, я говорю, чтобы избавиться от стрингификации и передавать кавычки вручную.
@KerrekSB, спасибо. Похоже, что «ответ» для меня заключается в том, что строковая обработка не будет работать для этого проблемного пространства. Я просто заменю каждое из них строками в кавычках. Не стесняйтесь добавлять ответ, объясняющий это.
Для кода Apache вы можете определить аналогичный макрос, который ожидает строковый аргумент и не преобразует его в строку.
Если вы хотите сохранить макросы и добиться хотя бы небрежного соответствия RFC 2324, вы можете выбрать какой-нибудь похожий символ, например обратный апостроф.
На самом деле это выполнимо, пусть и не портативно и, честно говоря, довольно некрасиво. Попробуйте myprint(I\x27m happy)
.
Вы не можете. Решение состоит в том, чтобы удалить стрингификацию препроцессора.
В вашем реальном случае использования это просто бесплатный макрос. Даже печатать не спасает, потому что HTTP_STATUS_ENTRY
такое длинное имя.
То, что вы хотите, это
case 418: return "I'm a teapot";
Но пока вы там, подставьте все остальные дела.
Спасибо: github.com/apache/trafficserver/pull/11273
То, о чем вы просите, сделать невозможно: препроцессор не обрабатывает произвольные входные символы, как вы могли ожидать. Скорее, у него есть свой собственный язык (например, для C++ см. [cpp]; C имеет аналогичную спецификацию), где единицами обработки являются «токены» (ищите создание грамматики токена предварительной обработки).
«Токены», которые обрабатывает препроцессор, соответствуют языку, который он в конечном итоге обслуживает. То есть токены препроцессора в некоторой степени ориентированы на токены «уровня C++», но отличаются от них, получаемые при создании грамматики токена в [lex.token].
Последовательность символов I'm
не является допустимым токеном предварительной обработки.
Зачем тебе это нужно? Какова основная проблема, которую предполагается решить? И обратите внимание, что использование макросов в C++ в целом крайне не рекомендуется, и что хотя C и C++ используют один и тот же препроцессор, это два разных языка, и тегирование обоих также не рекомендуется. Пожалуйста, отмечайте только тот язык, на котором вы на самом деле программируете.