使用星号制作条形图(处理负值)

时间:2018-04-23 15:12:38

标签: java arrays

首先,我开始学习Java,并使用星号打印出一个条形图。我已经将算法放在如何打印正值上,我想我已经掌握了处理负值所需要做的事情。我无法做到的是将这个想法转化为代码。我正在与之合作:

public class BarChart
{
    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        Random gen = new Random();

        // Read for input of array legnth
        System.out.print("Enter Array Length: ");
        int n = gen.nextInt(6) + 10;
        System.out.println(n);

        int[] values = new int[n];
        int randNum;
        for(int i = 0; i < n; i++)
        {
            // Get random number to add to the array
            randNum = gen.nextInt(20) + 1;
            values[i] = randNum;
        }
        print(values);
        System.out.println();

        values[3] = -2;
        // Print each element as asterisks
        for(int i = 0; i < values.length; i++)
        {
            if(values[i] < 0)
            {
                printAsterisk(values[i] * -1);
                System.out.printf("%20d:\n", values[i]);
            }
            else
            {
                System.out.printf("%20d:", values[i]);
                printAsterisk(values[i]);
                System.out.println();
            }
        }
    }

    // Methods
    /**
     * Prints an array
     * @param array array
     */
    public static void print(int[] array)
    {
        for(int i = 0; i < array.length; i++)
        {
            if(i > 0)
            {
                System.out.print(" | ");
            }
            System.out.print(array[i]);
        }
        System.out.println();
    }

    public static void printAsterisk(int val)
    {
        for(int i = 0; i < val; i++)
        {
            System.out.print("*");
        }
    }
}

这让我接近我想要的,但我得到的是:

 Enter Array Length: 14
13 | 13 | 4 | 5 | 11 | 1 | 3 | 13 | 3 | 4 | 19 | 4 | 10 | 10

                  13:*************
                  13:*************
                   4:****
**                  -2:
                  11:***********
                   1:*
                   3:***
                  13:*************
                   3:***
                   4:****
                  19:*******************
                   4:****
                  10:**********
                  10:**********

注意:数组长度和元素都是随机确定的。在我上面给出的例子中,我明确地将其中一个元素更改为负值,仅用于测试目的,使用值[3] = -2。

有负值的星号应如下所示:

          **[-2]
            [5 ]*****
         ***[-3]
            [9 ]*********

我也无法在上面的示例中使用%20d打印我想要的内容。但这不是主要关注的问题。就像在我打印的那样:

        5: *****
    ** -2:
        6: ******
  **** -4:

我的想法是,我需要从左侧缩进一定量,然后打印必要的星号,然后用括号打印星号的数量。所以我的问题是如何更改代码以生成我想要的输出。

3 个答案:

答案 0 :(得分:0)

  

有负值的星号应如下所示:

     
 **[-2]
   [5 ]*****
***[-3]
   [9 ]*********

您可能希望自动调整实际值,例如如果值为-11,则[]括号中需要3个字符,[左侧至少需要11个字符。

这意味着您应首先遍历这些值以确定您需要多少空间。

然后,您可以为printf动态构建格式字符串,例如如果最小值为-11且最大值为<= 999,则如下所示:

"%11s[%-3d]%s%n"

然后你给它一个包含*星的字符串,而不是直接打印它们。最好的方法是使用repeat辅助方法。

代码可能是这样的:

private static void printArray(int... arr) {
    int min = -1, numLen = 1;
    for (int val : arr) {
        min = Math.min(min, val);
        numLen = Math.max(numLen, Integer.toString(val).length());
    }
    String fmt = "%" + -min + "s[%" + numLen + "d]%s%n";
    for (int val : arr) {
        if (val >= 0)
            System.out.printf(fmt, "", val, repeat('*', val));
        else
            System.out.printf(fmt, repeat('*', -val), val, "");
    }
}
private static String repeat(char c, int len) {
    char[] buf = new char[len];
    Arrays.fill(buf, c);
    return new String(buf);
}

测试

public static void main(String[] args) {
    printArray(buildArray(14, -20, 20));
}
private static int[] buildArray(int len, int min, int max) {
    Random r = new Random();
    int[] arr = new int[len];
    for (int i = 0; i < len; i++)
        arr[i] = r.nextInt(max - min + 1) + min;
    return arr;
}

示例输出

               [  6]******
   ************[-12]
             **[ -2]
               [  5]*****
               [ 17]*****************
               [  3]***
           ****[ -4]
               [  6]******
               [  3]***
               [  3]***
               [  0]
               [  4]****
***************[-15]
      *********[ -9]

答案 1 :(得分:0)

你可以将其分解为打印重复的字符,使代码更清晰:

public void printChart(int[] nums) {
    int offset = Math.max(0, - IntStream.of(nums).min().getAsInt());
    for (int n : nums) {
        int space = offset + Math.min(n, 0);
        int neg = Math.max(-n, 0);
        int pos = Math.max( n, 0);
        System.out.println(String.format("%3d ", n) + repeat(" ", space) +
                repeat("*", neg) + "|" + repeat("*", pos));
    }
}

对于“打印重复字符串”部分,您可以从this question中选择任何解决方案,例如this one,或使用简单的for循环和缓冲区滚动自己。

public String repeat(String s, int n) {
    return new String(new char[n]).replace("\0", s);
}

示例输出,nums = {5, 8, -4, 1, -3}(不完全像您想要的输出,但很容易适应,恕我直言,这样看起来更好):

  5     |*****
  8     |********
 -4 ****|
  1     |*
 -3  ***|

答案 2 :(得分:0)

尝试这个,我修改了随机函数以获得负值。事实上,有很多可能解决您的问题,但我刚刚选择修改您的代码。 (最好改变打印星号的方式)

要从左侧打印星号,您可以执行以下操作:

    public static void printAsterisk(int val)
        {
              if(val >= 0) {
                      for(int i = 0; i < val; i++) 
                System.out.print("*");
              }
              else {
                  val*=-1;
                  System.out.printf("%"+(18-val)+"s"," ");
                  for(int i = 0; i < val; i++) 
                      System.out.printf("%1c",'*');
              }
        }

完整代码:

public class BarChart
{
    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        Random gen = new Random();

        // Read for input of array legnth
        System.out.print("Enter Array Length: ");
        int n = gen.nextInt(6) + 10;
        System.out.println(n);

        int[] values = new int[n];
        int randNum;
        for(int i = 0; i < n; i++)
        {
            // Get random number between -10 and 20
            randNum = gen.nextInt(20+1+20) - 10;
            values[i] = randNum;
        }

        values[3] = -2;

        print(values);
        System.out.println();

        // Print each element as asterisks
        for(int i = 0; i < values.length; i++)
        {
            if(values[i] < 0)
            {
                printAsterisk(values[i]);
                System.out.printf("%1d:\n", values[i]);
            }
            else
            {
                System.out.printf("%20d:", values[i]);
                printAsterisk(values[i]);
                System.out.println();
            }
        }
    }

    // Methods
    /**
     * Prints an array
     * @param array array
     */
    public static void print(int[] array)
    {
        for(int i = 0; i < array.length; i++)
        {
            if(i > 0)
            {
                System.out.print(" | ");
            }
            System.out.print(array[i]);
        }
        System.out.println();
    }

    public static void printAsterisk(int val)
    {
          if(val >= 0) {
                  for(int i = 0; i < val; i++) 
            System.out.print("*");
          }
          else {
              val*=-1;
              System.out.printf("%"+(18-val)+"s"," ");
              for(int i = 0; i < val; i++) 
                  System.out.printf("%1c",'*');
          }


    }
}

输出:

               4:****
               5:*****
              29:*****************************
            **-2:
              11:***********
        ******-6:
    **********-10:
               0:
          ****-4:
              18:******************
             *-1:
         *****-5:
       *******-7: