0

I'm trying to set bits in a binary string. I initially have an empty string which needs to set the give bit(i) in the string(s).

for the given example, the output should be 0x3001 as:

pos: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
bit: 0 0 1 1 0 0 0 0 0 0  0  0  0  0  0  1
     ^                                   ^
     MSB                               LSB

Which, in hex is 3001.

#include<iostream>
#include<string>
#include<sstream>
#include<iomanip>

using namespace std;
void generate_string(string& s,int i){
    int sl = s.length();
    int x = i/8;
    std::stringstream m(s, ios_base::app);
    if(sl<x){
        for(int j = x-sl;j>=0;j--){
            m<<'\x00';
        }
    }
    s = m.str();
    s[x] |= 1 << i%8;
}
int main(){
    string s = "";
    generate_string(s,15);
    generate_string(s,2);
    generate_string(s,3);
    for(int i=0;i<s.length();i++)
        cout<<hex<<(int)s[i];
    return 0;
}

But this program is not showing any output.

ayushgp
  • 4,891
  • 8
  • 40
  • 75
  • First of all, you *do* know that bit-numbers are actually the opposite way around? Bit 0 is the first (least significant) bit in a binary number, and bit 15 is the last (most significant) bit in a 16-bit binary number. Second, you really should learn how to use a debugger so you can step through your code yourself. – Some programmer dude Apr 01 '16 at 10:38
  • What do you want the program to do? Set the string characters corresponding to the bit numbers to 1? – Richard Hodges Apr 01 '16 at 10:45
  • @JoachimPileborg I need to implement it this way. And yeah I know that the bits are the other way around. I thonk you are saying that I'll need to change the `s[x] |= 1 << i%8;` to `s[x] |= 1 << (7-(i%8));`. I'm trying to get [this](http://stackoverflow.com/questions/20673131/can-someone-explain-redis-setbit-command) kind of behaviour. And learning to use a debugger is on my list. – ayushgp Apr 01 '16 at 10:46
  • @RichardHodges [this](http://stackoverflow.com/questions/20673131/can-someone-explain-redis-setbit-command) – ayushgp Apr 01 '16 at 10:47
  • Also I don't see the need for a string here? What's the purpose of the string, to store one bit per character? 8 bits per character? Why use a string and not a vector of *unsigned* bytes? – Some programmer dude Apr 01 '16 at 10:56
  • 1
    @JoachimPileborg for the sake of interest, I used to write software on the texas instruments TMS9995 chip. The 9900 instruction set numbered bits left to right. – Richard Hodges Apr 01 '16 at 10:58
  • @JoachimPileborg I cant use an array of int because I need to implement **exactly** the behaviour mentioned in the answer I linked above. ints take 32 bits and chars 8bits. I need the end result to have exactly the required no. of bytes. – ayushgp Apr 01 '16 at 11:03

3 Answers3

1

It's actually much more simpler than you think. The only complicated part is to calculate the bit number to be set in the byte.

Oh, and why use a string for this? Why not a vector?

Here's my solution, using std::vector instead:

void set_bit(std::vector<uint8_t>& bits, unsigned bit)
{
    static unsigned const bit_count = 8;   // Should really use std::numeric_limits<uint8_t>::digits

    unsigned index = bit / bit_count;

    while (index + 1 > bits.size())
        bits.push_back(0);

    // Since the bit-numbers are reversed from what's "common",
    // we need a little more complex calculation here.
    // bit % bit_count to get the "normal" bit number
    // bit_count - bit % bit_count to reverse the bit numbering
    // Then -1 to get a number between 0 and 7
    bits[index] |= 1 << (bit_count - bit % bit_count - 1);
}

You can use a similar solution using std::string too, but I don't see why.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
1

Maybe like this?

#include<iostream>
#include<string>

using namespace std;
void set_bit(string& s,int i){
    auto bits = ((i + 7) / 8) * 8;
    if (bits > s.length())
    {
        auto diff = bits - s.length();
        s += std::string(diff, '0');
    }
    s[i] = '1';
}

int main(){
    string s;
    set_bit(s, 2);
    set_bit(s, 3);
    set_bit(s, 15);
    cout << s << endl;
    return 0;
}

expected output:

0011000000000001

update: attempt 2 :-)

#include<iostream>
#include<iomanip>
#include<string>

using namespace std;
void set_bit(string& s,int i){
    auto bytes = (i + 7) / 8;
    if (bytes > s.length())
    {
        auto diff = bytes - s.length();
        s += std::string(diff, 0);
    }
    s[i / 8] |= char(1 << (7-(i%8)));
}

int main(){
    string s;
    set_bit(s, 2);
    set_bit(s, 3);
    set_bit(s, 15);

    std::cout << "as hex: ";
    for (auto c : s) {
        cout << hex << setfill('0') << setw(2) << (int(c) & 0xff);
    }
    cout << endl;

    std::cout << "as binary: ";
    auto sep = "";
    for (auto c : s) {
        unsigned char bits = c;
        for (unsigned char mask = 0x80 ; mask ; mask >>= 1)
        {
            cout << sep << ((bits & mask) ? '1' : '0');
            sep = " ";
        }
    }
    cout << endl;



    return 0;
}

expected output:

as hex: 3001
as binary: 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142
  • That's not quite the expected output as shown above, if you translate that binary number to hex it's definitely not `0x3001`. – Some programmer dude Apr 01 '16 at 11:01
  • This is using 16 bytes. Which is something That I dont want. The thing I'm trying to implement is using only 2 bytes to store the information. – ayushgp Apr 01 '16 at 11:10
0

I don't quite understand what the output should be in Your problem, because You are mixing most/least signifanct bits with nibbles order in sample input/output, but I You would like to print number in hex as a string You can do sth like this:

#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>

void feed(std::string& s, int x){
unsigned int mask = 15;
int nibblesInWord = sizeof(void*)*16;
std::stringstream ss;
while(nibblesInWord--){
 std::cout << int(x & mask) <<std::endl;
 ss << int(x & mask);
 x >>= 4;
}
s = ss.str();
std::reverse(s.begin(), s.end());
}


int main(){
std::string s;
 feed(s, 99);
 std::cout << s <<std::endl;
}
Mateusz Wojtczak
  • 1,621
  • 1
  • 12
  • 28
  • I've edited the expected input/output. And what would be the output of this program? – ayushgp Apr 01 '16 at 11:11
  • On 64 bit machine 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000063, You can just get rid of leading 0 and will be 63 – Mateusz Wojtczak Apr 01 '16 at 11:14