我正在制作一个简单的Cocoa程序,它可以将文本编码为二进制并将其解码回文本。我试图制作这个剧本,我甚至都没有完成这个。谁能帮我?这必须包括两个文本框和两个按钮或任何最好的,谢谢!
答案 0 :(得分:0)
这有两个部分。
第一种是将字符串的字符编码为字节。您可以通过发送字符串dataUsingEncoding:
消息来完成此操作。您选择哪种编码将决定它为每个字符提供哪些字节。从NSUTF8StringEncoding
开始,然后在其工作后尝试使用其他编码,例如NSUnicodeStringEncoding
。
第二部分是将每个字节的每一位转换为'0'
字符或'1'
字符,例如,字母A,以UTF-8编码为单个字符byte,将表示为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
数据。 C 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;
}
比特实际上只是基数2中的数字。西方世界的人通常会在基数10中写出数字,但数字是一个数字,无论它写入什么基础,每个字符和每个字节,实际上每一点,都只是一个数字。
数字 - 包括位 - 从最低位开始计数,根据提升基数的指数来查找该位置的大小。我们需要位,因此base是2,所以我们的位置值是:
依此类推,最多2 ^ 7。 (请注意,最高指数恰好比我们之后的数字低一个;在这种情况下,7对8。)
如果这一切都提醒你在小时候读到“那个地方”,“十位”,“数百个地方”等等,它应该:它是完全相同的原则。
所以像65这样的字节(以UTF-8表示)完全代表字符&#39; A&#39;是以下的总和:
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是“10”,100是“100”等。这在基数2中也是如此:因为10 ^ x是“1”在基数10中跟随x“0”s,因此在基数2中是2 ^ x“1”,接着是“x”0。因此,例如,基数2中的64是“1000000”(计算零并比较到上表)。
我们将使用这些精确的2次幂来测试每个输入字节中的每个位。
C有一对“移位”运算符,它们会在数字的低端插入零或删除数字。前者称为“左移”,写为<<
,你可以猜对了。
我们想要左转。我们希望将1左移一个我们之后的位数。这相当于将2(我们的基数)提高到该数字的幂;例如,1 << 6
= 2 ^ 6 =“1000000”。
C也有一个用于位测试的运算符;它是&
,按位AND运算符。 (不要将此与&&
混淆,后者是逻辑 AND运算符。&&
用于在做出决策时使用整个true / false值; &
是一个用于处理值内位的工具。)
严格来说,&
不测试单个位;它遍历两个输入值的位,并返回一个新值,其位是每个输入对的按位AND。所以,例如,
01100101
& 00101011
----------
00100001
当且仅当相应输入位的两个也为1时,输出中的每个位都为1.
我们将使用左移运算符给我们一个数字,其中一位,第n位, 设置 - 即2 ^ n - 然后使用按位AND运算符,用于测试在输入字节中是否也设置了相同的位。
//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。 / p>
bool
类型有点神奇:任何时候将任何值转换为bool
,它会自动变为1或0.任何非0都会变为1;任何0
变为0
。
Objective-C BOOL
类型不执行此操作,这就是我在上面的代码中使用bool
的原因。您可以自由地使用您喜欢的任何一个,除非您通常在处理任何需要BOOL
的内容时使用BOOL
,特别是在重写子类中的方法或实现协议时。您可以自由地来回转换,但不是无损转换(因为bool
将如上所述更改非零值。)
当用户点击您的按钮时,获取输入字段的stringValue
,使用合理的编码(例如UTF-8)和该字符串调用stringOfBitsFromEncoding:ofString:
,并将结果字符串设置为输出字段的新stringValue
。
额外功劳:添加一个弹出按钮,用户可以使用该按钮选择编码。
额外额外功劳:使用所有可用编码填充弹出按钮,无需硬编码或刻录清单。