Extracting price from string - ios

I am looking for a short and convenient way to extract a product's price from NSString.
I have tried regular expressions, but always found some cases where did not match.
The price can be any number including decimals, 0 and -1 (valid prices: 10, 10.99, -1, 0).
NSString can contain a string like: #"Prod. price: $10.99"
Thanks!

This will match all the examples you have given
-?\d+(\.\d{2})?
Optionally a -, followed by 1-many digits, optionally followed by a decimal point and 2 more digits.
If you've got other numbers that are not prices mixed in to the data then I don't think regex can fulfil your needs.

NSString *originalString = #"Prod. price: $10.99";
NSScanner *scanner = [NSScanner scannerWithString:originalString];
NSCharacterSet *numbers = [NSCharacterSet characterSetWithCharactersInString:#"-0123456789"];
[scanner scanUpToCharactersFromSet:numbers intoString:NULL];
double number;
[scanner scanDouble:&number];
number is equal to 10.99
Obviously if you have other numbers before the value you looking for you wont find it.

Assuming that your NSString will always contain the price with $ prep-ended to it, the following regex will match your need
.*?\$(-?(\d+)(.\d{1,2})?)
Once the above regex is matched you can find out match.group(1) to be the price from the NSString.

Related

Objective C: Conversion of large hex to double gives wrong value

I have an issue converting a big hex number 0x500123fb2d414d3d1192a659d4d39dfd to its decimal value
double serialNumberValue = 0;
NSScanner * scanner = [NSScanner scannerWithString:#"0x500123fb2d414d3d1192a659d4d39dfd"];
[scanner scanHexDouble: &serialNumberValue];
NSString* serialNumber = [NSString stringWithFormat: #"%.f", serialNumberValue];
NSLog(#"serialNumber decimal value : %#", serialNumber);
The result I get is: 106344161744262488068834846534090620928 which corresponds to 0x500123FB2D414C000000000000000000 in hex
While the correct conversion is: 106344161744262493917718975250015952381
How can i solve this issue ?
FYI: I need the last 6 digits of the hexadecimal number in its decimal value.

How to convert unicode hex number variable to character in NSString?

Now I have a range of unicode numbers, I want to show them in UILabel, I can show them if i hardcode them, but that's too slow, so I want to substitute them with a variable, and then change the variable and get the relevant character.
For example, now I know the unicode is U+095F, I want to show the range of U+095F to U+096f in UILabel, I can do that with hardcode like
NSString *str = [NSString stringWithFormat:#"\u095f"];
but I want to do that like
NSInteger hex = 0x095f;
[NSString stringWithFormat:#"\u%ld", (long)hex];
I can change the hex automatically,just like using #"%ld", (long)hex, so anybody know how to implement that?
You can initialize the string with the a buffer of bytes of the hex (you simply provide its pointer). The point is, and the important thing to notice is that you provide the character encoding to be applied. Specifically you should notice the byte order.
Here's an example:
UInt32 hex = 0x095f;
NSString *unicodeString = [[NSString alloc] initWithBytes:&hex length:sizeof(hex) encoding:NSUTF32LittleEndianStringEncoding];
Note that solutions like using the %C format are fine as long as you use them for 16-bit unicode characters; 32-bit unicode characters like emojis (for example: 0x1f601, 0x1f41a) will not work using simple formatting.
You would have to use
[NSString stringWithFormat:#"%C", (unichar)hex];
or directly declare the unichar (unsigned short) as
unichar uni = 0x095f;
[NSString stringWithFormat:#"%C", uni];
A useful resource might be the String Format Specifiers, which lists %C as
16-bit Unicode character (unichar), printed by NSLog() as an ASCII character, or, if not an ASCII character, in the octal format \ddd or the Unicode hexadecimal format \udddd, where d is a digit.
Like this:
unichar charCode = 0x095f;
NSString *s = [NSString stringWithFormat:#"%C",charCode];
NSLog(#"String = %#",s); //Output:String = य़

NSScanner not scanning long numeric string into number

I have a string "999999999999528106" and I am passing it to NSScanner but the output is not correct. I get 2147483647 as result.
I guess the big size of my string is not fitting into the NSInteger. Any clue
NSScanner *aScanner = [NSScanner scannerWithString:iString];
NSMutableCharacterSet *aCharset = [NSMutableCharacterSet whitespaceAndNewlineCharacterSet];
[aCharset formUnionWithCharacterSet:[NSCharacterSet symbolCharacterSet]];
[aScanner setCharactersToBeSkipped:[aCharset copy]];
NSInteger anIntegerResult = 0;
[aScanner setScanLocation:0];
if ([aScanner scanInteger:&anIntegerResult] && aScanner.isAtEnd)
return #(anIntegerResult);
From the NSScanner documentation:
Skips past excess digits in the case of overflow, so the receiver’s position is past the entire integer representation.
So yes, it's overflowing. You can use scanLongLong: instead.

Check if NSString contains any numbers and is at least 7 characters long

So I imagine that I need a regex statement to do this but I haven't had to do any regex with objective c yet, and I haven't written a regex statement in like a year.
I think it should be like ((?=.*[0-9]).{7,1000})
How do I put this into an objective c string comparison and evaluate the results?
Also is my regex correct?
While a regular expression would probably work, there is another approach:
NSString *str = // some string to check for at least one digit and a length of at least 7
if (str.length >= 7 && [str rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]].location != NSNotFound) {
// this matches the criteria
}
This code actually checks more than just 0-9. It handles digits from other languages too. If you really just want 0-9 then replace:
[NSCharacterSet decimalDigitCharacterSet]
with:
[NSCharacterSet characterSetWithCharactersInString:#"0123456789"];

ios LINESTRING parsing

I have been planning the route as a custom in google maps for iOS.
How do I parsing the incoming JSON in LINESTRING??
My LINESTRING:
"coordInfo": "LINESTRING (28.646751729297 40.9993029074749, 28.6470087874434 40.9995465119554, 28.6470087874434 40.9995465119554, 28.6474633603416 41.0000088561426)"
},
It looks like, from what you posted, that objectForKey#"coordInfo" gives you a single string with numbers in parentheses. You could parse that using the NSString method componentsSeparatedByCharactersInSet: passing a set that contains left and right parentheses, comma, and space to produce an array of the individual number strings (as well as the word "LINESTRING" as the first string in the array). The array will also contain some empty strings where 2 separator characters are together (like comma and space), so you'll have to test for that when taking objects out of the array.
You could also use an NSScanner like this:
NSString *toParse = #"LINESTRING (28.646751729297 40.9993029074749, 28.6470087874434 40.9995465119554, 28.6470087874434 40.9995465119554, 28.6474633603416 41.0000088561426)";
NSScanner *scanner = [NSScanner scannerWithString:toParse];
double num;
while (! [scanner isAtEnd]) {
[scanner scanUpToCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet] intoString:nil];
[scanner scanDouble:&num];
// put numbers into an array here or use them somehow
NSLog(#"%f",num);
}

Resources