Compare strings with numeric values - objective-c

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.

Related

Issues of pointing to same or different objects

Let's see a example:
Scenario 1:
NSString *str1=#"Hello";// str1 points to a literal string #"Hello"
NSString *str2=[[NSString alloc] initWithString:str1];
NSLog(#"%p %p",str1,str2);// str1 and str2 both point to same object
Scenario 2:
NSString *str3=[[NSString alloc] initWithFormat:#"Hello"];
NSString *str4=[[NSString alloc] initWithString:str3];
NSLog(#"%p %p",str3,str4);// str3 and str4 point to different objects
I want to know the difference between scenario 1 and 2.
It is an implementation detail (and indication that there is an optimization that Foundation could do that it isn't).
You should never assume that two objects are equal or unequal based on pointer equality. Pointer equality is only useful for checking if they are literally the same object. isEqual: must be used to check if they are semantically identical.
Under the covers, Foundation knows that #"Hello" is a constant string and creating a second immutable string from a constant string can just return the constant string.
It is assuming that initWithFormat: will produce a non-constant string. The optimization opportunity is that Foundation could, during parsing of the format string, detect that no formatting was done and just return the constant string (I'm kinda surprised it doesn't-- I should file an bugenhancement request).

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.

What is the value of the string #""?

I'm writing an iPhone application that uses a lot of editable text fields. I've been learning a lot about UITextFields and NSStrings by reading various references online, but there are some details that still elude me. When a user puts in an incorrect value for one of my text fields, I throw up an error message and put the text field back to the way it was before their input. For empty text fields, I've been doing this:
theTextField.text = #"";
Is this the best way to do this? I just came up with the idea myself, I don't know if there are any problems with it (other than the fact that it seems to work just fine so far).
Also, does #"" have the same value as a "nil" string? In other words, if I set a string to #"" and then call this:
if (myString) {...}
will the statement return true or false?
One last thing. When an NSString is initialized using this:
NSString *myString = [[NSString alloc] init];
what is that string's Length value?
The important thing to understand here is that an NSString with no characters in it, such as #"" or [[NSString alloc] init] is still a valid object. All the consequences that Nick has stated follow from that.
In Objective-C, any valid object will be "True" in a boolean context;* nil is the only false object value.
Since these strings are valid objects, they do have a length, but because they contain no characters, the length is 0.
There are no problems with assigning an empty string object #"" to another string pointer, such as the text of your text field. Since the string with no characters is still a valid NSString object, this is exactly the same as assigning a string which does happen to have characters.
*Unlike so-called "scripting" languages like Python or Perl, where an empty string or collection evaluates to boolean false.
Using
theTextField.text = #"";
is absolutely ok. There should be no problems at all.
if (#"")
will evaluate to true. #"" is not the same as nil.
The length of
NSString *myString = [[NSString alloc] init];
is 0.
This is not an answer to the question, but may be the answer to what you're trying to do.
If you're wondering whether you have to write if(str && str.length) to cover both nil and empty strings, you don't. You may use just if(str.length), since, in Objective-C, unknown messages to nil will return nil (so [a.b.c.d.e.f doStuff] will be nil if any of those values in the chain is nil). There is thus scarce need for specific nullity checks, unless what you want is precisely to determine nullity.
Check NSString's + string.

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.

How to find out if there is an "." in an NSString?

Have got an
NSString *str = #"12345.6789"
and want to find out if there is that "." character inside of it. I'm afraid that there are ugly char-encoding issues when I would just try to match an #"." against this? How would you do it to make sure it always finds a match if there is one?
I just need to know that there is a dot in there. Everything else doesn't matter.
You can use rangeOfString: message to get the range where your "." is.
The prototype is:
- (NSRange)rangeOfString:(NSString *)aString
You can find more info about this message in: Mac Dev Center
There would be something like this:
NSRange range;
range = [yourstring rangeOfString:#"."];
NSLog(#"Position:%d", range.location);
If you need to, there is another message ( rangeOfString:options: ) where you can add some options like "Case sensitive" and so on.
If [str rangeOfString:#"."] returns anything else than {NSNotFound, 0}, the search string was found in the receiver. There are no encoding issues as NSString takes care of encoding. However, there might be issues if your str is user-provided and could contain a different decimal separator (e.g., a comma). But then, if str really comes from the user, many other things could go wrong with that comparison anyway.
To check . symbol, it will be useful.
if ([[str componentsSeparatedByString:#"."] count]>1) {
NSLog(#"dot is there");
}else{
NSLog(#"dot is not there");
}
If what you really want to do is determine whether the string represents a number with a fractional part, a better solution is to feed the string to a number formatter, then examine the number's doubleValue to see whether it has a fractional part.
For the latter step, one way would be to use the modf function, which returns both the fractional part (directly) and the integral part (by reference). If the fractional part is greater than zero (or some appropriately small fraction below which you're willing to tolerate), then the number has a fractional part.
The reason why this is better is because not everybody writes decimal fractions in the “12345.6789” format. Some countries use a comma instead, and I'm sure that's not the only variation. Let the number formatter handle such cases for you.
I wrote a little method to make things a little more natural if you use this sort of thing a whole bunch in your project:
+(BOOL)seeIfString:(NSString*)thisString ContainsThis:(NSString*)containsThis
{
NSRange textRange = [[thisString lowercaseString] rangeOfString:[containsThis lowercaseString]];
if(textRange.location != NSNotFound)
return YES;
return NO;
}
Enjoy!