Get invisible decimal value in NSString objc - objective-c

I have a string with random names with an invisible decimal value as prefix . The decimal = the names length. I need to retrieve the names. Obviously they are of different length. I want the names in an array so my idea is to use stringByReplacingOccurrencesOfString:withString. I implement the word "trunk" at the beginning and end of names. Though I am having trouble accessing the index corresponding at the end of the name (decimal value), here is my code :
trimmed1 = [[trimmed1 stringByReplacingOccurrencesOfString:sp withString:#"trunk"]mutableCopy];
NSString *trunk = #"trunk%d";// add the ghost decimal at the end of prefix in order to get its value;
NSRange range =[trimmed1 rangeOfString:trunk];
int ghost= [trunk characterAtIndex:5];
NSMutableString *mu = [NSMutableString stringWithString:trimmed1];
[mu insertString : #"trunk" atIndex :range.location+range.length+ ghost];
I get the error [__NSCFString insertString:atIndex:]: Range or index out of bounds.

You are misunderstanding what %d means.
In a format used for creating a string it means "insert the value of an integer argument formatted as a string".
When matching one string against another it means "match the characters %d", I.e. it is not special in anyway.
You are getting an error as your string does not contain the characters "trunk%d". If you check the return value of rangeOfString: you will find it is returning a failure indication - read the documentation for how to test for that value.
For the simple task of matching an arbitrary decimal number trying looking at the NSString method rangeOfCharactersFromSet:.
You can also solve this problem with the classes NSScanner and NSRegularExpression.
HTH

Related

Compare strings with numeric values

I have searched many hours how to compare this two strings ( and have str1 equal str2 == YES):
This string is given by a user input in my interface (search bar)
NSString *str1 = #"11,2";
This string is a property of my model object
NSString *str2 = #"11.2";
i have tested this but it's not working
if ([str1 rangeOfString:str2 options:options range:NSMakeRange(0, [str1 length]) locale:[NSLocale currentLocale]].location == NSNotFound
Witch is the best solution to compare the two NSStrings and have str1 equal str2 that returns YES ?
Edit :
I know that i can do it simply by replacing the "," by "." and the do the comparaison, but i am searching an elegant solution that take the fact that 11.2 and 11,2 are the same in different locales ( using NSDecimalNumber for example).
You've just essentially answered your own question - use NSDecimalNumber to parse the user's input according to the current locale. Parse your string using your locale (or better yet keep it as a floating point value. That should solve your problem apart from the standard issue that comparing floating point values for exact equality is not advised, though NSDecimalNumber may help you address that. HTH
If you can trust user's locale settings on the machine you could use a NSScanner instance to scan the number string and use a float or double as your model so that you can perform proper searching.

Working with big numbers in Objective-C?

I need to convert values like 1393443048683555715 to HEX. But, first of all, i cann't display it as decimal using NSLog(), for example.
Ok, it works:
NSLog(#"%qu", 1393443048683555706);
But what about converting to HEX. What type i have to use to store this big value?
NSLog([NSString stringWithFormat: #"%x", 1393443048683555706]);
// result eb854b7a. It's incorrect result!
but i forgot to say that this big number represented as string #"1393443048683555706" (not int)
You can use %qi and %qu format specifiers with NSLog to display 64-bit integers. Your constant appears to fit in 64-bit signed number, with the limits of:
[−9223372036854775808 to 9223372036854775807]
The "x" format specifier is for 32-bit numbers; you need to use either "qx" or "qX" (depending on whether you want the letter values to be uppercase or not). These are the formatters for unsigned long long values, see:
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html#//apple_ref/doc/uid/TP40004265-SW1
Next, you should not pass a string as you have done above directly to NSLog - this can cause a crash.
NSLog(string); // bad!!
NSLog(#"%#", string); // good
So if your value comes as a string, you'll want to do this:
NSString *longNumber = #"1393443048683555706";
NSLog(#"%qx", [longNumber longLongValue]);
If the string value can't be coerced to a number, longLongValue will return 0. I'll leave it to you do handle the error (and bounds) checking - see NSString for details.
If you want to save the hex value as a string, do this:
NSString *hexRepresentation = [NSString stringWithFormat:#"%qx", [longNumber longLongValue]];
Again, best to take care for error handling.

Help in padding numerical strings

I am trying to generate a numerical string by padding the number with zeroes to the left.
0 would become 00000
1 would become 00001
10 would become 00010
I want to create five character NSString by padding the number with zeroes.
I read this Create NSString by repeating another string a given number of times but the output is an NSMutableString.
How can I implement this algorithm with the output as an NSString?
Best regards.
You can accomplish this by calling
[NSString stringWithFormat:#"%05d", [theNumber intValue]];
where theNumber is the NSString containing the number you want to format.
For further reading, you may want to look at Apple's string formatting guide or the Wikipedia entry for printf.
One quick & simple way to do it:
unsigned int num = 10; // example value
NSString *immutable = [NSString stringWithFormat:#"%.5u", num];
If you actually really want to use the long-winded approach from the example you read, you can send a “copy” message to a mutable string to get an immutable copy. This holds for all mutable types.

Objective-C Converting an integer to a hex value

I've got a dictionary initialized like so...
keyDictionary = [[NSDictionary dictionaryWithObjects:values forKeys:keys]retain];
where keys is an NSArray of the alphabet and other characters and values is an NSArray of unsigned chars, which are the USB hex keycodes for those characters.
The USB key codes are hex values that range from 0x04 to 0xE7. I'm trying to create a map between these two depending on what key is pressed on the keyboard.
The values array is created like so...
NSArray *values = [NSArray arrayWithObjects:
[NSNumber numberWithUnsignedChar:0x04]/*A*/,
[NSNumber numberWithUnsignedChar:0x05]/*B*/, /*ETC*/];
So ideally when I run this code...
where character == #"I"
- (uint8) getUSBCode:(NSString *)character
{
NSNumber *val = [keyDictionary objectForKey:character];
return (uint8)[val unsignedCharValue];
}
I would expect to get back 0x0C, but I'm getting 12 back as an int (which after I thought about it, makes sense). I need the hex value preserved. I do NOT need a string value. I need a straight conversion to the hex value or a better way to store
uint8 is just a typedef unsigned char.
EDIT I was not clear when I posted this earlier. Here's what I need.
I need the hex value of these codes because they are being sent over the internal company network. In addition, the pressed key's value is being converted from big endian (or little, it's escaping me right now which one it is) to the other, then being transmitted over an internal network. I understand that these values are stored in binary, but I need to transmit them in hex.
Also, I stated I was getting 12 back from the function. I was reading 12 from the debugger, not actually getting the value. That might be why I was getting confused.
12 (in base 10) is 0x0c.
If you want to print it out in hex, use the %x format specifier e.g.
NSLog(#"Hex value of char is 0x%02x", (unsigned int) c);
If you want to see it in hex in the debugger (assuming Xcode 3.2.x) right click on the variable and select hexadecimal as the format.
You know that an int is stored in binary (i.e. the 'hex' value is always and never preserved), so I'm interpreting your question as pertaining to printing to the screen.
You should be able to use a format specifier for that -- something like %0x.
The value that's returned from your -getUSBCode: method isn't two decimal digits, it's one eight-bit byte. Both "12" and "0x0C" are strings that represent that byte's value, so saying you want "0x0C" but don't want a string is a contradiction.

Xcode - EXEC_BAD_ACCESS when concatenting a large string

I'm getting a EXEC_BAD_ACCESS when concatenting a large string.
I've read from a feed and to create my webview I build up my string like:
NSString *pageData = #"<h1>header</h1>";
pageData = [pageData stringByAppendingFormat#"<p>"];
pageData = [pageData stringByAppendingFormat#"self.bodyText"];
pageData = [pageData stringByAppendingFormat#"</p>"];
etc
The problem I've got is self.bodytext is 21,089 characters with spaces when I do a count on word.
Is there a better method for doing this?
Thanks
You would definitely want to use NSMutableString for something like this:
NSMutableString * pageData = [NSMutableString stringWithCapacity:0];
[pageData appendFormat:#"<h1>header</h1>"];
[pageData appendFormat:#"<p>"];
...
NSMutableString is designed for this kind of sequential concatenation, where the basic NSString class is really not meant to be used in this manner. Your original code would actually allocate a new NSString every time you called stringByAppendFormat:, and then procede to copy into it all of the thousands of characters you had already appended. This could easily result in an out of memory error, since the size of the temporary strings would be growing exponentially as you add more and more calls.
Using NSMutableString will not re-copy all of the string data when you call appendFormat:, since the mutable string maintains an internal buffer and simply tacks new strings on to the end of it. Depending on the size of your string, you may want to reserve a huge chunk of memory ahead of time (use a meaningful number for the ...WithCapacity: argument). But there is no need to go that route unless you actually run into performance issues.
There are a few problems with your sample code:
You should be using a NSMutableString to build up an output string by appending multiple parts. NSString is an immutable class which means that each time you call stringByAppendingFormat: you are incurring the overhead of creating an additional new NSString object which will need to be collected and released by the autorelease pool.
NSMutableString * pageData = [NSMutableString stringWithCapacity:0];
You should use appendString: on your NSMutableString to append content, instead of stringByAppendingFormat: or appendFormat:. The format methods are intended for creating new strings based on a format specifier which includes special fields as placeholders. See Formatting String Objects for more details. When you're using stringByAppendingFormat: with just a literal string like your code has, you are incurring the overhead of parsing the string for the non-existant placeholders, and more importantly, if the string happens to have a placeholder (or something that looks like one) in it, you'll end up with the EXEC_BAD_ACCESS crash that you are getting. Most likely this happening when your bodyText is appended. Thus if you simply want to append a '' to your NSMutableString do something like this:
[pageData appendString:#"<p>"];
If you want to append the contents of the self.bodyText property to the string, you shouldn't put the name of the property inside of a string literal (i.e. #"self.bodyText" is the literal string "self.bodyText", not the contents of the property. Try:
[pageData appendString:self.bodyText];
As an example, you could actually combine all three lines of your sample code by using a format specification:
pageData = [pageData stringByAppendingFormat:#"<p>%#</p>", self.bodyText];
In the format specification %# is a placeholder that means insert the result of sending the description or descriptionWithLocale: message to the object. For an NSString this is simply the contents of the string.
I doubt the length of the string is really a problem. A 50,000-character string is only about 100 KB. But you want to be very careful about using format strings. If your string contains something that looks like a formatting specifier, there had better be a corresponding argument or you'll get garbage if you're lucky and a crash if you're not. I suspect this is the error, since there is no other obvious problem from your description. Be careful about what you put in there, and avoid ever putting dynamic text in a format string — just put a %# in the format string and pass the dynamic text as an argument.
Use appendString: instead of appendFormat: when dealing with arbitrary strings.
pageData = [pageData stringByAppendingString:#"<p>"];
pageData = [pageData stringByAppendingString:#"self.bodyText"];
pageData = [pageData stringByAppendingString:#"</p>"];
or do not use an arbitrary string as the format:
pageData = [pageData stringByAppendingFormat:#"<p>%#</p>" , #"self.bodyText"];
If you are building the string up in pieces, use NSMutableString instead of several stringBy calls.
Remember that % is a special character for formatted strings and for url escapes, so if bodyText contains a url it could easily cause a crash.