1

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
6
  • 1
    It's probably simplest to operate on 8-byte integers rather than on individual bytes. Commented Aug 9, 2017 at 21:59
  • How do you tell the difference between "Hello" and "Hello\x7f"? Both would be represented in the same way. Did you mean to include the null terminator too, or do you want to disallow that character? Commented Aug 9, 2017 at 22:32
  • @DanielH: I read the question as the extra 1s wont be added until the next full octet, not starting after the last encoded bit, so "Hello" would be 10010001 10010111 01100110 11001101 11100000 11111111 11111111 ..., whereas "Hello\x7f" would be 10010001 10010111 01100110 11001101 11111111 11000000 11111111 ... instead. Commented Aug 9, 2017 at 23:40
  • What is 8 bit ASCII? Commented Aug 9, 2017 at 23:40
  • @RemyLebeau Then what about "Daniel H" vs "Daniel H\x7f"? The string "Daniel H", encoded in 7 bits per character, would end at the end of the 7th octet. It is difficult to avoid all ambiguity; SMS does something similar, so you can’t end a text message with a multiple of 8 characters total with a carriage return (not that you would usually want to), and I think the original spec made it so you couldn’t end the message with an @ (which you might want). Commented Aug 10, 2017 at 15:07

2 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, just had to reverse the numbers to work (0 -> 6, etc).
1

Try something like this:

#include <string>
#include <vector>

std::string stuffIt(const std::string &str, const int maxOctets)
{
    const int maxBits = maxOctets * 8;
    const int maxChars = maxBits / 7;

    if (str.size() > maxChars)
    {
        // t0o many chars to stuff into maxOctes!
        return "";
    }

    std::vector<bool> temp(maxBits);
    int idx = temp.size()-1;

    for (int i = 0; i < str.size(); ++i)
    {
        char ch = str[i];
        for(int j = 0; j < 7; ++j)
            temp[idx--] = (ch >> (6-j)) & 1;
    }

    int numBits = (((7 * str.size()) + 7) & ~7);

    for (int i = (temp.size()-numBits-1); i >= 0; --i) {
        temp[i] = 1;
    }

    std::string s;
    s.reserve(temp.size());

    for(int j = temp.size()-1; j >= 0; --j)
        s.push_back(temp[j] ? '1' : '0');

    return s;
}

stuffIt("Hello", 12) returns:

100100011001011101100110110011011110000011111111111111111111111111111111111111111111111111111111

stuffIt("Hello", 24) returns:

100100011001011101100110110011011110000011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

stuffIt("Hello", 36) returns:

100100011001011101100110110011011110000011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

stuffIt("Hello", 46) returns:

10010001100101110110011011001101111000001111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

If you want to know how many octets a given string will require (without adding octets full of 1s), you can use this formula:

const int numChars = str.size();
const int numBits = (numChars * 7);
const int bitsNeeded = ((numBits + 7) & ~7);
const int octetsNeeded = (bitsNeeded / 8);

If you want the extra 1s, just round octetsNeeded up to the desired value (for instance, the next even multiple of 12).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.