Char (hex representation) from NSString - objective-c

I have a C char array in iOS that looks like this:
static char aStr[MY_STRING_LENGTH] = {0xc0,0xa7,0x82};
When I inspect it on the console (p aStr), I get output that looks like:
(char [MY_STRING_LENGTH]) $1 = "\xc0\xa7\x82"
and that is all fine. However, I need to put that original string in a plist, and read it in as config data. If I type my entry in the plist as a NSString, how can I get the C char array out with the same values? So far, everything I have tried seems to translate the hex values into something else.
I have tried things like:
NSString *newStr = [stringFromPlist UTF8String];
Or breaking the NSString into an array with:
NSArray *arr = [stringFromPlist componentsSeparatedByString:#","];
and then iterating and converting with:
char newArr[MY_STRING_LENGTH];
for (int i = 0; i < MY_STRING_LENGTH; i++) {
newArr[i] = [arr[i] UTF8String];
}
but so far nothing seems to do what I need. I keep ending up with values in the char array that contain the "0x" instead of the "\x".
My C chops are FAR too rusty for this, so I am hoping someone can point out my error.
Cheers!

I don't know if there is a more elegant solution, but you could try:
NSString *stringFromPlist = #"0xc0,0xa7,0x82";
NSArray *arr = [stringFromPlist componentsSeparatedByString:#","];
char newArr[MY_STRING_LENGTH];
for (int i = 0; i < MY_STRING_LENGTH; i++) {
unsigned result = 0;
NSScanner *scanner = [NSScanner scannerWithString:arr[i]];
[scanner scanHexInt:&result];
newArr[i] = result;
}

Related

Convert one NSArray filled with NSStrings to a UTF8String vector

So I was wondering, is there some quick way of converting one NSArray filled with NSStrings to the equivalent UTF8string values?
I want to store some parameter configuration in a NSArray and then use them in a function that takes (int argv, const char *argv[]) as arguments.
I implemented this in a convoluted way
int argc = [gameParameters count];
const char **argv = (const char **)malloc(sizeof(const char*)*argc);
for (int i = 0; i < argc; i++) {
argv[i] = (const char *)malloc(sizeof(char)*[[gameParameters objectAtIndex:i] length]+1);
strncpy((void *)argv[i], [[gameParameters objectAtIndex:i] UTF8String], [[gameParameters objectAtIndex:i] length]+1);
}
but I'm not really happy with and cleaning up memory is tedious.
Do you know a better way to achieve this result?
Your current implementation is not correct if the string contains non-ASCII characters. For example, the string #"é" (SMALL LETTER E WITH ACUTE) has length 1, but the UTF-8 sequence "C3 A9" has 2 bytes. Your code would not allocate enough memory for that string.
(In other words: [string length] returns the number of Unicode characters in the string, not the number of bytes of the UTF-8 representation.)
Using strdup(), as suggested by Kevin Ballard, would solve this problem:
argv[i] = strdup([[gameParameters objectAtIndex:i] UTF8String]);
But you should also check if duplicating the strings is necessary at all. If you call the function in the current autorelease context, the following would be sufficient:
int argc = [gameParameters count];
const char **argv = (const char **)malloc(sizeof(const char*)*argc);
for (int i = 0; i < argc; i++) {
argv[i] = [[gameParameters objectAtIndex:i] UTF8String];
}
yourFunction(argc, argv);
free(argv);

Convert text in an NSString to it's 8-byte ASCII Hex equivalent, and store back in an NSString

I want to convert the NSString #"2525" to the NSString #"0032003500320035". The 8-byte ASCII value for "2" in hex is "0032" and for "5" it's "0035". Just to get the c-string equivalent, I tried...
const char *pinUTF8 = [pin cStringUsingEncoding:NSASCIIStringEncoding];
...but as you can see I'm struggling with this and I knew it wasn't going to be that easy. Any tips?
Thanks so much in advance for your wisdom!
Try this:
NSString *str = #"2525";
const char *s = [str cStringUsingEncoding:NSASCIIStringEncoding];
size_t len = strlen(s);
NSMutableString *asciiCodes = [NSMutableString string];
for (int i = 0; i < len; i++) {
[asciiCodes appendFormat:#"%04x", (int)s[i]];
}
NSLog(#"%#", asciiCodes);

Convert NSString to C string, increment and come back to NSString

I'm trying to develop a simple application where i can encrypt a message. The algorithm is Caesar's algorithm and for example, for 'Hello World' it prints 'KHOOR ZRUOG' if the increment is 3 (standard).
My problem is how to take each single character and increment it...
I've tried this:
NSString *text = #"hello";
int q, increment = 3;
NSString *string;
for (q = 0; q < [text length]; q++) {
string = [text substringWithRange:NSMakeRange(q, 1)];
const char *c = [string UTF8String] + increment;
NSLog(#"%#", [NSString stringWithUTF8String:c]);
}
very simple but it doesn't work.. My theory was: take each single character, transform into c string and increment it, then return to NSString and print it, but xcode print nothing, also if i print the char 'c' i can't see the result in console. Where is the problem?
First of all, incrementing byte by byte only works for ASCII strings. If you use UTF-8, you will get garbage for glyphs that have multi-byte representations.
With that in mind, this should work (and work faster than characterAtIndex: and similar methods):
NSString *foo = #"FOOBAR";
int increment = 3;
NSUInteger bufferSize = [foo length] + 1;
char *buffer = (char *)calloc(bufferSize, sizeof(char));
if ([foo getCString:buffer maxLength:bufferSize encoding:NSASCIIStringEncoding]) {
int bufferLen = strlen(buffer);
for (int i = 0; i < bufferLen; i++) {
buffer[i] += increment;
if (buffer[i] > 'Z') {
buffer[i] -= 26;
}
}
NSString *encoded = [NSString stringWithCString:buffer
encoding:NSASCIIStringEncoding];
}
free(buffer);
first of all replace your code with this:
for (q = 0; q < [text length]; q++) {
string = [text substringWithRange:NSMakeRange(q, 1)];
const char *c = [string UTF8String];
NSLog(#"Addr: 0x%X", c);
c = c + increment;
NSLog(#"Addr: 0x%X", c);
NSLog(#"%#", [NSString stringWithUTF8String:c]);
}
Now you can figure out your problem. const char *c is a pointer. A pointer saves a memory address.
When I run this code the first log output is this:
Addr: 0x711DD10
that means the char 'h' from the NSString named string with the value #"h" is saved at address 0x711DD10 in memory.
Now we increment this address by 3. Next output is this:
Addr: 0x711DD13
In my case at this address there is a '0x00'. But it doesn't matter what is actually there because a 'k' won't be there (unless you are very lucky).
If you are happy there is a 0x00 too. Because then nothing bad will happen. If you are unlucky there is something else. If there is something other than 0x00 (or the string delimiter or "end of string") NSString will try to convert it. It might crash while trying this, or it might open a huge security hole.
so instead of manipulating pointers you have to manipulate the values where they point to.
You can do this like this:
for (q = 0; q < [text length]; q++) {
string = [text substringWithRange:NSMakeRange(q, 1)];
const char *c = [string UTF8String]; // get the pointer
char character = *c; // get the character from this pointer address
character = character + 3; // add 3 to the letter
char cString[2] = {0, 0}; // create a cstring with length of 1. The second char is \0, the delimiter (the "end marker") of the string
cString[0] = character; // assign our changed character to the first character of the cstring
NSLog(#"%#", [NSString stringWithUTF8String:cString]); // profit...
}

How to make the fowling data conversion: NSArray to char

Well I'm currently calling a method that requires one char input method, but I the data for it is loaded from a file than putted into an array and then I want to convert one of the array's elements to an const char (all the array's elements are URL's). What basically I'm trying to do is to make the program to load a specific file and then put the lines separately into the array's elements (I mean: 1 line = 1 new array element), and then I made a for loop like this:
NSUInteger nElements = [array count];
int i;
for (i = 0; i<nElements; i++) {
const char* urlName = [[array objectAtIndex:i] cStringUsingEncoding:NSUTF8StringEncoding]; // I don't know if this is correct but don't works :)
}
If it's an array of NSURL objects you'd have to convert them to strings like this:
const char* urlName = [[[array objectAtIndex:i] absoluteString] UTF8String];
Assuming it's an array of NSString, you could do this:
const char* urlName = [[array objectAtIndex:i] UTF8String];

How do I convert NSString with Hexvalue to binary char*?

I have a long hex value stored as a NSString, something like:
c12761787e93534f6c443be73be31312cbe343816c062a278f3818cb8363c701
How do I convert it back into a binary value stored as a char*
This is a little sloppy, but should get you on the right track:
NSString *hexString = #"c12761787e93534f6c443be73be31312cbe343816c062a278f3818cb8363c701";
char binChars[128]; // I'm being sloppy and just making some room
const char *hexChars = [hexString UTF8String];
NSUInteger hexLen = strlen(hexChars);
const char *nextHex = hexChars;
char *nextChar = binChars;
for (NSUInteger i = 0; i < hexLen - 1; i++)
{
sscanf(nextHex, "%2x", nextChar);
nextHex += 2;
nextChar++;
}
There was a thread on this (or on a very similar) hexadecimal conversion topic a couple of weeks back over on one of the Cocoa mailing lists.
I can't reasonably reproduce the full discussion here (long thread), but the message that starts off the thread is here:
http://www.cocoabuilder.com/archive/message/cocoa/2009/5/9/236391
I do wish there were a Cocoa method for this task, but (pending finding that or pending its implementation) the code (by Mr Gecko, posted at http://www.cocoabuilder.com/archive/message/cocoa/2009/5/10/236424) looks like it would work here.
static NSString* hexval(NSData *data) {
NSMutableString *hex = [NSMutableString string];
unsigned char *bytes = (unsigned char *)[data bytes];
char temp[3];
int i = 0;
for (i = 0; i < [data length]; i++) {
temp[0] = temp[1] = temp[2] = 0;
(void)sprintf(temp, "%02x", bytes[i]);
[hex appendString:[NSString stringWithUTF8String: temp]];
}
return hex;
}