NSString from bool array

Discussion in 'iOS Programming' started by BlobbleGame, Jun 25, 2011.

  1. BlobbleGame macrumors newbie

    Mar 4, 2011
    This should be easy, but I'm having some trouble. I'm attempting to create an NSString from a multidimensional bool array so that I can store and transmit it.

    I have a bool array:
    bool wall[100][100];

    I would like the bytes of the array to be converted to a string. I have tried many different methods of creating an NSString from the array including the following.

    NSData *wallData = [NSData dataWithBytes:wall length:sizeof(wall)];
    NSString* wallString = [[NSString alloc] initWithData:wallData encoding:NSUTF8StringEncoding];
    This results in no output.

    I'm guessing that this is due to the mismatch in size and the requirements o the encoding, but both are complex to solve and I'm going at this blind.

    Any help would be greatly appreciated.

  2. chown33, Jun 25, 2011
    Last edited: Jun 25, 2011

    chown33 macrumors 604

    Aug 9, 2009
    Sailing beyond the sunset
    A bool is not a character. If something isn't a character, then it can't be turned into an NSString simply by putting it into NSData first. All you'll get is misinterpreted binary data.

    You have to convert the binary data to a character representation first.

    I suggest analyzing a simpler version of the problem:
    bool simple[ 5 ];
    That's right, a bool array containing only 5 values.

    What is the sizeof(simple)? Using the %x format specifier for NSLog, what are the values displayed? After seeing the values, are those binary values representable in a NSString? Is the NSString data containing those binary values transmittable by whatever mechanism you plan to use to transmit it?

    Personally, if I had to choose a simple character representation for booleans, it would be '0' for 0/NO, and '1' for 1/YES. The simplest reason is because those are characters, whereas the bool binary values themselves are not. Or you could use any other two distinct characters, such as the pair 'N'/'Y' or '-'/'+'.
  3. BlobbleGame thread starter macrumors newbie

    Mar 4, 2011
    Essentially I need a sequence of 10000 bits. It's perfectly feasible to store these as characters (8 bits per character for ASCII). Storing a separate character for each bool would make it at least 8 times the size.

    My logic is correct, but I do not know by which mechanism to convert the data.
  4. chown33 macrumors 604

    Aug 9, 2009
    Sailing beyond the sunset
    Your logic is flawed: you can't store arbitrary sequences of bits as UTF-8. The UTF-8 encoding has specific rules that must be followed. Certain byte sequences are allowed, and are meaningful. Other byte sequences are forbidden, because they are meaningless. You should read up on UTF-8, such as its Wikipedia article.

    Your strategy is also flawed: premature optimization. If you want minimal size, and the booleans are sparsely asserted, you might do better with a compression scheme such as Run-Length Encoding. In any case, that's all still premature optimization.

    The first problem to solve is how to encode and decode single-bit representations of bool.
    In short, how to pack and unpack bits into bytes.

    So given a simple array of 8 bools, how do you think you'd pack them into the 8 low bits of a byte. Assume for now that you're packing them into the low bits of an int. Once you get 8 bits packed into an int, you can store that into a char, or append a char to an NSMutableData.

    The basic mechanism for accessing bits is shifting and masking.
    The shift operators in C (hence, Objective-C) are << and >>.
    The bitwise masking operators are & and | (AND and OR).

    Once you have code written, tested, and working for 8 bits, expand it to work with 20 bits. That means you'll have to deal with multiple 8-bit bytes of output. You'll also have to deal with the fact that 20 is not an exact multiple of 8. So you'll have to figure out something for padding the last bits.
  5. BlobbleGame thread starter macrumors newbie

    Mar 4, 2011
    Does Objective C store each bool in an array as an individual byte?

    I appreciate your advice, but I'd rather not spend days writing my own compression technique and doing the bit calculations when it seems highly likely that there is already a method by which this can be done.

    The process is simple:
    Multiple Bits -> Number
    Number -> Character
    Multiple Characters -> String

    If I had asked to store a series of integers would your response have been the same? The only step to that process is setting and retrieving the individual bits in each integer, which must be quite a simple process.

    Thanks for the advice, but I believe you are making this more complex than it need be.
  6. chown33, Jun 25, 2011
    Last edited: Jun 25, 2011

    chown33 macrumors 604

    Aug 9, 2009
    Sailing beyond the sunset
    NSLog the wallData in your original code. Or NSLog sizeof(wall) as %d.

    You're right: it's not complex at all.

    Any compression other than bits-into-bytes does add complexity, but save that for later. There are any number of libraries (such as gzip) that could be used to compress a sequence of bytes.

    The problem is you don't see how to convert a bool into a single bit. Or given a single bit, such as 1 or 0 in the LSB of an int, you don't see how to shift the new bit into place in a byte.

    Here's a function to return a single LSB 1 or 0 depending on the bool value:
    int bitForBool( bool b )
    {  return ( b ? 1 : 0 );  }
    It's simple enough it really doesn't even need to be a function.

    Here's the code to shift up an existing int, and combine with the LSB from another int:
    int bits;
    int newBit = bitForBool( yourBoolArray[ someArrayIndex ] );
    bits = ( bits << 1 ) | (newBit & 1);
    Obviously, the accumulation of bits should be in a loop, and you should write the total of 8 bits after accumulating a byte.

    I will leave the unpacking (decoding) of the bits as an exercise.

    If you don't understand the code, it suggests you should study the bit-oriented operations.

    If you'd asked about storing a series of integers, I would have asked what format.

    Same question applies here for the bits.

    You haven't identified how you're transmitting the 8-bits-per-byte. If it's over an HTTP POST or some other protocol that might restrict the characters, or might somehow mangle them in transit, then you need to choose a representation that won't be mangled. For example BASE64 (look it up on Wikipedia).

    If you're just transmitting plain bytes, then there is no purpose in converting the NSData into NSString. The NSData holding the bits packed into bytes already holds exactly the sequence of bytes to transmit.

    If you're having to encode the plain bytes, then you have to pick an encoding that's reversible. This may be dictated by whatever protocol or transport method you're using.

Share This Page