java - 如何计算字符串中格式字符的数量?

标签 java android string string-formatting

[更新]

我有一个 java 字符串,它可以有格式字符(那些带有 % 的)。

当我们调用 String.format(String, args..)

时,有没有办法计算这个字符串所需的参数数量?

例如:

String placeholderString = "the %s jumped over the %s, %d times";
String.format(placeholderString, "cow", "moon", 2);

至少需要 3 个参数,否则会抛出 MissingFormatArgumentException

String placeholderString = "the %1$s jumped over the %1$s, %2$d%% %n";
String.format(placeholderString, "cow", 2);

至少需要 2 个参数。

什么是优雅高效计算带格式字符的字符串所需参数的最小数量的方法?

我需要这个的原因是因为我希望能够在运行时为该方法提供参数。如果参数超过最小计数,我想获取那些“未使用”的参数并将它们附加到字符串的末尾。您还可以建议我如何满足此要求的替代方法。

例如:我可以递增地提供参数,直到不抛出 MissingFormatArgumentException。然后我可以获取剩余的参数并附加它们。这解决了我的问题,但我想知道这是否是最好的方法。

最佳答案

这也接受不正确的格式,但格式解析器显然过于昂贵(即工作量太大)——尽管这可能比正则表达式匹配更有效。这是否优雅我不能说 - 可能的输入变化对于圆滑或圆滑的方法来说太复杂了。

我已经改变了我的第一个解决方案,它只会返回最少数量的参数,因为添加错误种类的参数可能会导致异常:您应该使用与转换代码匹配的类的参数。使用 null 会导致警告和丑陋的输出。

Pattern pat = Pattern.compile( "(?!<%)%" +
                  "(?:(\\d+)\\$)?" +
                  "([-#+ 0,(]|<)?" +
                  "\\d*" +
                  "(?:\\.\\d+)?" +
                  "(?:[bBhHsScCdoxXeEfgGaAtT]|" +
                  "[tT][HIklMSLNpzZsQBbhAaCYyjmdeRTrDFc])" );

Class<?> classOf( String conv ){
    if( conv.startsWith( "t" ) ){
        return Date.class;
    }
    switch( conv.charAt( 0 ) ){
    case 'b':
        return Boolean.class;
    case 'h': case 'd': case 'o': case 'x':
        return Integer.class;
    case 's':
        return String.class;
    case 'c':
        return Character.class;
    case 'e': case 'f': case 'g': case 'a':
        return Double.class;
    default:
        return Void.class;
    }
}

List<Class<?>> count( String fmt ){
    List<Class<?>> res = new ArrayList<>();
    Matcher m = pat.matcher( fmt );
    while( m.find() ){
        if( m.group(1) != null ){
            String dec = m.group(1);
            int ref = Integer.parseInt( dec );
            if( res.size() < ref ){
                while( res.size() < ref - 1 ){
                    res.add( Void.class );
                }
                res.add( classOf( m.group(3).toLowerCase() )) ;
            } else {
                Class<?> clazz = classOf( m.group(3).toLowerCase() );
                res.set( ref - 1, clazz );
            }
        } else if( m.group(2) != null && "<".equals( m.group(2) ) ){
            // ignore
        } else {
            res.add( classOf( m.group(3).toLowerCase() ));
        }
    }
    return res;
}

测试使用

void demo( String... formats ){
    for( String fmt: formats ){
        List<Class<?>> res = count( fmt );
        System.out.print( fmt + ": " + res.size() + ":" );
        for( Class<?> clazz: res ){
            System.out.print( " " + clazz.getSimpleName() );
        }
        System.out.println();
    }
}

输出:

%d: 1: Integer
%1$d: 1: Integer
the %s jumped over the %s, %d times: 3: String String Integer
the %1$s jumped over the %1$s, %2$d%% %n: 2: String Integer
Duke's Birthday: %1$tm %1$te,%1$tY: 1: Date
Duke's Birthday: %1$tm %<te,%<tY: 1: Date
%4$s %3$s %2$s %1$s %4$s %3$s %2$s %1$s: 4: String String String String
%s %s %<s %<s: 2: String String
%s %s %s %s: 4: String String String String
%2$s %s %<s %s: 4: Void String String String

这是简单的版本,只返回计数:

int count( String fmt ){
    Matcher m = pat.matcher( fmt );
    int np = 0;
    int maxref = 0;
    while( m.find() ){
        if( m.group(1) != null ){
            String dec = m.group(1);
            int ref = Integer.parseInt( dec );
            maxref = Math.max( ref, maxref );
        } else if( m.group(2) != null && "<".equals( m.group(2) ) ){
            // ignore
        } else {
            np++;
        }
    }
    return Math.max( np, maxref );
}

关于java - 如何计算字符串中格式字符的数量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28133103/

相关文章:

c++ - 将字符数组附加到字符串 C++

javascript - 如何使用 parseFloat 将字符串转换为数字?

java - Android 教程 - 当我尝试访问现有 TextView 时,为什么我的应用程序崩溃

java - 方法无故关闭程序

java - 如何以编程方式停止 Spark 作业执行

java - org.springframework.web.servlet.PageNotFound noHandlerFound警告: No mapping found for HTTP request with URI

安卓开发 |推文一个字符串

php 文件返回错误转换为 Android GET 请求的 JSON

java - MimeUtility.decode() 不适用于每个编码文本

java - 扩展抽象类时出错