Препроцессор макросов C для включения числа в строку

Я хотел бы вставить произвольные управляющие коды 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";

В конечном итоге этот код будет использоваться с другими нестандартными функциями/поведениями на специальном оборудовании.

Поскольку не существует способа встраивания экранированных символов в строку с использованием десятичных escape-последовательностей (только восьмеричных или шестнадцатеричных), вы не можете делать то, что хотите (конечно, неразумно).

Jonathan Leffler 26.09.2023 05:47

Нет простого способа сделать это, и вам не следует этого делать. Просто используйте \r\n. Это то, чего ожидают все остальные, и то, что вы увидите в коде других.

HolyBlackCat 26.09.2023 06:07

Из вашего комментария к ответу ниже: «коды управления в данных дисплея, передаваемых через медленное беспроводное соединение» и на основе приведенной выше строки примера... Посмотрите на «кодирование пары байтов» или, возможно, другую форму сжатия данных (например, : каноническое кодирование Хаффмана на обоих концах.) Кажется, ваша цель — максимизировать пропускную способность при медленном соединении, при котором вычислительная мощность доступна на обоих концах. Четкое изложение потребностей сэкономит время каждого.

Fe2O3 26.09.2023 07:57

Я думаю, вам нужно сделать шаг назад и сосредоточиться на реальной проблеме, которая заключается в отправке строк по медленному беспроводному соединению, а не в создании экзотических escape-последовательностей в строках C. Возможно, вместо этого вам следует спросить, как это сделать лучше всего — это звучит как вопрос для electronics.stackexchange.com . Могу поделиться опытом по этой теме.

Lundin 26.09.2023 09:03

Вы приняли ответ от @chqrlie. Просто предложение: вместо того, чтобы создавать самодельный протокол, ограниченный только несколькими SP, расширите его сейчас, включив в него символ, который нужно умножить. Светодиодный дисплей с билетной лентой, который сегодня можно увидеть в торговом центре, включал в себя отрезки нескольких звездочек, а также несколько равных... Сейчас самое время для расползания функций...

Fe2O3 26.09.2023 09:18
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
98
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Не существует универсального способа сделать это для десятичных чисел, но если количество кодов ограничено, вы можете использовать вставку токенов:

#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 26.09.2023 06:11

@Kay: существуют серьезные ограничения, но я боюсь, что в C нет общего решения. Другой подход — встроить аргумент в ASCII: #define WHITESPACE(n) "\x01(" #n ")", используемый как char sentence[] = "A big space between here" WHITESPACE(30) "and here.", и преобразовать число во время выполнения из цифр вместо чтения байтов.

chqrlie 26.09.2023 06:17

И здесь я подумал, что поддержка обфускации кода - это что-то ТАК обескураживающее.

Fe2O3 26.09.2023 06:21

@chqrlie Это умная идея - теряет некоторую эффективность, но достигает цели, которую другие здесь отказываются понять. Спасибо.

Kay 26.09.2023 06:32

@Kay То, что вы ищете, можно реализовать, взломав исходный код printf()... Давай, будь нестандартным... Gnu предвидел тебя...

Fe2O3 26.09.2023 06:39

Я работаю над небольшой встроенной системой со светодиодным матричным дисплеем. Здесь нет ничего стандартного, и было бы удобно включать управляющие коды в данные дисплея, передаваемые по медленному беспроводному соединению.

Kay 26.09.2023 06:54

@Kay Не уточняйте свои потребности в комментариях, спрятанных под ответом. Отредактируйте вопрос и опишите свою ситуацию, в которой все ожидают его увидеть. Какой смысл заставлять людей думать, что вы будете использовать printf(), если это неуместно? Трудно уловить то, о чем даже не говорится в вашем вопросе.

Fe2O3 26.09.2023 07:11

@Fe2O3 Точка взята ржавой. Вопрос отредактирован.

Kay 26.09.2023 07:25

Я не уверен, считается ли это разумным решением или нет, но оно должно сработать. Если вам нужно охватить весь 8-битный кодовый набор, может быть много макросов CC_###.

Jonathan Leffler 26.09.2023 07:38

Другие вопросы по теме