Как передать спецификатор ширины переменной длины в sscanf? - PullRequest
13 голосов
/ 13 февраля 2009
sscanf(input_str, "%5s", buf); //reads at max 5 characters from input_str to buf

Но мне нужно использовать что-то вроде% MACRO_SIZEs вместо% 5s

Тривиальным решением является создание строки формата для того же

char fmt_str[100] = "";    
snprintf(fmt_str, 100, "%%%ds", MACRO_SIZE);
sscanf(input_str, fmt_str, buf);

Есть ли лучший способ добиться того же?

Ответы [ 3 ]

10 голосов
/ 13 февраля 2009

Как сказал Стефан, но для sscanf() правильнее ответить на вопрос и с немного большим количеством хитростей макросов:

#define MACRO_SIZE 5

#define FORMAT(S) "%" #S "s"
#define RESOLVE(S) FORMAT(S)

char buf[MACRO_SIZE + 1];
sscanf(input_str, RESOLVE(MACRO_SIZE), buf);

При этом используется автоматическое объединение C смежных строковых литералов в C для формирования необходимой строки форматирования во время компиляции. Это работает, только если MACRO_SIZE является макросом препроцессора, а не если это обычная переменная времени выполнения.

Требуется дополнительный вызов макроса через RESOLVE(), поскольку в противном случае аргумент не будет преобразован в его значение #define d, и мы получим строку форматирования "%MACRO_SIZEs", а это не то, что нам нужно .

8 голосов
/ 13 февраля 2009

если ваш MACRO_SIZE является константой во время компиляции, вы можете попробовать это:

#define MACRO_SIZE "5"
snprintf(fmt_str, 100, "%" MACRO_SIZE "s", buf);
1 голос
/ 13 февраля 2009

«Правильное» решение - это то, что вы называете тривиальным. Все эти умные макросы (я бы сам использовал m4) просто сделают ваш код менее управляемым, чем если бы вы просто оставили его как константу.

Проблема, с которой вы здесь столкнулись, состоит в том, что строки не являются структурой данных первого класса в C. Они представляют собой массив байтов. Для этого вам нужно создать массив, который вы хотите получить желаемое значение, и вы создаете этот массив с помощью sprintf. Это не красиво, но это правильно.

Если у вас есть проблемы с производительностью, и вы нашли их здесь, тогда да, исключите вызовы функций. Но если значение для MACRO_SIZE не будет повторяться сто раз или распределяться по нескольким файлам, я бы просто изменил литерал. Макрос - это просто фальшивка с большей гибкостью, использование sprintf на самом деле дает вам гибкость.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...