【问题标题】:String.Format count the number of expected argsString.Format 计算预期参数的数量
【发布时间】:2011-02-14 05:29:14
【问题描述】:

是否可以计算 String.Format() 字符串中预期的 args/params 的数量?

例如:"Hello {0}. Bye {1}" 应返回计数 2。

我需要在string.Format() 抛出异常之前显示错误。

感谢您的帮助。

【问题讨论】:

标签: c# .net string


【解决方案1】:

您可以使用正则表达式,例如 {(.*?)},然后只计算匹配项。如果您需要处理像 {0} {0} (我猜应该返回 1)这样的情况,那么这会使它变得更加困难,但是您总是可以将所有匹配项放在一个列表中并在其上执行 Linq select distinct .我在想类似下面的代码:

var input = "{0} and {1} and {0} and {2:MM-dd-yyyy}";
var pattern = @"{(.*?)}";
var matches = Regex.Matches(input, pattern);
var totalMatchCount = matches.Count;
var uniqueMatchCount = matches.OfType<Match>().Select(m => m.Value).Distinct().Count();
Console.WriteLine("Total matches: {0}", totalMatchCount);
Console.WriteLine("Unique matches: {0}", uniqueMatchCount);

编辑:

我想解决 cmets 中提出的一些问题。下面发布的更新代码处理存在转义括号序列(即 {{5}})的情况,其中未指定参数,并且还返回最高参数的值 + 1。代码假定输入字符串将格式良好,但在某些情况下这种权衡可能是可以接受的。例如,如果您知道输入字符串是在应用程序中定义的,而不是由用户输入生成的,则可能不需要处理所有边缘情况。也可以使用单元测试来测试要生成的所有错误消息。我喜欢这个解决方案的一点是,它很可能会处理向它抛出的绝大多数字符串,而且它比here 标识的解决方案更简单(这表明重新实现 string.AppendFormat)。我会考虑这样一个事实,即此代码可能无法通过使用 try-catch 并仅返回“无效的错误消息模板”或类似的东西来处理所有边缘情况。

以下代码的一个可能改进是更新正则表达式以不返回前导“{”字符。这将消除对 Replace("{", string.Empty) 的需要。同样,此代码可能并非在所有情况下都是理想的,但我认为它充分解决了所提出的问题。

const string input = "{0} and {1} and {0} and {4} {{5}} and {{{6:MM-dd-yyyy}}} and {{{{7:#,##0}}}} and {{{{{8}}}}}";
//const string input = "no parameters";
const string pattern = @"(?<!\{)(?>\{\{)*\{\d(.*?)";
var matches = Regex.Matches(input, pattern);
var totalMatchCount = matches.Count;
var uniqueMatchCount = matches.OfType<Match>().Select(m => m.Value).Distinct().Count();
var parameterMatchCount = (uniqueMatchCount == 0) ? 0 : matches.OfType<Match>().Select(m => m.Value).Distinct().Select(m => int.Parse(m.Replace("{", string.Empty))).Max() + 1;
Console.WriteLine("Total matches: {0}", totalMatchCount);
Console.WriteLine("Unique matches: {0}", uniqueMatchCount);
Console.WriteLine("Parameter matches: {0}", parameterMatchCount);

【讨论】:

  • @Joe,那么是否有一个正则表达式可以计算编号。预期的参数?
  • @Joe,divi 这将为字符串“Somestuff {5}”返回值 1...你不是对 5 感兴趣,而不是 1?
  • @Deepee1 - Somestuff{5} 应该返回值 6 而不是 5。但是是的,它应该返回 6。
  • 这从这里发布的一些链接中帮助了我。谢谢
  • @joe 请查看我的编辑,我试图解决您的问题。谢谢。
【解决方案2】:

我认为这将处理转义括号和 0:0000 的东西...将给出最大的括号值...所以在我的示例中将给出 1。

       //error prone to malformed brackets...
        string s = "Hello {0:C} Bye {1} {0} {{34}}";

        int param = -1;
        string[] vals = s.Replace("{{", "").Replace("}}", "").Split("{}".ToCharArray());
        for (int x = 1; x < vals.Length-1; x += 2)
        {
            int thisparam;
            if (Int32.TryParse(vals[x].Split(',')[0].Split(':')[0], out thisparam) && param < thisparam)
                param = thisparam;
        }
        //param will be set to the greatest param now.

【讨论】:

  • MessageBox.Show(String.Format("yopa {{0}}","test"));输出“yopa {0}”,因此它确实处理了转义。我说错了嵌套,我的意思是逃跑。
  • 这非常棒,而且比 RegEx 方法更容易阅读。
【解决方案3】:

这个简单的方法很容易解决这个问题:

public static int CountArguments(string str)
    {
        int quantity= 0;
        while(str.Contains("{" + quantity+ "}"))
        {
            quantity++;
        }
        return quantity;
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-04
    • 1970-01-01
    • 2019-06-20
    • 2013-03-30
    • 2021-12-13
    • 2010-11-28
    • 2014-10-10
    相关资源
    最近更新 更多