Используя Libtcod, как консольно напечатать строку с динамическим количеством цветов?

У меня есть вспомогательная функция, которая принимает строку и вектор цветов для форматирования строки, и прямо сейчас мое решение состоит в том, чтобы вручную проверить размер цветового вектора и вызвать печать консоли с тем же количеством цветов.

Скажем, у меня есть вектор цвета 4, в коде это будет выглядеть примерно так:

void helper_func(TCODConsole* con, std::string msg_str, std::vector<TCOD_colctrl_t> color_vector)
{
  char* message = msg_str.c_str();
  //this is repeated 1 through 16, adding another color_vector.at(n) for each.
  ...
  else if (color_vector.size() == 2)
   //message might be "%cHello%c was in red"
   console->print(x, y, message, color_vector.at(0), color_vector.at(1))
  ...
  else if (color_vector.size() == 4)
   //message might be "%cThe octopus%c shimmers at %cnight%c"
   console->print(x, y, message, color_vector.at(0), color_vector.at(1), color_vector.at(2), color_vector.at(3))
  ...
}

Хотя это работает, это ужасно, и я искал разные способы сделать это, позволяя использовать более 16 цветов и т. д.

Я пробовал делать sprintf для каждого цвета в векторе, добавляя его в out_string и повторяя. Я пытался сделать то же самое с ostringstream. Я попытался разбить msg_str на "%c", а затем соединить полученные строки после добавления цвета в каждую. Это никогда не срабатывало, всегда либо с использованием первого цвета, либо с использованием случайных символов вместо цветов с этого момента.

Я надеялся, что все вышеперечисленное сработает, потому что просто sprintf(out_char, format_msg, TCOD_COLCTRL_1) выводит на консоль (используя console->print(out_char)) просто отлично.

Мой вопрос: есть ли хороший способ передать различное количество цветов в функцию console->print и обеспечить точное отображение этих цветов без серьезной избыточности кода?


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

Я полагаю, что этот вопрос можно было бы обобщить, чтобы спросить то же самое об обычных printf с заменами.


person TankorSmash    schedule 18.04.2014    source источник
comment
Я считаю, что заголовок, который вы ищете, похож на: Как вызвать функцию с переменным числом аргументов с помощью вектора?   -  person user2864740    schedule 19.04.2014
comment
например ref stackoverflow.com/questions/21330153/ , stackoverflow.com/questions/17974209/ , stackoverflow.com/questions/9276902/   -  person user2864740    schedule 19.04.2014
comment
Спасибо, похоже, есть несколько разных вопросов, которые соответствуют этой концепции. Я взгляну.   -  person TankorSmash    schedule 19.04.2014
comment
@user2864740 user2864740 пытается понять этот ответ, но я не понимаю, как здесь можно применить массив mylist[1]. В моем случае это было бы больше похоже на mylist[16]. Похоже, это поможет, но я не уверен, что я ошибаюсь. Комментарии здесь не способ спросить об этом, я полагаю. stackoverflow.com/a/9277814/541208   -  person TankorSmash    schedule 19.04.2014
comment
См. stackoverflow.com/a/9302246/2864740 (я даже не уверен, что эта операция хорошо определена для va_list хаки)   -  person user2864740    schedule 19.04.2014


Ответы (1)


Одной из возможных альтернатив вариативным функциям может быть синтаксический анализ msg_str для "%c" и итеративная печать каждого сегмента строки в правильном цвете в соответствии с color_vector. Я не уверен, что этот код скомпилируется — я написал его в блокноте, так что, возможно, потребуется доработать. Надеюсь, вы уловили суть того, что я предлагаю.

void helper_func(TCODConsole* con, std::string msg_str, std::vector<TCOD_colctrl_t> color_vector) 
{
    std::string str2;
    std::size_t pos;
    std::size_t pos2;

    pos = msg_str.find("%c");
    if (pos != std::string::npos)
        str2 = msg_str.substr(0,pos);
    else
        str2 = msg_str;
    console->print(x, y, str2.c_str());
    int n = 0;
    while (pos != std::string::npos) {
        pos2 = msg_str.find("%c",pos+1);
        if (pos2 != std::string::npos)
          str2 = msg_str.substr(pos+2,pos2);
        else
          str2 = msg_str.substr(pos2+2,msg_str.length()-pos2+2);
        console->print(x, y, str2.c_str(),color_vector.at(n));
        pos = pos2;
        n++;
    }
}

Я подумал, что должен упомянуть, что в моем коде есть проблема. Значение x во втором операторе печати необходимо вычислять каждый раз через цикл while, поскольку x изменяется как функция pos2. В противном случае все будет продолжать печатать на одном и том же месте. :) Должно быть легкое изменение...

person xeonicus    schedule 03.09.2014