To ensure that a formatted string returned by NSString initWithFormat:arguments:
is as expected, I need to determine if there are the same number of format specifiers as arguments. Below is a (slightly contrived and highly edited) example:
- (void)thingsForStuff:(CustomStuff)stuff, ...
{
NSString *format;
switch (stuff)
{
case CustomStuffTwo:
format = @"Two things: %@ and %@";
break;
case CustomStuffThree:
format = @"Three things: %@, %@, and %@";
break;
default:
format = @"Just one thing: %@";
break;
}
va_list args;
va_start(args, method);
// Want to check if format has the same number of %@s as there are args, but not sure how
NSString *formattedStuff = [[NSString alloc] initWithFormat:format arguments:args];
va_end(args);
NSLog(@"Things: %@", formattedStuff);
}
Using this method, [self thingsForStuff:CustomStuffTwo, @"Hello", @"World"]
would log
"Two things: Hello and World"
...but [self thingsForStuff:CustomStuffTwo, @"Hello"]
would log
"Two things: Hello and "
...something that would be preferred to be caught before it happens.
Is there a way to count the format specifiers in a string, preferably something lightweight/inexpensive?
Well, I created my own regex, I have no idea if it's going to catch all of them, and may end finding some false positives, but seems to be working for me:
static NSString *const kStringFormatSpecifiers =
@"%(?:\\d+\\$)?[+-]?(?:[lh]{0,2})(?:[qLztj])?(?:[ 0]|'.{1})?\\d*(?:\\.\\d+)?[@dDiuUxXoOfeEgGcCsSpaAFn]";
You can count the number of arguments using:
NSRegularExpression *regEx = [NSRegularExpression regularExpressionWithPattern: kStringFormatSpecifiers options:0 error:nil];
NSInteger numSpecifiers = [regEx numberOfMatchesInString: yourString options:0 range:NSMakeRange(0, yourString.length)];
Is there a way to count the format specifiers in a string, preferably something lightweight/inexpensive?
Nope -- really isn't. At least, not if you want it to work across all possible format strings. You would have to duplicate the parser that is used by stringWithFormat:
. I.e. don't try to validate everything.
You could count the number of %
, but that would not catch things like %%
or other special cases. That may be good enough for your purposes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With