iOS hex addition - ios

i have an NSString with hex value
NSString* someString = #"AAB827EB5A6E225CAA
i want to extract from b (the second char) to 2 (-5 char)
make an addition of all extracted char and i have to find the 5C as result (-4 and -3 char)
i have tried this :
NSMutableArray *hex = [[NSMutableArray alloc]init];
unichar firstChar = [[someString uppercaseString] characterAtIndex:0];
unichar seconChar = [[someString uppercaseString] characterAtIndex:1];
unichar lastChar = [[someString uppercaseString] characterAtIndex:[print length]-1];
unichar beforeLastChar = [[someString uppercaseString] characterAtIndex:[print length]-2];
if (firstChar == 'A' && seconChar == 'A' && lastChar =='A' && beforeLastChar=='A') {
for (int i=2;i< [print length]-4; i++) {
NSString *decim =[NSString stringWithFormat:#"%hu",[someString characterAtIndex:i]];
[hex addObject:decim];
}
NSLog(#"hex : %#",hex);
}
but the log is
hex : (
98,
56,
50,
55,
101,
98,
53,
97,
54,
101,
50,
50, )
i've tried to covert it to string then int for calculation but if i can avoid conversion and continue with hex i would prefer
thanks for help

The code could be probably simplifed even more but one possibility:
NSString *someString = #"AAB827EB5A6E225CAA";
// I have improved a bit your check for prefix and suffix
if ([someString hasPrefix:#"AA"] && [someString hasSuffix:#"AA"]) {
NSMutableArray *hexNumbers = [[NSMutableArray alloc] init];
for (int i = 2; i < [someString length] - 4; i++) {
unichar digit = [someString characterAtIndex:i];
NSUInteger value;
// we have to convert the character into its numeric value
// we could also use NSScanner for it but this is a simple way
if (digit >= 'A') {
value = digit - 'A' + 10;
} else {
value = digit - '0';
}
// add the value to the array
[hexNumbers addObject:#(value)];
}
NSLog(#"hex : %#", hexNumbers);
// a trick to get the sum of an array
NSNumber *sum = [hexNumbers valueForKeyPath:#"#sum.self"];
// print the sum in decadic and in hexadecimal
NSLog(#"Sum: %#, in hexa: %X", sum, [sum integerValue]);
}

Related

who can tell me what the function's affect?

The first method is:
-(NSData *)stringToAddBytes:(NSString*)addString
{
int length = (int)[addString length];
if(length < 2)
{
return nil;
}
Byte buf[length / 2];
for(int i = 0 ;i < length/2 ;i++)
{
NSString *str = [addString substringWithRange:NSMakeRange(i * 2, 2)];
Byte b = [self hexStringToByte:str];
buf[i]=b;
}
NSData * myD = [[NSData alloc]initWithBytes:buf length:length/2];
return myD;
}
THe method that the first method called.
-(Byte)hexStringToByte:(NSString*)str
{
NSArray *charArray = [[NSArray alloc]initWithObjects:#"0",#"1",#"2",#"3",#"4",#"5",#"6",#"7",#"8",#"9",
#"A",#"B",#"C",#"D",#"E",#"F",nil];
NSString *str1 = [str substringWithRange:NSMakeRange(0, 1)];
int num1 = (int)[charArray indexOfObject:str1];
NSString *str2 = [str substringWithRange:NSMakeRange(1, 1)];
int num2 = (int)[charArray indexOfObject:str2];
Byte b = num1*16+num2;
return b;
}
Thank you for your answer.It looks change large char to small char.
hexStringToByte: wil convert string with hexadecimal number representation (example #"FF") to Byte value (in this example 255).
stringToAddBytes: uses hexStringToByte: to create NSData of bytes breaking addString into two letter peases and converting them to Byte values.
In other words, this is string serialization.
Example:
// 255 = 0xFF
// 170 = 0xAA
// 136 = 0x88
NSString* addString = #"FFAA88";
NSData* data = [self stringToAddBytes:addString];
// data will be [255, 170, 136]
Be aware that NSData is not an array, instead, it represents a raw object.

How to put a Hex string to byte array in Objective C [duplicate]

Is there any method in Objective-C that converts a hex string to bytes? For example #"1156FFCD3430AA22" to an unsigned char array {0x11, 0x56, 0xFF, ...}.
Fastest NSString category implementation that I could think of (cocktail of some examples):
- (NSData *)dataFromHexString {
const char *chars = [self UTF8String];
int i = 0, len = self.length;
NSMutableData *data = [NSMutableData dataWithCapacity:len / 2];
char byteChars[3] = {'\0','\0','\0'};
unsigned long wholeByte;
while (i < len) {
byteChars[0] = chars[i++];
byteChars[1] = chars[i++];
wholeByte = strtoul(byteChars, NULL, 16);
[data appendBytes:&wholeByte length:1];
}
return data;
}
It is close to 8 times faster than wookay's solution. NSScanner is quite slow.
#interface NSString (NSStringHexToBytes)
-(NSData*) hexToBytes ;
#end
#implementation NSString (NSStringHexToBytes)
-(NSData*) hexToBytes {
NSMutableData* data = [NSMutableData data];
int idx;
for (idx = 0; idx+2 <= self.length; idx+=2) {
NSRange range = NSMakeRange(idx, 2);
NSString* hexStr = [self substringWithRange:range];
NSScanner* scanner = [NSScanner scannerWithString:hexStr];
unsigned int intValue;
[scanner scanHexInt:&intValue];
[data appendBytes:&intValue length:1];
}
return data;
}
#end
/// example
unsigned char bytes[] = { 0x11, 0x56, 0xFF, 0xCD, 0x34, 0x30, 0xAA, 0x22 };
NSData* expectedData = [NSData dataWithBytes:bytes length:sizeof(bytes)];
NSLog(#"data %#", [#"1156FFCD3430AA22" hexToBytes]);
NSLog(#"expectedData isEqual:%d", [expectedData isEqual:[#"1156FFCD3430AA22" hexToBytes]]);
The scanHexInt: and similar methods of NSScanner might be helpful in doing what you want, but you'd probably need to break the string up into smaller chunks first, in which case doing the translation manually might be simpler than using NSScanner.
Not in the way you are doing it. You'll need to write your own method to take every two characters, interpret them as an int, and store them in an array.
Modified approach,
/* Converts a hex string to bytes.
Precondition:
. The hex string can be separated by space or not.
. the string length without space or 0x, must be even. 2 symbols for one byte/char
. sample input: 23 3A F1 OR 233AF1, 0x23 0X231f 2B
*/
+ (NSData *) dataFromHexString:(NSString*)hexString
{
NSString * cleanString = [Util cleanNonHexCharsFromHexString:hexString];
if (cleanString == nil) {
return nil;
}
NSMutableData *result = [[NSMutableData alloc] init];
int i = 0;
for (i = 0; i+2 <= cleanString.length; i+=2) {
NSRange range = NSMakeRange(i, 2);
NSString* hexStr = [cleanString substringWithRange:range];
NSScanner* scanner = [NSScanner scannerWithString:hexStr];
unsigned int intValue;
[scanner scanHexInt:&intValue];
unsigned char uc = (unsigned char) intValue;
[result appendBytes:&uc length:1];
}
NSData * data = [NSData dataWithData:result];
[result release];
return data;
}
/* Clean a hex string by removing spaces and 0x chars.
. The hex string can be separated by space or not.
. sample input: 23 3A F1; 233AF1; 0x23 0x3A 0xf1
*/
+ (NSString *) cleanNonHexCharsFromHexString:(NSString *)input
{
if (input == nil) {
return nil;
}
NSString * output = [input stringByReplacingOccurrencesOfString:#"0x" withString:#""
options:NSCaseInsensitiveSearch range:NSMakeRange(0, input.length)];
NSString * hexChars = #"0123456789abcdefABCDEF";
NSCharacterSet *hexc = [NSCharacterSet characterSetWithCharactersInString:hexChars];
NSCharacterSet *invalidHexc = [hexc invertedSet];
NSString * allHex = [[output componentsSeparatedByCharactersInSet:invalidHexc] componentsJoinedByString:#""];
return allHex;
}
First attempt in Swift 2.2:
func hexStringToBytes(hexString: String) -> NSData? {
guard let chars = hexString.cStringUsingEncoding(NSUTF8StringEncoding) else { return nil}
var i = 0
let length = hexString.characters.count
let data = NSMutableData(capacity: length/2)
var byteChars: [CChar] = [0, 0, 0]
var wholeByte: CUnsignedLong = 0
while i < length {
byteChars[0] = chars[i]
i+=1
byteChars[1] = chars[i]
i+=1
wholeByte = strtoul(byteChars, nil, 16)
data?.appendBytes(&wholeByte, length: 1)
}
return data
}
Or, as an extension on String:
extension String {
func dataFromHexString() -> NSData? {
guard let chars = cStringUsingEncoding(NSUTF8StringEncoding) else { return nil}
var i = 0
let length = characters.count
let data = NSMutableData(capacity: length/2)
var byteChars: [CChar] = [0, 0, 0]
var wholeByte: CUnsignedLong = 0
while i < length {
byteChars[0] = chars[i]
i+=1
byteChars[1] = chars[i]
i+=1
wholeByte = strtoul(byteChars, nil, 16)
data?.appendBytes(&wholeByte, length: 1)
}
return data
}
}
This is a continuous work-in-progress, but appears to work well so far.
Further optimizations and a more in-depth discussion can be found on Code Review.
Several solution is returned wrong value if the string like this
"DBA"
The correct data for "DBA" string is "\x0D\xBA" (int value : 3514)
if you got a data is not like this "\x0D\xBA" it mean you got a wrong byte because the value will be different, for example you got data like this "\xDB\x0A" the int value is 56074
Here is rewrite the solution:
+ (NSData *)dataFromHexString:(NSString *) string {
if([string length] % 2 == 1){
string = [#"0"stringByAppendingString:string];
}
const char *chars = [string UTF8String];
int i = 0, len = (int)[string length];
NSMutableData *data = [NSMutableData dataWithCapacity:len / 2];
char byteChars[3] = {'\0','\0','\0'};
unsigned long wholeByte;
while (i < len) {
byteChars[0] = chars[i++];
byteChars[1] = chars[i++];
wholeByte = strtoul(byteChars, NULL, 16);
[data appendBytes:&wholeByte length:1];
}
return data;
}

Creating Random Alpha numeric on IOS

i'm java programmer that 'must' move on to obj-C for a while,
i got some confuse when generating random alphanumeric code... here my javacode:
PS: i want to generate code like this :Gh12PU67, AC88pP13, Bk81gH89
private String generateCode(){
String code = "";
Random r = new Random();
char[] c = new char[]{'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
for(int i = 0; i<4; i++){
int uplow = r.nextInt(2);
String temp = ""+ c[r.nextInt(c.length)];
if(uplow==1)
code = code + temp.toUpperCase();
else
code = code + temp;
if((i+1)%2==0){
code += r.nextInt(10);
code += r.nextInt(10);
}
}
return code;
}
then i create on OBJ-C
-(void)generateCode{
NSString *alphabet = #"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXZY0123456789";
NSMutableString *s = [NSMutableString stringWithCapacity:4];
for (NSUInteger i = 0U; i < 4; i++) {
u_int32_t r = arc4random() % [alphabet length];
unichar c = [alphabet characterAtIndex:r];
[s appendFormat:#"%C", c];
}
NSLog(#"s-->%#",s);
}
but i got "HpNz" for result AC88pP13 insted that hve pattern String,string, numeric,numeric, lowescase string,numeric,numeric...
that case screw my life for 3 days...
Your Objective-C code looks good, but (as #Wain correctly said in a comment above),
the Java function function contains logic to insert 2 digits after 2 letters, which you
have not replicated in the Objective-C method.
I would make that logic slightly less obscure and write it as
- (void)generateCode
{
static NSString *letters = #"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXZY";
static NSString *digits = #"0123456789";
NSMutableString *s = [NSMutableString stringWithCapacity:8];
for (NSUInteger i = 0; i < 2; i++) {
uint32_t r;
// Append 2 random letters:
r = arc4random_uniform((uint32_t)[letters length]);
[s appendFormat:#"%C", [letters characterAtIndex:r]];
r = arc4random_uniform((uint32_t)[letters length]);
[s appendFormat:#"%C", [letters characterAtIndex:r]];
// Append 2 random digits:
r = arc4random_uniform((uint32_t)[digits length]);
[s appendFormat:#"%C", [digits characterAtIndex:r]];
r = arc4random_uniform((uint32_t)[digits length]);
[s appendFormat:#"%C", [digits characterAtIndex:r]];
}
NSLog(#"s-->%#",s);
}
Remark (from the man page):
arc4random_uniform(length) is preferred over arc4random() % length,
as it avoids "modulo bias" when the upper bound is not a power of two.
Remark: A more verbatim translation of the Java code code += r.nextInt(10);
to Objective-C would be
r = arc4random_uniform(10);
[s appendString:[#(r) stringValue]];
which creates a NSNumber object #(r) from the random number, and then
converts that to a string.
if you want a secure random string you should use this code:
#define ASCII_START_NUMERS 0x30
#define ASCII_END_NUMERS 0x39
#define ASCII_START_LETTERS_A 0x41
#define ASCII_END_LETTERS_Z 0x5A
#define ASCII_START_LETTERS_a 0x61
#define ASCII_END_LETTERS_z 0x5A
-(NSString *)getRandomString:(int)length {
NSMutableString *result = [[NSMutableString alloc]init];
while (result.length != length) {
NSMutableData* data = [NSMutableData dataWithLength:1];
SecRandomCopyBytes(kSecRandomDefault, 1, [data mutableBytes]);
Byte currentChar = 0;
[data getBytes:&currentChar length:1];
NSString *s = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if (currentChar > ASCII_START_NUMERS && currentChar < ASCII_END_NUMERS) { // 0 to 0
[result appendString:s];
continue;
}
if (currentChar > ASCII_START_LETTERS_A && currentChar < ASCII_END_LETTERS_Z) { // A to Z
[result appendString:s];
continue;
}
if (currentChar > ASCII_START_LETTERS_a && currentChar < ASCII_END_LETTERS_z) { // a to z
[result appendString:s];
continue;
}
}
return result;
}

Base 62 conversion in Objective-C

I spent much too much time trying to find an implementation for base 62 conversion for Objective-C. I am sure this is a terrible example and there must be an elegant, super-efficient way to do this, but this works, please edit or answer to improve it! But I wanted to help people searching for this to have something that will work. There doesn't appear to be anything specific to be found for an Objective-C implementation.
#implementation Base62Converter
+(int)decode:(NSString*)string
{
int num = 0;
NSString * alphabet = #"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
for (int i = 0, len = [string length]; i < len; i++)
{
NSRange range = [alphabet rangeOfString:[string substringWithRange:NSMakeRange(i,1)]];
num = num * 62 + range.location;
}
return num;
}
+(NSString*)encode:(int)num
{
NSString * alphabet = #"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
NSMutableString * precursor = [NSMutableString stringWithCapacity:3];
while (num > 0)
{
[precursor appendString:[alphabet substringWithRange:NSMakeRange( num % 62, 1 )]];
num /= 62;
}
// http://stackoverflow.com/questions/6720191/reverse-nsstring-text
NSMutableString *reversedString = [NSMutableString stringWithCapacity:[precursor length]];
[precursor enumerateSubstringsInRange:NSMakeRange(0,[precursor length])
options:(NSStringEnumerationReverse |NSStringEnumerationByComposedCharacterSequences)
usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
[reversedString appendString:substring];
}];
return reversedString;
}
#end
Your code is fine. If anything, make it more generic. Here is a recursive version for any base (same code):
#import <Foundation/Foundation.h>
#interface BaseConversion : NSObject
+(NSString*) formatNumber:(NSUInteger)n toBase:(NSUInteger)base;
+(NSString*) formatNumber:(NSUInteger)n usingAlphabet:(NSString*)alphabet;
#end
#implementation BaseConversion
// Uses the alphabet length as base.
+(NSString*) formatNumber:(NSUInteger)n usingAlphabet:(NSString*)alphabet
{
NSUInteger base = [alphabet length];
if (n<base){
// direct conversion
NSRange range = NSMakeRange(n, 1);
return [alphabet substringWithRange:range];
} else {
return [NSString stringWithFormat:#"%#%#",
// Get the number minus the last digit and do a recursive call.
// Note that division between integer drops the decimals, eg: 769/10 = 76
[self formatNumber:n/base usingAlphabet:alphabet],
// Get the last digit and perform direct conversion with the result.
[alphabet substringWithRange:NSMakeRange(n%base, 1)]];
}
}
+(NSString*) formatNumber:(NSUInteger)n toBase:(NSUInteger)base
{
NSString *alphabet = #"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; // 62 digits
NSAssert([alphabet length]>=base,#"Not enough characters. Use base %ld or lower.",(unsigned long)[alphabet length]);
return [self formatNumber:n usingAlphabet:[alphabet substringWithRange:NSMakeRange (0, base)]];
}
#end
int main(int argc, char *argv[]) {
#autoreleasepool {
NSLog(#"%#",[BaseConversion formatNumber:3735928559 toBase:16]); // deadbeef
return EXIT_SUCCESS;
}
}
A Swift 3 version: https://gist.github.com/j4n0/056475333d0ddfe963ac5dc44fa53bf2
You could improve your encode method in such a way that reversing the final string is not necessary:
+ (NSString *)encode:(NSUInteger)num
{
NSString *alphabet = #"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
NSUInteger base = [alphabet length];
NSMutableString *result = [NSMutableString string];
while (num > 0) {
NSString *digit = [alphabet substringWithRange:NSMakeRange(num % base, 1)];
[result insertString:digit atIndex:0];
num /= base;
}
return result;
}
Of course, this could also be generalized for arbitrary bases or alphabets, as suggested by #Jano in his answer.
Note that this method (as well as your original encode method) returns an empty string for num = 0, so you might want to consider this case separately (or just replace while (num > 0) { ... } by do { ... } while (num > 0).
For more efficiency, one could avoid all intermediate NSString objects altogether, and work with plain C strings:
+ (NSString *)encode:(NSUInteger)num
{
static const char *alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
NSUInteger base = 62;
char result[20]; // sufficient room to encode 2^64 in Base-62
char *p = result + sizeof(result);
*--p = 0; // NULL termination
while (num > 0) {
*--p = alphabet[num % base];
num /= base;
}
return [NSString stringWithUTF8String:p];
}

Parsing a NSString to a byte array

I need to parse an NSString to a byte array and am having some trouble doing it. I have a padded byte array in a method and convert that into a mutablestring, then I have a method that needs to place those numbers back into a byte array.
In C# it would be as simple as:
do
{
val = byte.Parse(str.Substring(i, 3));
byteArr[j++] = val;
i += 3;
}
Here is the code snippit Note** Ive been trying a lot of different things in the do loop so its a mess in there right now:
-(NSData*) StrToByteArray: (NSString*)str
{
NSLog(#"StrToByteArray. String: %#", str);
if([str length]==0)
NSLog(#"Invailid String");
int val;
Byte byteArr[[str length]/3];
int i = 0;
int j = 0;
NSRange range;
do {
range = NSMakeRange(i, 3);
val = (int)[str substringFromIndex:i];
NSLog(#"StrToByteArray. VAR: %i", val);
byteArr[j++] = val;
NSLog(#"byteArr: %i",byteArr[i]);
i+=3;
}while(i<str.length);
NSData* wrappedByteArr = [NSData dataWithBytes:&byteArr length: sizeof(byteArr)];
return wrappedByteArr;
}
Here is the loop that makes the padded string:
for(int i = 0; i<=len;i++)
{
val = byteArr[i];
NSLog(#"byteArr to string original: %i", val);
if(val<(Byte)10)
{
[tempStr appendString:(#"00")];
[tempStr appendString:[NSString stringWithFormat:#"%d",val]];
}
else if(val<(Byte)100)
{
[tempStr appendString:(#"0")];
[tempStr appendString:[NSString stringWithFormat:#"%d",val]];
}
else {
[tempStr appendString:[NSString stringWithFormat:#"%d",val]];
}
}
NSLog(#"string: %#", tempStr);
return tempStr;
Take 2
Now that I know what the data looks like and how you want to parse it, I would approach it like this:
- (NSData *) parseStringToData:(NSString *) str
{
if ([str length] % 3 != 0)
{
// raise an exception, because the string's length should be a multiple of 3.
}
NSMutableData *result = [NSMutableData dataWithLength:[str length] / 3];
unsigned char *buffer = [result mutableBytes];
for (NSUInteger i = 0; i < [result length]; i++)
{
NSString *byteString = [str substringWithRange:NSMakeRange(i * 3, 3)];
buffer[i] = [byteString intValue];
}
return result;
}
Edit:
Your padding method could be simplified as well by providing the correct format specifier that automatically pads integers.
for(int i = 0; i<=len;i++)
{
val = byteArr[i];
NSLog(#"byteArr to string original: %i", val);
[tempStr appendFormat:#"%03d", val];
}

Resources