I have a template string and an array of parameters that come from different sources but need to be matched up to create a new "filled-in" string:
string templateString = GetTemplate(); // e.g. "Mr {0} has a {1}"
string[] dataItems = GetDataItems(); // e.g. ["Jones", "ceiling cat"}
string resultingString = String.Format(templateString, dataItems);
// e.g. "Mr Jones has a ceiling cat"
With this code, I'm assuming that the number of string format placeholders in the template will equal the number of data items. It's generally a fair assumption in my case, but I want to be able to produce a resultingString
without failing even if the assumption is wrong. I don't mind if there are empty spaces for missing data.
If there are too many items in dataItems
, the String.Format
method handles it fine. If there aren't enough, I get an Exception.
To overcome this, I'm counting the number of placeholders and adding new items to the dataItems array if there aren't enough.
To count the placeholders, the code I'm working with at the moment is:
private static int CountOccurrences(string haystack)
{
// Loop through all instances of the string "}".
int count = 0;
int i = 0;
while ((i = text.IndexOf("}", i)) != -1)
{
i++;
count++;
}
return count;
}
Obviously this makes the assumption that there aren't any closing curly braces that aren't being used for format placeholders. It also just feels wrong. :)
Is there a better way to count the string format placeholders in a string?
A number of people have correctly pointed out that the answer I marked as correct won't work in many circumstances. The main reasons are:
- Regexes that count the number of placeholders doesn't account for literal braces (
{{0}}
) - Counting placeholders doesn't account for repeated or skipped placeholders (e.g.
"{0} has a {1} which also has a {1}"
)