I am using a NSScanner to detect text bound by [square brackets] in a string, and convert it into HTML hyperlinks. I hope to turn convert this text in the following way:
This [is an] example of the [text] I'm using
should convert to
This is an example of the text I'm using
I've implemented a NSScanner, but in order to make it work properly, I need to extract both the first and second of the square brackets.
Here's the current state of my code:
NSScanner *theScanner;
NSString *text = nil;
theScanner = [NSScanner scannerWithString:stringWithBrackets];
NSString *stringWithoutBrackets;
while ([theScanner isAtEnd] == NO) {
[theScanner scanUpToString:#"[" intoString:NULL];
[theScanner scanUpToString:#"]" intoString:&text];
<BREAK>
At this breakpoint, I have a string returned, which does not contain the closing bracket. So, for the example text string shown above, the contents of NSString *text at the first breakpoint is
[is an
In order to properly manipulate the string, I need to work with both the opening and closing bracket.
Essentially, my question is: how do I advance the NSScanner on one character, and include that character into the variable 'text'?
You can skip the ] character with scanString:
if ([theScanner scanString:#"]" intoString:NULL]) {
text = [text stringByAppendingString:#"]"];
} else {
// Next character is not ']'
}
The else case would only happen if there is no matching ] character. text contains the part from [ to the end of the string in that case.
Alternatively, you could use NSRegularExpression and e.g. the matchesInString method which returns an array of all ranges in the string matching the regular expression.
Related
I am looking to get the actually unicode value of a character, and put it into an escaped string. I set the title of an NSButton to ± , now I am trying to get the title of this button and convert it back to this "\U00B1";
For Example
unichar theChar = [theButton.title characterAtIndex:0];
//now how would I change the above unichar to an string like #"\\u03b2"
One solution would be:
unichar theChar = ...
NSString *escapeCode = [NSString stringWithFormat:#"\\\\u%04x", theChar];
Note how you need four backslashes to get two in the resulting string.
Could anyone give some advise please.
In my iOS app I am parsing XML (with a help of third-party-library) and have a problem with extra whitespaces/newLines at the beginning/end of the strings. Initial string, that return this third-party-library, it's a C++ std::wstring that I convert to NSString (the encoding should be right as the content of new NSString is equal to proper part of my XML-file). After the trim length of "empty" elements (that contain only whitespaces and new lines) doesn't become zero but change it's value by half.
The code is below....
std::wstring val;
NSString *initial = [[NSString alloc] initWithBytes:val.data() length:sizeof (wchar_t)*val.size() encoding:NSUTF16LittleEndianStringEncoding];
NSString *trimmed = [initial stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
If try to output like NSLog(#"bybyby'%#'bebebe", trimmed); 'bebebe have never displayed. Looks like that there are left some new lines, whitespaces that can't be detected.
wchar_t is a 32-bit integer (on iOS and OS X), therefore you must use NSUTF32LittleEndianStringEncoding for the conversion to NSString.
Example:
std::wstring val (L" Hello World ");
NSString *initial = [[NSString alloc] initWithBytes:val.data() length:sizeof (wchar_t)*val.size() encoding:NSUTF32LittleEndianStringEncoding];
NSString *trimmed = [initial stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSLog(#"'%#'", trimmed);
// Output: 'Hello World'
What probably happened in your case (with NSUTF16LittleEndianStringEncoding)
is that every second character in the initial string is a NUL character,
which acts as a terminator when printed.
I need to determine if a text is an email address, or mobile number, for email address I can use some regular expression, for mobile number I can check if the string has only digits(right?)
and the sequence is like:
is (regex_valid_email(text))
{
// email
}
else if (all_digits(text))
{
// mobile number
}
but how do I check if a string has only numbers in iOS?
Thanks
You create an NSCharacterSet that includes the digits and probably the dash and maybe parentheses (depending on what format you are seeing for the phone numbers). You then invert that set, so you have a set that has everything but those digits and things, then use rangeOfCharactersFromSet and if you get anything but NSNotFound, then you have something other than digits.
This should work:
//This is the input string that is either an email or phone number
NSString *input = #"18003234322";
//This is the string that is going to be compared to the input string
NSString *testString = [NSString string];
NSScanner *scanner = [NSScanner scannerWithString:input];
//This is the character set containing all digits. It is used to filter the input string
NSCharacterSet *skips = [NSCharacterSet characterSetWithCharactersInString:#"1234567890"];
//This goes through the input string and puts all the
//characters that are digits into the new string
[scanner scanCharactersFromSet:skips intoString:&testString];
//If the string containing all the numbers has the same length as the input...
if([input length] == [testString length]) {
//...then the input contains only numbers and is a phone number, not an email
}
I'm using the NSString method [myString capitalizedString], to capitalize all words of my string.
However capitalization doesn't work very well for words starting with numbers.
i.e. 2nd chance
becomes
2Nd Chance
Even if n is not the first letter of the word.
thanks
You have to roll your own solution to this problem. The Apple docs state that you may not get the specified behavior using that function for multi-word strings and for strings with special characters. Here's a pretty crude solution
NSString *text = #"2nd place is nothing";
// break the string into words by separating on spaces.
NSArray *words = [text componentsSeparatedByString:#" "];
// create a new array to hold the capitalized versions.
NSMutableArray *newWords = [[NSMutableArray alloc]init];
// we want to ignore words starting with numbers.
// This class helps us to determine if a string is a number.
NSNumberFormatter *num = [[NSNumberFormatter alloc]init];
for (NSString *item in words) {
NSString *word = item;
// if the first letter of the word is not a number (numberFromString returns nil)
if ([num numberFromString:[item substringWithRange:NSMakeRange(0, 1)]] == nil) {
word = [item capitalizedString]; // capitalize that word.
}
// if it is a number, don't change the word (this is implied).
[newWords addObject:word]; // add the word to the new list.
}
NSLog(#"%#", [newWords description]);
Unfortunately this seems to be the general behaviour of capitalizedString.
Perhaps a not so nice workaround / hack would be to replace each number with a string before the transformation, and then change it back afterwards.
So, "2nd chance" -> "xyznd chance" -> "Xyznd Chance" -> "2nd Chance"
I'm receiving an NSString which uses commas as delimiters, and a backslash as an escape character. I was looking into splitting the string using componentsSeparatedByString, but I found no way to specify the escape character. Is there a built-in way to do this? NSScanner? CFStringTokenizer?
If not, would it be better to split the string at the commas, and then rejoin tokens that were falsely split (after inspecting them for a (non-escaped) escape character at the end) or looping through each character trying to find a comma, and then looking back one character to see if the comma is escaped or not (and then one more character to see if the escape character is escaped).
Now that I think about it, I would need to check that the amount of escape characters before a delimiter is even, because only then is the delimiter itself not being escaped.
If someone has a method that does this, I'd appreciate it if I could take a look at it.
I think the most straightforward method to do this would be to go through the string character by character as you suggest, appending into new string objects. You can follow two simple rules:
if you find a backslash, ignore but copy the next character (if exists) unconditionally
if you find a comma, end of that section
You could do this manually or use some of the functionality of NSScanner to help you (scanUpToCharactersFromSet:intoString:)
I would prefer to use a regular expression based parser to weed out the escape characters and then possibly doing a split operation (of some type) on the string.
Okay, (I hope) this is what wipolar suggested. It's the first implementation that works. I've just started with a non-GC-collected language, so please post a comment if you think this code can be improved, especially in the memory-management department.
- (NSArray *) splitUnescapedCharsFrom: (NSString *) str atChar: (char) delim withEscape: (char) esc
{
NSMutableArray * result = [[NSMutableArray alloc] init];
NSMutableString * currWord = [[NSMutableString alloc] init];
for (int i = 0; i < [str length]; i++)
{
if ([str characterAtIndex:i] == esc)
{
[currWord appendFormat:#"%c", [str characterAtIndex:++i]];
}
else if ([str characterAtIndex:i] == delim)
{
[result addObject:[NSString stringWithString:currWord]];
[currWord release];
currWord = [[NSMutableString alloc] init];
}
else
{
[currWord appendFormat:#"%c", [str characterAtIndex:i]];
}
}
[result addObject:[NSString stringWithString:currWord]];
[currWord release];
return [NSArray arrayWithArray:result];
}