2

I've got a helper function that accepts a string and a vector of colors to use to format the string and right now my solution is to manually check the size of the color vector and call the console print with that same amount of colors.

Say I've got a color vector of 4, in the code it'd do something like:

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))
  ...
}

While this works, it's awful and I was looking into different ways of pulling it off, allowing for more than 16 colors, etc.

I've tried doing a sprintf for each color in the vector, adding it to the out_string and repeating. I've tried doing the same with an ostringstream. I've tried splitting the msg_str on "%c" and then joining the resulting strings once I've added the color in to each. It never worked out, always either using the first color and then using random characters instead of colors from there on out.

I was hopeful that any of the above would work because simply sprintf(out_char, format_msg, TCOD_COLCTRL_1) prints to the console (using console->print(out_char)) just fine.

My question is: is there a good way to pass a varying number of colors to the console->print function and have it accurately display those colors, without severe code redundancy?


As a fallback, I could print out a section of the string up to the first color, calculate its size, move x over by that much and print the next section, but that's not ideal.

I suppose that this question could be generalized to asking the same thing about regular printf with substitutions too.

TankorSmash
  • 12,186
  • 6
  • 68
  • 106
  • I believe the title you are looking for is similar to: "How to call a variadic function using a vector?" – user2864740 Apr 18 '14 at 21:12
  • e.g. ref http://stackoverflow.com/questions/21330153/c-vector-wrapper-around-variadic-function , http://stackoverflow.com/questions/17974209/c11-calling-a-variadic-function-with-the-elements-of-a-vector , http://stackoverflow.com/questions/9276902/passing-stdvectorint-items-to-variadic-function – user2864740 Apr 18 '14 at 21:14
  • Thanks, it looks like there's a few different questions that match that concept. I'll take a look. – TankorSmash Apr 18 '14 at 21:14
  • @user2864740 trying to understand this answer, but I don't see how the array of `mylist[1]` would apply here. In my case, it'd be more like `mylist[16]`. It looks like it would help, but I'm not sure what I'm getting wrong. The comments here isn't the way to ask about it, I suppose. http://stackoverflow.com/a/9277814/541208 – TankorSmash Apr 18 '14 at 21:29
  • See http://stackoverflow.com/a/9302246/2864740 (I'm not even sure if this operation is "well defined" for the va_list hacks) – user2864740 Apr 18 '14 at 21:35

1 Answers1

2

One possible alternative to a variadic functions might involve parsing msg_str for "%c" and iteratively printing each segment of the string in the correct color according to color_vector. I'm not sure if this code below will compile--I wrote it in notepad, so it might need some work. Hopefully you get the gist of what I'm suggesting.

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++;
    }
}

I thought I should mention, there is a problem in my code. The x value in the second print statement needs to be calculated each time through the while loop since x changes as a function of pos2. Otherwise, everything will just keep printing in the same spot. :) Should be an easy change...

xeonicus
  • 21
  • 3