Согласно вашему коду:
String[] name = {"tom", "dick", "harry"};
for(int i = 0; i<=name.length; i++) {
System.out.print(name[i] +'\n');
}
Если вы проверите System.out.print (name.length),
, вы получите 3;
, что означает, что длина вашего имени равна 3
, ваш цикл работает от 0 до 3, который должен работать либо от «0 до 2», либо от «1 до 3»
Ответ
String[] name = {"tom", "dick", "harry"};
for(int i = 0; i<name.length; i++) {
System.out.print(name[i] +'\n');
}
Объединение ответов Дамовизы и Джо. I've updated answer afer Aydsman's nad activa's comments.
int count = Regex.Matches(templateString, @"(?<!\{)\{([0-9]+).*?\}(?!})") //select all placeholders - placeholder ID as separate group
.Cast<Match>() // cast MatchCollection to IEnumerable<Match>, so we can use Linq
.Max(m => int.Parse(m.Groups[1].Value)) + 1; // select maximum value of first group (it's a placegolder ID) converted to int
This approach will work for templates like:
"{0} aa {2} bb {1}" => count = 3
"{4} aa {0} bb {0}, {0}" => count = 5
"{0} {3} , {{7}}" => count = 4
Вы всегда можете использовать Regex:
using System.Text.RegularExpressions;
// ... more code
string templateString = "{0} {2} .{{99}}. {3}";
Match match = Regex.Matches(templateString,
@"(?<!\{)\{(?<number>[0-9]+).*?\}(?!\})")
.Cast<Match>()
.OrderBy(m => m.Groups["number"].Value)
.LastOrDefault();
Console.WriteLine(match.Groups["number"].Value); // Display 3
Возможно, вы пытаетесь расколоть орех кувалдой?
Почему бы просто не добавить try / catch вокруг вашего вызова String.Format.
Это немного уродливо, но решает вашу проблему способом, требующим минимальных усилий, минимального тестирования и гарантированно работающего, даже если в форматировании строк есть что-то еще, что вы не рассматривали (например, {{литералы или более сложный формат строки с нечисловыми символами внутри: {0: $ #, ## 0.00; ($ #, ## 0.00); Zero})
(И да, это означает, что вы не обнаружите больше элементов данных, чем формат спецификаторы, но является ли это проблемой? Предположительно, пользователь вашего программного обеспечения заметит, что он усек свой вывод и исправит строку формата?)
На самом деле это не ответ на ваш вопрос, а возможное решение вашей проблемы (хотя и не очень элегантное); вы можете дополнить коллекцию dataItems
несколькими экземплярами string.Empty
, поскольку string.Format
не заботится об избыточных элементах.
Подсчет заполнителей не помогает - рассмотрим следующие случаи:
"{0} ... {1} ... {0}" - требуется 2 значения
"{1} {3}" - необходимо 4 значения, два из которых игнорируются
Второй пример не является надуманным.
Например, у вас может быть что-то вроде этого в американском английском:
String.Format("{0} {1} {2} has a {3}", firstName, middleName, lastName, animal);
В некоторых культурах второе имя может не использоваться, и вы можете иметь:
String.Format("{0} {2} ... {3}", firstName, middleName, lastName, animal);
Если вы для этого необходимо найти спецификаторы формата {index [, length] [: formatString]} с максимальным индексом, игнорируя повторяющиеся фигурные скобки (например, {{n}}). Повторяющиеся фигурные скобки используются для вставки фигурных скобок как литералов в выходную строку. Я оставлю кодирование в качестве упражнения :) - но я не Не думаю, что это можно или нужно делать с помощью Regex в наиболее общем случае (например, с length и / или formatString).
И даже если сегодня вы не используете length или formatString, будущий разработчик может подумать, что это безобидное изменение добавить один - было бы стыдно, если бы это нарушило ваш код.
Я бы попытался имитировать код в StringBuilder.AppendFormat (который вызывается String.Format), даже если он немного уродлив - используйте Lutz Reflector для получить этот код. В основном перебирайте строку в поисках спецификаторов формата и получайте значение индекса для каждого спецификатора.
s безобидное изменение, чтобы добавить его - было бы позором, если бы это сломало ваш код.Я бы попытался имитировать код в StringBuilder.AppendFormat (который вызывается String.Format), даже если он немного уродлив - используйте Lutz Reflector, чтобы получить этот код. В основном перебирайте строку в поисках спецификаторов формата и получайте значение индекса для каждого спецификатора.
s безобидное изменение, чтобы добавить его - было бы позором, если бы это сломало ваш код.Я бы попытался имитировать код в StringBuilder.AppendFormat (который вызывается String.Format), даже если он немного уродлив - используйте Lutz Reflector, чтобы получить этот код. В основном перебирайте строку в поисках спецификаторов формата и получайте значение индекса для каждого спецификатора.
Поскольку У меня нет полномочий редактировать сообщения, я предлагаю свою более короткую (и правильную) версию ответа Маркуса:
int num = Regex.Matches(templateString,@"(?<!\{)\{([0-9]+).*?\}(?!})")
.Cast<Match>()
.Max(m => int.Parse(m.Groups[0].Value)) + 1;
Я использую регулярное выражение, предложенное Айдсманом, но не тестировал его.
Вы можете использовать регулярное выражение для подсчета пар {}, которые имеют только форматирование, которое вы будете использовать между ними. @ "\ {\ d + \}" достаточно, если вы не используете параметры форматирования.