1

I am using a Constructor to take an unsigned int as an argument, break it into digits and assign the appropriate true and false values to a vector object. But the problem is that, my poor logic assigns the values in reverse order as the last digit is separated first and so on. The Code I have written is:

vector<bool> _bits; 
uBinary(unsigned int num){  
    int i = 1;
    while(num > 0)
    {
        int d = num%10;
        num /= 10;
        _bits.resize(i++);
        if(d == 1)
        {
            _bits[_bits.size() - 1] = true; 
        }
        else if(d==0)
        {
            _bits[_bits.size() - 1] = false;
        }
    }
}

For example: if argument 10011 is passed to the function uBinary() the vector object will be assigned the values in this order 11001 or true,true,false,false,true which is reversed. All I need to do here is that, I want to assign the values without reversing the order and I don't want to use another loop for this purpose.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
HN Learner
  • 544
  • 7
  • 19
  • why do you use a `unsigned int` to store a binary in the first place? – 463035818_is_not_an_ai Apr 28 '17 at 16:04
  • 2
    cheat and use a `std::bitset` :) – NathanOliver Apr 28 '17 at 16:05
  • you can `std::reverse` a `vector`, though not sure if it works with a `vector` – 463035818_is_not_an_ai Apr 28 '17 at 16:06
  • @tobi303 actually I am using bool to store bits. unsigned int is only passed as argument there – HN Learner Apr 28 '17 at 16:06
  • 3
    If you want to do it without reversing at the end (which is by far the simplest way), you need to know the number of digits in advance, which requires a loop or call to `log10`. – Cameron Apr 28 '17 at 16:06
  • @NathanOliver I appreciate your idea, but I am a beginner and want to develop good logic, that's why i am doing this to practice my programming skills – HN Learner Apr 28 '17 at 16:07
  • @Cameron thanks Sir ... I don't want to use another loop. But will check that log10 method. Thanks for adding something new to my knowledge :) – HN Learner Apr 28 '17 at 16:09
  • imho `_bits.back()` is nicer to read than `_bits.[_bits.size()-1]` and if anyhow you increase the size for each element you could as well use `push_back` instead of `resize` + assign – 463035818_is_not_an_ai Apr 28 '17 at 16:09
  • Wait, why is your input in decimal? Why not either a string or the actual bits themselves in a `uint32_t` or something? – Cameron Apr 28 '17 at 16:11
  • Thanks @tobi303 I really know the difference. push_back() will be better here. But I was thinking of assigning the elements in reverse order to overcome this problem that's why used this one – HN Learner Apr 28 '17 at 16:12
  • @Cameron what if the user enters the input? That's why I used unisgned int. I know I am wrong in many places. But as i mentioned, im just a beginner and in learning process. Thanks for all your kind advises :) – HN Learner Apr 28 '17 at 16:13
  • 1
    I would suggest you to use a `std::string` for the input, however, maybe then the task is to easy to make a good excercise ;) – 463035818_is_not_an_ai Apr 28 '17 at 16:14
  • 2
    If the user enters the input, it will be a string of characters (which is more efficient to process than all these integer divisions...). – Cameron Apr 28 '17 at 16:14
  • 2
    Instead of `_bits[_bits.size()-1]= true`, you might currently use `_bits.push_back(true)`, and to have in reverse order, `_bits.insert(_bits.begin(), true)`. but `reverse` at the end is simpler and more efficient (as push_front for vector is `O(N)`). – Jarod42 Apr 28 '17 at 16:15
  • 1
    at least you should `reserve` some space in the vector to avoid frequent reallocations when you `resize` or `push_back` – 463035818_is_not_an_ai Apr 28 '17 at 16:16
  • 1
    Okay guys... Thanks a lot all of you. I have learnt new things from you. :) And will have a look on all of these ideas. Thanks ! :) – HN Learner Apr 28 '17 at 16:18
  • @Jarod42 Sir your Idea is awesome. Thanks a lot ! – HN Learner Apr 28 '17 at 16:21
  • Now I know how to handle such problems with vectors. And yes, will be using string instead of integers to take such input. Thanks Again – HN Learner Apr 28 '17 at 16:22

2 Answers2

2

One way is to start at the highest possible digit (unsigned int can only hold values up to 4294967295 on most platforms) and ignore leading zeros until the first actual digit is found:

for (uint32_t divisor = 1000000000; divisor != 0; divisor /= 10) {
    uint32_t digit = num / divisor % 10;
    if (digit == 0 && _bits.size() == 0 && divisor != 1)
        continue;  // ignore leading zeros
    _bits.push_back(digit == 1);
}

But finding the digits in reverse and then simply reversing them is much simpler (and at least as efficient):

do {
    _bits.push_back(num % 10 == 1);
    num /= 10;
} while (num != 0);
std::reverse(_bits.begin(), _bits.end());
Cameron
  • 96,106
  • 25
  • 196
  • 225
1

One way you can do the reversing with another loop or std::reverse is to use recursion. With recursion you can walk down the int until you hit the last digit and then you add the values to the vector as the calls return. That would look like

void uBinary(unsigned int num)
{   
    if (num == 0)
        return;
    uBinary(num / 10);
    _bits.push_back(num % 10 ? true : false);
}

Which you can see working with

int main()
{
    uBinary(10110);
    for (auto e : _bits)
        std::cout << e << " ";
}

Live Example


Do note that it is advisable not to use leading underscores in variables names. Some names are reserved for the implementation and if you use one it is undefined behavior. For a full explanation of underscores in names see: What are the rules about using an underscore in a C++ identifier?

Community
  • 1
  • 1
NathanOliver
  • 171,901
  • 28
  • 288
  • 402