3

I am thinking of a method of how to iterate through a string given by a user. It has to do with a dice rolling; format: xdy[z] where x is times rolled and dy is dice type and z is just an integer

The format is this: a number from 1-999 (x), then the letter d and then a specific number[the dice type] (only 5 to chose from; 4,6,12,20,100),and then square brackets with a number from 1 to 100 in it...so some examples look like this...1d4[57], 889d20[42], 43d4[4], 1d4[1] - 999d100[100] is the range of characters so 6 characters vs 12 characters. I am not sure how to go about this, here is what I have now but it seems like there can be a better way to go about this. The input that I get from the user is already validated using a regular expression to ensure the format is correct. I wanted to store the values in vector arrays then concatenate everything in the end.

void rollDie(std::string input)
{
    int bracketCount;
    std::vector<int> timesRolled;
    std::vector<int> diceType;
    std::vector<int> additional;
    bool d = false;
    bool bc = false;

    for (int i = 0; i < input.length; i++) //or length - 1
    {
        if (isdigit(input[i]))
        {
            if (bool d = false) 
            {
                timesRolled.push_back(input[i]);
            }
        }
        if(isalpha(input[i]))
        {
            d = true;
        }
        if (isdigit(input[i])) 
        {
            if (d = true)
            {
                diceType.push_back(input[i]);
            }
        }
        if (!isalpha(input[i]) && !isdigit(input[i]))
        {
            bracketCount++;
            bc = true;
            if (bracketCount = 2) break;
        }
        if (isdigit(input[i]))
        {
            if (bc = true) 
            {
                additional.push_back(input[i]);
            }
        }
    }
}
Stefan Collier
  • 4,314
  • 2
  • 23
  • 33
lucyb
  • 333
  • 5
  • 15
  • 2
    `if (d = true)`, `if (bracketCount = 2)` and `if (bc = true)` can't possibly be right. All those `if` checks are assigning, and then testing if the new value is truthy (which it is in all cases). The `if (d = false)` is the same, but since the assignment is falsy, the test always fails. – ShadowRanger Oct 18 '16 at 05:13
  • 4
    If you used RegEx to validate, why not using RegEx to get the numbers? – Ely Oct 18 '16 at 05:15
  • 2
    If the answer below does not work for you, please provide feedback. If it works, please accept/upvote. – Wiktor Stribiżew Oct 18 '16 at 06:10

1 Answers1

4

If you are using a regular expression to validate the input then you might as well use the same regular expression to extract the values.

Something like:

    std::regex e{ R"-((\d{1,3})[Dd](4|6|12|20|100)\[(\d{1,3})\])-" };

    std::cout << "Enter dice roll: " << std::flush;

    std::smatch m;
    for(std::string line; std::getline(std::cin, line);)
    {
        if(std::regex_match(line, m, e))
            break; // if it's good we're done here

        // keep going until we get it right
        std::cout << "Error: bad format, please use: nnndxx[ddd]" << '\n';
    }

    int rolls = std::stoi(m[1]);
    int sides = std::stoi(m[2]);
    int extra = std::stoi(m[3]);

    std::cout << "Rolls: " << rolls << '\n';
    std::cout << "Sides: D" << sides << '\n';
    std::cout << "Extra: " << extra << '\n';
Galik
  • 47,303
  • 4
  • 80
  • 117
  • 1
    thanks this makes sense to me! I had the same regex as you but only to validate the expression, was not sure how to re-use it again, thank you. – lucyb Oct 18 '16 at 07:01
  • 1
    I have a question, how would I break your for each statement? After I get the correct values I want to calculate some values but I can't do it since I am stuck in the loop – lucyb Oct 19 '16 at 02:28
  • 2
    @lucyb I edited the answer. Simply use the `break;` statement. – Galik Oct 19 '16 at 07:37
  • 2
    I'd actually move the `std::smatch m;` out of the loop, and have the loop body just be: `if (std::regex_match(line, m, e)) break; std::cout << "bad format"; ` – Martin Bonner supports Monica Oct 19 '16 at 07:41
  • 1
    Obviously, with better formatting - but it's hard to format code in comments! – Martin Bonner supports Monica Oct 19 '16 at 07:42
  • 1
    @MartinBonner That makes more sense so I changed the example. It's probably better still placed in a function returning a `struct` but you can only second guess the `OP`s requirements so much. – Galik Oct 19 '16 at 08:03