【问题标题】:String Formatting with money [closed]用钱格式化字符串[关闭]
【发布时间】:2016-03-18 08:36:11
【问题描述】:

我正在尝试编写一个程序来接收输入和输出文件,其中包含硬币列表和这些硬币的数量。

import java.io.*;
import java.util.*;

public class CookieJar {
public static void cashingIn(File input, File output){
    try{
        Scanner in = new Scanner(input);
        PrintWriter writ = new PrintWriter(output);
        double sum = 0;
        if(in.hasNext()){
        String next = in.nextLine();
        Scanner help = new Scanner(next);
        while(in.hasNextLine()){
            int y = Integer.parseInt(next.substring(0, 1));
            if(next.contains("pennies")){
                sum += y*0.01;
            }
            if(next.contains("dimes")){
                sum += y*.1;
            }
            if(next.contains("quarters")){
                sum += y*.25;
            }
            if(next.contains("nickles")){
                sum += y*.05;
            }
            if(next.contains("penny")){
                sum += .01;
            }
            if(next.contains("dime")){
                sum += .1;
            }
            if(next.contains("nickle")){
                sum += .05;
            }
            if(next.contains("quarter")){
                sum += .25;
            }
            if(sum == 0){
                String find = String.format("%s", "You have no money in the jar");
                writ.println(find);
            }
            String fixer = String.format("$%sf", sum);
            writ.println("You have " + fixer + " in the jar");
        }
        help.close();
        }
        else{
            String find = String.format("%s" , "You have no money in the jar");
            writ.println(find);
        }
            in.close();

            writ.close();
    }catch(IOException e){

    }
 }
}

我在使用此代码时遇到的问题是,我无法从文件中获取硬币数量,并无法确定每种硬币的类型。这是我正在使用的测试方法的示例。

@Test
public void test3() {
    try {
        // create file
        File        input  = folder.newFile( "input.txt" );
        File        output = folder.newFile( "output.txt" );

        PrintWriter write  = new PrintWriter( input );
        write.println( "32 nickels" );
        write.println( " 1" );
        write.println( "   nickel 42" );
        write.println( "quarters 1 penny" );
        write.println( "1 quarter 23 pennies 16" );
        write.println( "" );
        write.println( "dimes 1 dime 1 dime 1 dime 1 dime" );
        write.close();

        // invoke program
        CookieJar.cashingIn( input, output );

        // verify file results
        assertTrue  ( "Output file does not exist", output.exists() );
        Scanner scan     = new Scanner( output );
        String  expected = "You have $14.64 in the jar";
        assertTrue  ( "Unexpected end of file: expected \"%s\"" + expected, scan.hasNext() );
        String  actual   = scan.nextLine();
        assertEquals( "Incorrect result", expected, actual );
        assertFalse ( "File contains more data than expected", scan.hasNext() );
        scan.close();
    } 
    catch (IOException e) {
        fail( "No exception should be thrown" );
    }
}

如果我进入千位,我还必须使数字带有逗号。我可能对帮助我所需的内容不够具体,所以如果您需要更多说明,请询问。感谢您的任何帮助。我对格式化很困惑。

【问题讨论】:

  • 不要使用double 来表示钱,它不能准确地表示所有值(例如,0.1 不能表示)。请改用BigDecimal
  • 包含“季度”的行也包含“季度”,因此您将重复计算所有金额(除了便士)
  • 你只检查下一个字符串一次,所以当你有行 write.println("dimes 1 dime 1 dime 1 dime 1 dime" );在您的测试代码中出现,它将运行以下 if 块一次: if(next.contains("dimes")){ sum += y*.1; } if(next.contains("dime")){ sum += .1;但我猜你需要在每次出现字符串时计算它。您还假设该数字仅在字符串的第一个字符中找到: int y = Integer.parseInt(next.substring(0, 1));当情况显然不是这样时
  • 正如@AndyTurner 建议的那样,您将重复计算大多数复数数量,因为 quarterquarters 中,dime 在 dimes 等。更重要的是使用int y = Integer.parseInt(next.substring(0, 1));,您只允许在每行的开头使用 1 位数字。您的测试数据似乎与该假设相矛盾。
  • @Draken 但OP也没有考虑数量何时出现在单位之前的行上,例如示例中为“1”和“镍”。

标签: java file split string-formatting stringtokenizer


【解决方案1】:

这是一种扩展评论,但我相信遵循这将帮助您自己解决问题。

你有一个测试很好,但它和代码测试/做的太多了。处理字符串和计算硬币至少是一项职责,而与文件交互绝对是另一项职责。通过同时测试两者,您的测试将变得复杂而缓慢。

应用Single Responsibility Principle 可以更轻松、更快速地进行测试:

//The ONLY responsibility of this class is to keep count of coin strings it is given
public class CookieJar {
   private double sum = 0; //consider internally counting pennies with an int

   public void addString(string next){
      int y = Integer.parseInt(next.substring(0, 1));
      if(next.contains("pennies")){
          sum += y*0.01;
      }
      //etc (but no code that reads/writes to console or files)
   }

   public string summarize(){
      if(sum == 0){
         return String.format("%s", "You have no money in the jar");
      }
      String fixer = String.format("$%sf", sum);
      return "You have " + fixer + " in the jar";
   }
}

测试将更容易编写和更快,您可以轻松地在单独的测试中单独测试每种硬币类型,然后在它们都工作时一起测试:

@Test
public void test3() {
    CookieJar cookieJar = new CookieJar();

    cookieJar.addString("32 nickels");

    assertEquals("You have $1.60 in the jar", cookieJar.summarize());
}

源文件代码现在看起来更简单了:

//The ONLY responsibility of this class is to allow reading and writing of coin files 
public final class CookieJarIo {

    private CookieJarIo(){} //static class

    public static void cashingIn(File input, File output){
        try{
            Scanner in = new Scanner(input);
            PrintWriter writ = new PrintWriter(output);

            CookieJar cookieJar = new CookieJar(); //use our other class

            if (in.hasNext()){
              String next = in.nextLine();
              Scanner help = new Scanner(next);
              while(in.hasNextLine()){
                cookieJar.addString(next);
                writ.println(cookieJar.summarize());
              }
              help.close();
            } else {
                writ.println(cookieJar.summarize());
            }
            in.close();

            writ.close();
        } catch(IOException e){

        }
    }
}

【讨论】:

    【解决方案2】:

    您应该认真考虑@weston 关于职责分离的回答。

    但是,在此代码中,如果您注意到您希望输入文件包含交替整数和字符串的流,则可以使其工作,例如

    32 nickels
     1
    nickel 42
    quarters 1 penny
    1 quarter 23 pennies 16
    
    dimes 1 dime 1 dime 1 dime 1 dime
    

    您可以使用Scanner in 检测和处理此模式中的令牌:

    int amountInPennies = 0;
    while (in.hasNextInt()) {
      int quantity = in.nextInt();
    
      if (!in.hasNext()) {
        System.err.println("Didn't have a unit! Stopping.");
        break;
      }
      String unit = in.next();
    
      switch (unit) {
        case "penny":
        case "pennies":
          amountInPennies += 1 * quantity;
          break;
        case "nickel":
        case "nickels":
          amountInPennies += 5 * quantity;
          break;
        // etc.
      }
    }
    BigDecimal amountInDollars = BigDecimal.valueOf(amountInPennies, -2);
    System.out.println("You have " + amount + " in the jar.");
    

    关于如何将金额格式化为货币,您应该查看NumberFormat.getCurrencyInstance()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-28
      • 2012-02-14
      相关资源
      最近更新 更多