0

我正在制作一个简单的 Cocoa 程序,可以将文本编码为二进制并将其解码回文本。我试图制作这个脚本,但我什至还没有接近完成它。谁能帮我?这必须包括两个文本框和两个按钮或任何最好的,谢谢!

4

1 回答 1

0

这有两个部分。

第一种是将字符串的字符编码为字节。您可以通过向字符串发送dataUsingEncoding:消息来做到这一点。您选择的编码将决定它为每个字符提供哪些字节。从 开始NSUTF8StringEncoding,然后尝试其他编码,例如NSUnicodeStringEncoding,一旦你开始工作。

第二部分是将每个字节的每一位转换为'0'字符或'1'字符,例如,以 UTF-8 编码为单个字节的字母 A 将表示为01000001.

因此,将字符转换为字节,并将字节转换为表示位的字符。这两个是完全独立的任务;第二部分应该适用于任何字节流,包括任何有效的编码字符流、任何无效的编码字符流,以及实际上任何不是文本的东西。

第一部分很简单:

- (NSString *) stringOfBitsFromEncoding:(NSStringEncoding)encoding
    ofString:(NSString *)inputString
{
    //Encode the characters to bytes using the UTF-8 encoding. The bytes are contained in an NSData object, which we receive.
    NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];

    //I did say these were two separate jobs.
    return [self stringOfBitsFromData:data];
}

对于第二部分,您需要遍历bytes数据。交流for回路将在那里完成工作,看起来像这样:

//This is the method we're using above. I'll leave out the method signature and let you fill that in.
- …
{
    //Find out how many bytes the data object contains.
    NSUInteger length = [data length];
    //Get the pointer to those bytes. “const” here means that we promise not to change the values of any of the bytes. (The compiler may give a warning if we don't include this, since we're not allowed to change these bytes anyway.)
    const char *bytes = [data bytes];

    //We'll store the output here. There are 8 bits per byte, and we'll be putting in one character per bit, so we'll tell NSMutableString that it should make room for (the number of bytes times 8) characters.
    NSMutableString *outputString = [NSMutableString stringWithCapacity:length * 8];

    //The loop. We start by initializing i to 0, then increment it (add 1 to it) after each pass. We keep looping as long as i < length; when i >= length, the loop ends.
    for (NSUInteger i = 0; i < length; ++i) {
        char thisByte = bytes[i];

        for (NSUInteger bitNum = 0; bitNum < 8; ++bitNum) {
            //Call a function, which I'll show the definition of in a moment, that will get the value of a bit at a given index within a given character.
            bool bit = getBitAtIndex(thisByte, bitNum);

            //If this bit is a 1, append a '1' character; if it is a 0, append a '0' character.
            [outputString appendFormat: @"%c", bit ? '1' : '0'];
        }
    }

    return outputString;
}

位 101(或 1100101)

位实际上只是以 2 为基数的数字。西方世界的人类通常以 10 为基数写出数字,但数字是一个数字,无论它是用什么基数写的,每个字符,每个字节,甚至每个位,都是只是一个数字。

数字(包括位)从最低的位置开始计数,根据基数被提高到的指数来计算该位置的大小。我们想要位,所以基数是 2,所以我们的位置值是:

  • 2^0 = 1:个位(最低位)
  • 2^1 = 2:二进制位(下一个高位)
  • 2^2 = 4:四人组
  • 2^3 = 8:八分之二

依此类推,最多 2^7。(请注意,最高指数正好比我们所追求的位数小一;在这种情况下,7 对 8。)

如果这一切让你想起小时候读过的“个位”、“十位”、“百位”等,那应该是:原理完全相同。

因此,一个字节(如 65)(在 UTF-8 中)完全表示字符“A”,是以下各项的总和:

  2^7 × 0 = 0
+ 2^6 × 0 = 64
+ 2^5 × 1 = 0
+ 2^4 × 0 = 0
+ 2^3 × 0 = 0
+ 2^2 × 0 = 0
+ 2^1 × 0 = 0
+ 2^0 × 1 = 1
= 0 + 64 +0+0+0+0+0 + 1
= 64 + 1
= 65

当您小时候学习以 10 为底的数字时,您可能注意到十是“10”,一百是“100”,等等。在底数 2 中也是如此:因为 10^x 是“1”,然后是 x以 10 为底的“0”,2^x “1”后跟以 2 为底的“x”0。因此,例如,以 2 为底的 64 是“1000000”(计算零并与表格进行比较以上)。

我们将使用这些精确的二的幂数来测试每个输入字节中的每个位。

寻找比特

C 有一对“移位”运算符,它们将在数字的低端插入零或删除数字。前者叫做“左移”,写成<<,你可以猜反了。

我们要左移。我们想将 1 左移我们所追求的位数。这完全等同于将 2(我们的基数)提高到该数字的幂;例如,1 << 6= 2^6 = “1000000”。

测试位

C 也有一个用于位测试的运算符;它是&按位与运算符。(不要将此与&&逻辑AND运算符混淆。&&用于在做出决策时使用整个真/假值;&是处理值中的位的工具之一。)

严格来说,&不测试单个位;它遍历两个输入值的位,并返回一个新值,其位是每个输入对的按位与。所以,例如,

  01100101
& 00101011
----------
  00100001

当且仅当两个相应的输入位也是 1 时,输出中的每个位都是 1。

把这两件事放在一起

我们将使用左移运算符给我们一个数字,其中设置了一位,即第 n 位,2^n,然后使用按位与运算符来测试在我们的输入字节。

//This is a C function that takes a char and an int, promising not to change either one, and returns a bool.
bool getBitAtIndex(const char byte, const int bitNum)
//It could also be a method, which would look like this:
//- (bool) bitAtIndex:(const int)bitNum inByte:(const char)byte
//but you would have to change the code above. (Feel free to try it both ways.)
{
    //Find 2^bitNum, which will be a number with exactly 1 bit set. For example, when bitNum is 6, this number is “1000000”—a single 1 followed by six 0s—in binary.
    const int powerOfTwo = 1 << bitNum;

    //Test whether the same bit is also set in the input byte.
    bool bitIsSet = byte & powerOfTwo;

    return bitIsSet;
}

我应该承认一点魔法

按位 AND 运算符不会计算为单个位 - 它不会仅计算为 1 或 0。请记住上面的示例,其中&运算符返回 33。

bool类型有点神奇:任何时候将任何值转换为,bool它都会自动变为 1 或 0。任何不是 0 的都变为 1;任何东西都0变成了0

Objective-CBOOL类型不这样做,这就是我bool在上面的代码中使用的原因。你可以随意使用任何你喜欢的东西,除了你通常应该BOOL在处理任何需要 a 的东西时使用BOOL,特别是在覆盖子类中的方法或实现协议时。您可以自由地来回转换,但不是无损的(因为bool如上所述会更改非零值)。

哦,是的,你也谈到了文本框

当用户单击您的按钮时,获取stringValue您的输入字段,stringOfBitsFromEncoding:ofString:使用合理的编码(例如 UTF-8)和该字符串进行调用,并将结果字符串设置为stringValue您的输出字段的新字符串。

额外积分:添加一个弹出按钮,用户可以使用该按钮选择编码。

额外的额外功劳:使用所有可用编码填充弹出按钮,无需硬编码或硬敲击列表。

于 2013-04-19T03:10:35.410 回答