Я хотел бы вставить произвольные управляющие коды x в строку, но использовать десятичные числа, а не шестнадцатеричные (\ux) или октябрьские (\0x). Если использовать бессмысленный, но сразу понятный пример, я был бы рад иметь макрос, скажем, CC, чтобы я мог формировать строку следующим образом:
// Decimal 10 and 13 are ASCII LF and CR resp.
char mystring[] = "This is line 1" CC(10) CC(13) "This is line 2";
В конечном итоге этот код будет использоваться с другими нестандартными функциями/поведениями на специальном оборудовании.
Нет простого способа сделать это, и вам не следует этого делать. Просто используйте \r\n. Это то, чего ожидают все остальные, и то, что вы увидите в коде других.
Из вашего комментария к ответу ниже: «коды управления в данных дисплея, передаваемых через медленное беспроводное соединение» и на основе приведенной выше строки примера... Посмотрите на «кодирование пары байтов» или, возможно, другую форму сжатия данных (например, : каноническое кодирование Хаффмана на обоих концах.) Кажется, ваша цель — максимизировать пропускную способность при медленном соединении, при котором вычислительная мощность доступна на обоих концах. Четкое изложение потребностей сэкономит время каждого.
Я думаю, вам нужно сделать шаг назад и сосредоточиться на реальной проблеме, которая заключается в отправке строк по медленному беспроводному соединению, а не в создании экзотических escape-последовательностей в строках C. Возможно, вместо этого вам следует спросить, как это сделать лучше всего — это звучит как вопрос для electronics.stackexchange.com . Могу поделиться опытом по этой теме.
Вы приняли ответ от @chqrlie. Просто предложение: вместо того, чтобы создавать самодельный протокол, ограниченный только несколькими SP, расширите его сейчас, включив в него символ, который нужно умножить. Светодиодный дисплей с билетной лентой, который сегодня можно увидеть в торговом центре, включал в себя отрезки нескольких звездочек, а также несколько равных... Сейчас самое время для расползания функций...





Не существует универсального способа сделать это для десятичных чисел, но если количество кодов ограничено, вы можете использовать вставку токенов:
#include <stdio.h>
#define CC_13 "\x0D"
#define CC_10 "\x0A"
#define CONCAT(a, b) a ## b
#define CC(n) CONCAT(CC_, n)
int main(void) {
// Decimal 13 and 10 are ASCII CR and LF resp.
char mystring[] = "This is line 1" CC(13) CC(10) "This is line 2";
// simple macros are supported too
#define CR 13
#define LF 10
printf("%s" CC(CR) CC(LF), mystring);
return 0;
}
Макрос CC можно использовать с числами и простыми макросами, если соответствующий макрос CC_xxx определен как строковая константа. Если это определение отсутствует, вы получите (несколько загадочное) сообщение об ошибке.
Если ваша цель — встроить управляющие байты, вышеописанное подойдет, хотя и немного излишне, поскольку вы можете использовать макросы CC_xxx напрямую.
Судя по дополнительной информации, представленной в комментариях, вы, похоже, хотите встроить двоичные данные в строковые константы в качестве аргументов для встроенных команд, которые сами определены как управляющие коды: было бы обременительно использовать для этого описанный выше трюк и указывать числа вне диапазона 1. .255 может вызвать проблемы, поскольку вы будете вставлять в эти строки нулевые байты, которые могут быть неправильно интерпретированы.
Я предлагаю вам передать эти аргументы в виде строки цифр для анализа во время выполнения внутри целевого устройства. Вот пример:
#define STR(n) #n
#define WHITESPACE(n) "\x1B" STR(n) "F"
char sentence[] = "A big space between here" WHITESPACE(30) "and here."
Вы можете отправить эту строку устройству, и обработчик устройства проанализирует необязательный числовой аргумент между escape-байтом и F (для вперед), чтобы продвинуться вперед на определенное количество пикселей. Использование escape-последовательностей — это всего лишь пример. Вы можете использовать любое соглашение, которое вам больше подходит, но оно позволяет легко создавать строки на стороне сервера с помощью printf:
#include <stdio.h>
int main(void) {
// Slide in a welcome message
for (int i = 0; i < 100; i++) {
char buf[80];
// CR moves the cursor the beginning of the line
// ESC K erases the rest of the line
// ESC n F moves the cursor right by n pixels
snprintf(buf, sizeof buf, "\r\033K\033%dFHello world!", 100 - i);
send_device(buf);
usleep(1000);
}
return 0;
}
К сожалению, мне нужно любое число, поскольку я хотел бы использовать значения в качестве аргументов для управляющих кодов. Например: добавьте к управляющему коду WHITESPACE число, чтобы вставить пробел в несколько пикселей. char sentence[] = "A big space between here" WHITESPACE CC(30) "and here."
@Kay: существуют серьезные ограничения, но я боюсь, что в C нет общего решения. Другой подход — встроить аргумент в ASCII: #define WHITESPACE(n) "\x01(" #n ")", используемый как char sentence[] = "A big space between here" WHITESPACE(30) "and here.", и преобразовать число во время выполнения из цифр вместо чтения байтов.
И здесь я подумал, что поддержка обфускации кода - это что-то ТАК обескураживающее.
@chqrlie Это умная идея - теряет некоторую эффективность, но достигает цели, которую другие здесь отказываются понять. Спасибо.
@Kay То, что вы ищете, можно реализовать, взломав исходный код printf()... Давай, будь нестандартным... Gnu предвидел тебя...
Я работаю над небольшой встроенной системой со светодиодным матричным дисплеем. Здесь нет ничего стандартного, и было бы удобно включать управляющие коды в данные дисплея, передаваемые по медленному беспроводному соединению.
@Kay Не уточняйте свои потребности в комментариях, спрятанных под ответом. Отредактируйте вопрос и опишите свою ситуацию, в которой все ожидают его увидеть. Какой смысл заставлять людей думать, что вы будете использовать printf(), если это неуместно? Трудно уловить то, о чем даже не говорится в вашем вопросе.
@Fe2O3 Точка взята ржавой. Вопрос отредактирован.
Я не уверен, считается ли это разумным решением или нет, но оно должно сработать. Если вам нужно охватить весь 8-битный кодовый набор, может быть много макросов CC_###.
Поскольку не существует способа встраивания экранированных символов в строку с использованием десятичных escape-последовательностей (только восьмеричных или шестнадцатеричных), вы не можете делать то, что хотите (конечно, неразумно).