Search code examples
c++stringbitset

Create string of 7-bit ASCII text from 8-bit ASCII chars in C++


I wish to create a string with up to 46 octets, filled in with 7-bit ASCII chars. For example, for the string 'Hello':

  1. I take the last 7 bits of 'H' (0x48 - 100 1000) and put it in the first 7 bits of the first octet.
  2. I take the next char 'e' (0x65 - 110 0101), the first bit will go to the last bit of the first octet then it will fill the next 6 bits of octet 2.
  3. Repeat 1-2 until end of string, then the rest of the octets will be filled in with 1's.

Here is my attempt which I have worked quite a bit on, I've tried using bitset but it seems that it is not appropriate for this task as I do not have to have 46 octets all the time. If the string can fit in 12 (or 24, 36) octets (and just have the rest filled in by 1's) then I do not have to use 46.

#include <iostream>
#include <string>
#include <vector>

using namespace std;


int main()
{
    std::string a = "Hello";
    int N = 0;
    if (a.size() <= 11) {
        // I'm supposed to implement some logic here to check if it
        // will fit 12, 24, 36 or 46 octets but I will do it later.
        N = 80;
    }

    std::vector<bool> temp(N);
    int j = 0;
    for (int i = 0; i < a.size(); i++) {
        std::vector<bool> chartemp(a[i]);

        cout << a[i] << "\n";
        cout << chartemp[0] << "\n";
        cout << chartemp[1] << "\n";
        cout << chartemp[2] << "\n";
        cout << chartemp[3] << "\n";
        cout << chartemp[4] << "\n";
        temp[j++] = chartemp[0];
        temp[j++] = chartemp[1];
        temp[j++] = chartemp[2];
        temp[j++] = chartemp[3];
        temp[j++] = chartemp[4];
        temp[j++] = chartemp[5];
        temp[j++] = chartemp[6];
    }

    for (int k = j; k < N; k++) {
        temp[j++] = 1;
    }

    std::string s = "";
    for (int l = 0; l <= temp.size(); l++)
    {
        if (temp[l]) {
            s += '1';
        }
        else {
            s += '0';
        }
    }    
    cout << s << "\n";

}

The result is

000000000000000000000000000000000001111111111111111111111111111111111111111111110

Solution

  • It seems as if you expect statement std::vector<bool> chartemp(a[i]) to copy the i'th character of a as a series of bits into the vector. Yet the constructor of a vector interprets the value as the initial size, and a[i] is the ASCII-value of the respective character in a (e.g. 72 for 'H'). So you have a good chance to create vectors of larger size than expected, each position initialized with false.

    Instead, I'd suggest to use bit-masking:

        temp[j++] = a[i] & (1 << 6);
        temp[j++] = a[i] & (1 << 5);
        temp[j++] = a[i] & (1 << 4);
        temp[j++] = a[i] & (1 << 3);
        temp[j++] = a[i] & (1 << 2);
        temp[j++] = a[i] & (1 << 1);
        temp[j++] = a[i] & (1 << 0);
    

    And instead of using temp[j++], you could use temp.push_back(a[i] & (1 << 0)), thereby also overcoming the need of initializing the vector with the right size.