Как передать спецификатор ширины переменной длины в sscanf?

Если T ограничено Comparable<? super T>, то решение @glglgl, приведенное выше, является достаточно хорошим, так как кажется, что любой из типов, которые T может принять на основании вопроса, является совместимым.

Однако, если T не ограничен таким образом, и вы не можете или не хотите изменить это, решение будет несколько более общим и потребует, чтобы вызывающий код явно предоставил компаратор для [ 115] элементов в качестве второго аргумента для Comparator.comparing

static <T> void sortNeightbours(Collection<Vertex<? extends T>> neighbours, Comparator<? super T> elementComparator) {
    neighbours.sort(Comparator.comparing(Vertex::getElement, elementComparator);
} 

Вам не нужно определять отдельный (статический) метод, для этого он может быть встроен, если хотите.

Для вершины, тип элемента которой сопоставим, как Integer, Double или String, вызывающий код будет таким же:

   List<Vertex<Integer>> ints = ...;
   List<Vertex<Double>> dbls = ...;
   List<Vertex<String>> strs = ...;

   sortNeighbours(ints, Comparator.naturalOrder());
   sortNeighbours(dbls, Comparator.naturalOrder());
   sortNeighbours(strs, Comparator.naturalOrder());

Вы можете определить дополнительный метод для обработки Comparables так, что вам не нужно каждый раз добавлять naturalOrder() вызов в ваш код.

13
задан Aman Jain 13 February 2009 в 07:09
поделиться

3 ответа

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

#define MACRO_SIZE "5"
snprintf(fmt_str, 100, "%" MACRO_SIZE "s", buf);
8
ответ дан 1 December 2019 в 23:16
поделиться

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

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

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

1
ответ дан 1 December 2019 в 23:16
поделиться

Как сказанный Stefan, но для 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 автоматическое объединение смежных строковых литералов, для формирования необходимой строки форматирования во время компиляции. Это только работает если MACRO_SIZE макрос препроцессора, не, если это - нормальная динамическая переменная.

Дополнительный макро-вызов через RESOLVE() необходим, так как иначе аргумент не был бы разрешен к #defined значение, и мы закончили бы со строкой форматирования "%MACRO_SIZEs", который не является тем, что мы хотим.

10
ответ дан 1 December 2019 в 23:16
поделиться
Другие вопросы по тегам:

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