【问题标题】:Getting ASCII value instead of string value获取 ASCII 值而不是字符串值
【发布时间】:2021-03-29 21:39:21
【问题描述】:

给定一个非空字符串和一个 int N,返回以 char 0 开头的字符串,然后是字符串的每个第 N 个字符。因此,如果 N 为 3,使用 char 0、3、6、... 等等。 N 大于等于 1。

 everyNth("Miracle", 2) → "Mrce"
 everyNth("abcdefg", 2) → "aceg"
 everyNth("abcdefg", 3) → "adg"

此代码实际上并未编译。但是在放置几个断点并在调试模式下运行后,它显示它将返回一个 ASCII 值“77”而不是 str.charAt() 位置的字符串值。我不确定为什么。请帮忙。

我正在努力学习和理解如何解决这个问题背后的基本逻辑。

我知道您可以使用 Stringbuilder 并将每个值附加到缓冲区而不是打印值是获得答案的一种方法。所以我想避免使用任何预定义的类,它们会在后台执行逻辑。

尝试: 我也尝试将String 类型转换为char,但结果相同。

public static String everyNth(String str, int n){
    String charAtPosition = "";
    int x = 0, pos = 0;
    String finalString = "";
    String stringPosition = str.charAt(pos); <-- Getting ASCII value instead of string value for ex. in "Miracle" string input, it should return "M"
    charAtPosition = stringPosition * n;
    for(int i = 0; i < str.length(); i++){
        finalString = finalString + charAtPosition;
    }
    return finalString;
}

【问题讨论】:

  • String stringPosition = str.charAt(pos); 正在编译吗?还有charAtPosition = stringPosition * n;?
  • 不,它实际上没有编译。我基于我在调试模式下运行发布了这个问题。
  • String stringPosition = str.charAt(pos) 替换为String stringPosition = String.valueOf(str.charAt(0))。您不能将 char 值分配给 String 变量。

标签: java string ascii


【解决方案1】:

您的代码无法编译。首先,将String stringPosition = str.charAt(pos) 替换为String stringPosition = String.valueOf(str.charAt(0)),因为str.charAt(pos) 返回一个char 值,您不能将其分配给String 变量。

此外,它就像使用 0 启动循环计数器并使用值 n 步进一样简单。在每次迭代中,将循环计数器处的字符附加到StringBuilder

public final class Main {

    public static final void main(String[] args) {
        System.out.println(everyNth("Miracle", 2));
        System.out.println(everyNth("abcdefg", 2));
        System.out.println(everyNth("abcdefg", 3));
    }

    public static String everyNth(String str, int n) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < str.length(); i += n) {
            sb.append(str.charAt(i));
        }
        return sb.toString();
    }
}

输出:

Mrce
aceg
adg

您可以使用String 代替StringBuilder,但我建议您在这种情况下使用StringBuilder 而不是String,因为循环中重复的字符串连接会创建与数字一样多的String 实例的串联。查看this discussion 了解更多信息。

【讨论】:

    【解决方案2】:

    这是一种使用 lambda 和流的方法。

    • 从 0 开始,每隔 n 个整数迭代一次
    • 映射第 n 个字符
    • 转换为字符串
    BiFunction<String, Integer, String> everyNth =
            (s, n) -> IntStream
                    .iterate(0, i -> i < s.length(), i -> i + n)
                    .mapToObj(i -> s.charAt(i) + "")
                    .reduce("", (a, b) -> a + b).toString();
    

    一些测试数据和运行

    Map<String, Integer> testData =
            Map.of("Miracle", 2, "abcdefgh", 2, "abcdefg", 3, "a",
                    4, "programming", 4, "notchanging", 1);
    
    testData.forEach((k, v) -> System.out.printf("Every %s, %-12s -> %s%n",
            v, k, everyNth.apply(k, v)));
    

    打印

    Every 2, Miracle      -> Mrce
    Every 4, programming  -> pri
    Every 2, abcdefgh     -> aceg
    Every 4, a            -> a
    Every 1, notchanging  -> notchanging
    Every 3, abcdefg      -> adg
    

    【讨论】:

    • 我会写BiFunction&lt;String, Integer, String&gt; everyNth = (s, n) -&gt; IntStream.iterate(0, i -&gt; i &lt; s.length(), i -&gt; i + n).mapToObj(i -&gt; String.valueOf(s.charAt(i))).reduce("", String::concat);。我更喜欢String.valueOf(s.charAt(i)) 而不是s.charAt(i) + "" 的原因是后者听起来像串联,而前者听起来像转换。此代码中的其他一些改进是:使用方法引用,并删除冗余的toString。尽管如此,这个解决方案的问题是它会在每次执行时以不同的顺序产生输出。
    • 如果您查看 OP 的评论和关闭的理由,这是有道理的。代码无法编译。 OP 在这里做了很多错误的事情 ->String stringPosition = str.charAt(pos); 和下面的声明。
    • 你可以直接用.collect(Collectors.joining())代替.reduce("", (a, b) -&gt; a + b).toString()
    • @ArvindKumarAvinash 使用 LinkedHashMap 将解决输出顺序问题。
    • @iota 是的,我知道。我以为我评论过使用Collectors.joining()。显然该评论已被删除。并且输出顺序无关紧要(不是要求的一部分)。即使我使用LinkedHashMap,Map.of() 仍然会改变顺序。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多