Есть ли лучший способ подсчета заполнителей формата строки в строке в C #?

Согласно вашему коду:

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');
}
13
задан Damovisa 5 June 2009 в 05:57
поделиться

7 ответов

Объединение ответов Дамовизы и Джо. 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

9
ответ дан 1 December 2019 в 17:42
поделиться

Вы всегда можете использовать 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
7
ответ дан 1 December 2019 в 17:42
поделиться

Возможно, вы пытаетесь расколоть орех кувалдой?

Почему бы просто не добавить try / catch вокруг вашего вызова String.Format.

Это немного уродливо, но решает вашу проблему способом, требующим минимальных усилий, минимального тестирования и гарантированно работающего, даже если в форматировании строк есть что-то еще, что вы не рассматривали (например, {{литералы или более сложный формат строки с нечисловыми символами внутри: {0: $ #, ## 0.00; ($ #, ## 0.00); Zero})

(И да, это означает, что вы не обнаружите больше элементов данных, чем формат спецификаторы, но является ли это проблемой? Предположительно, пользователь вашего программного обеспечения заметит, что он усек свой вывод и исправит строку формата?)

2
ответ дан 1 December 2019 в 17:42
поделиться

На самом деле это не ответ на ваш вопрос, а возможное решение вашей проблемы (хотя и не очень элегантное); вы можете дополнить коллекцию dataItems несколькими экземплярами string.Empty , поскольку string.Format не заботится об избыточных элементах.

3
ответ дан 1 December 2019 в 17:42
поделиться

Подсчет заполнителей не помогает - рассмотрим следующие случаи:

"{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, чтобы получить этот код. В основном перебирайте строку в поисках спецификаторов формата и получайте значение индекса для каждого спецификатора.

18
ответ дан 1 December 2019 в 17:42
поделиться

Поскольку У меня нет полномочий редактировать сообщения, я предлагаю свою более короткую (и правильную) версию ответа Маркуса:

int num = Regex.Matches(templateString,@"(?<!\{)\{([0-9]+).*?\}(?!})")
             .Cast<Match>()
             .Max(m => int.Parse(m.Groups[0].Value)) + 1;

Я использую регулярное выражение, предложенное Айдсманом, но не тестировал его.

1
ответ дан 1 December 2019 в 17:42
поделиться

Вы можете использовать регулярное выражение для подсчета пар {}, которые имеют только форматирование, которое вы будете использовать между ними. @ "\ {\ d + \}" достаточно, если вы не используете параметры форматирования.

0
ответ дан 1 December 2019 в 17:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: