【问题标题】:Formatting with Array[i] Logic使用 Array[i] 逻辑格式化
【发布时间】:2017-12-18 02:10:37
【问题描述】:

我正在尝试构建一个打印 75 个随机大写和小写字母的程序,每行 25 个。我想我已经解决了所有的逻辑,但是每当我运行它时,格式都是关闭的,而不是每行打印 25 个字符,它会打印一个随机数。到目前为止,这是我的代码:

char allLetters[] = new char[3700];

for(int i = 1; i <= 75; i++) { //Begin for loop

int max = 122;
int min = 65;

allLetters[i] = (char)(Math.random() * (max - min) + min);

if(i % 25 != 0){

if (allLetters[i] <= 90) {
    System.out.printf("%s,",allLetters[i]);
}

if (allLetters[i] >= 97) {
    System.out.printf("%s,",allLetters[i]);
}

} //Close if

else {

if (allLetters[i] <= 90) {
    System.out.printf("%s\n",allLetters[i]);
}

if (allLetters[i] >= 97) {
    System.out.printf("%s\n",allLetters[i]);
}

}

} //End for

目前,输出类似于:

U,i,y,e,v,T,G,p,P,a,U,G,e,B,w,U,o,F,G,w,j,m,R
O,X,w,w,u,p,t,g,X,J,R,c,w,I,d,H,R,m,y,b,o
C,p,M,F,X,U,v,O,a,Y,F,E,x,s,x,k,C,b,D,R,r,H

我尝试过使用除 i 之外的不同变量,玩弄数字等,但我似乎无法找到导致格式化关闭的逻辑中的确切缺陷。任何帮助将不胜感激!

【问题讨论】:

    标签: java formatting logic


    【解决方案1】:

    您的逻辑问题在于,即使您不打印每个选定的字符,您也会对其进行计数。介于 90 和 97 之间的 ASCII 字符(排他性)不是字符,您理所当然地跳过打印它们。然而,循环仍在计算这些迭代,就好像打印了一个有效的字母一样。这会导致输出中的计数不正确。

    在下面的代码 sn-p 中使用的解决方法是在循环中不断选择字符,直到我们真正得到一个小写或大写字母。只有这样我们才能继续你之前的逻辑。

    char allLetters[] = new char[3700];
    int max = 122;
    int min = 65;
    
    for (int i = 1; i <= 75; i++) {
        char next;
        do {
            next = (char)(Math.random() * (max - min) + min);
        } while (next > 90 && next < 97);
        allLetters[i] = next;
        if (i % 25 != 0) {
            System.out.printf("%s,", next);
        }
        else {
            System.out.printf("%s\n", next);
        }
    }
    

    Demo

    【讨论】:

    • 哇,非常感谢。对于像我这样的新人来说,优雅且易于理解。
    • 不需要使用651229097等常量。只需使用'A''z''Z''a',就可以明确他们的意图。此外,强烈建议不要使用“将Math.random() 与常量相乘”的成语。这很容易出错,这个例子说明了原因。使用(Math.random() * (max - min) + min),您将永远无法获得max。我建议改用ThreadLocalRandom.current().nextInt(min, max + 1)。当您将next 声明为int 并在printf 中使用%c 而不是%s 时,您可以省略类型转换为char,并省略过时的数组存储操作。
    【解决方案2】:

    您对随机字符设置的两个条件,即allLetters[i] &lt;= 90allLetters[i] &gt;= 97,并没有涵盖可能字符的整个区间,在您的程序中是 65 到 122,包括 65 到 122。当生成 91 到 96 之间的字符时,您的程序不会打印任何内容。得到这六个随机字符之一的概率大约为 10%,因此您打印了 21..23 个字符。

    如果您真的想跳过这六个字符,请使用while 循环而不是for 循环来解决问题,并且仅在打印某些内容时才增加打印字符的计数器:

    int printed = 0;
    while (printed != 75) {
        char ch = (char)(Math.random() * (max - min) + min);
        if (ch >= 91 && ch <= 96) continue;
        printed++;
        System.out.print(ch);
        if (printed % 25 == 0 {
            System.out.println();
        } else {
            System.out.print(',');
        }
    }
    

    【讨论】:

    • 感谢您的帮助!我会考虑使用 while 循环。
    【解决方案3】:

    我正在查看您的问题,并且有一个使用 Java 8+ IntStream 和 lambdas 的“聪明”解决方案。在026 之间生成75 个随机int(s),使用来自RandomnextBoolean() 将每个值映射到从'a''A' 偏移的一个字符String。将其收集到一个 75 个字符 String。然后打印我们感兴趣的三个 25 字符 substring(s)。比如,

    Random rand = new Random();
    String s = IntStream.generate(() -> rand.nextInt(26)).limit(75)
            .mapToObj(i -> Character.toString(
                    rand.nextBoolean() ? (char) (i + 'a') : (char) (i + 'A')))
            .collect(Collectors.joining());
    System.out.println(s.substring(0, 25));
    System.out.println(s.substring(25, 50));
    System.out.println(s.substring(50));
    

    【讨论】:

    • 这绝对很有趣,但现在我试图坚持简单的 for、if 和 while 逻辑。感谢您花时间寻找解决方案,非常感谢!
    • 请注意,所有Random 实例都已经具有流工厂方法。对于这个特定任务,ThreadLocalRandom 可能比同步Random 更可取,因此,您可以使用ThreadLocalRandom.current() .ints(75, 0, 26),然后在下一步减少代码重复:.mapToObj(i -&gt; Character.toString((char) (i + ThreadLocalRandom.current().nextBoolean()? 'a': 'A')),不过,我更愿意避免装箱开销,即使代码变得稍微复杂一些,即.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString()...
    猜你喜欢
    • 1970-01-01
    • 2017-11-26
    • 2021-09-28
    • 2016-01-14
    • 1970-01-01
    • 1970-01-01
    • 2011-11-27
    • 1970-01-01
    相关资源
    最近更新 更多