2012-04-05 93 views
0

我从一段代码中收到错误。我只会显示一行代码,至少我认为这一行是从错误报告中导致的。它是:使用一个隐含类型种姓是否改变变量的类型?

b = temp(temp.length-1).toInt; //temp is an ArrayBuffer[String] 

的错误是:

For input string: "z" 
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48) 
at java.lang.Integer.parseInt(Integer.java:449) 
at java.lang.Integer.parseInt(Integer.java:499) 
at scala.collection.immutable.StringLike$class.toInt(StringLike.scala:231) 
at scala.collection.immutable.StringOps.toInt(StringOps.scala:31) 
at Driver$.stringParse$1(Driver.scala:59) 
at Driver$.main(Driver.scala:86) 
at Driver.main(Driver.scala) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
at java.lang.reflect.Method.invoke(Method.java:597) 
at scala.tools.nsc.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:78) 
at scala.tools.nsc.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:24) 
at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:88) 
at scala.tools.nsc.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:78) 
at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:101) 
at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:33) 
at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:40) 
at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:56) 
at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:80) 
at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:89) 
at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala) 

从我可以告诉,这是造成问题与此有关。由于它是不可变的,我知道它不能改变。但我不确定。我基于此

at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48) 

一旦我做了像我上面的代码独立的东西,它是否会改变整个对象? Temp是一个ArrayBuffer [String]。所以我试图访问一个数字的字符串表示,并将其转换。但是在这样做的时候,这是否改变了它,并阻止我做任何事情?

如果你认为把我所有的代码都写好会让我知道编辑它,但它很多,我不想惹恼任何人。我感谢任何能够帮助我理解这一点的人!编辑:我的代码(只有在这里帮助我找出我的错误,但没有必要看,我只是不能看到它给我这个错误的地方)。

我的代码的目的是解析顶部的任何一个字符串。它放在一起并放入一个字符串中,然后读取其他两个符号以便与之一起使用。它解析str很好,但是它在str2中读取“z”,在str3中读取“y”时发现问题。正如人们所看到的那样,问题在于递归之后和之后的第二个字符串。同样重要的是要注意,字符串必须是这种形式。所以它只能被解析为“(和x(和y z))”,但不能以任何其他方式使它更方便。

val str = "(and x y)"; 
val str2 = "(and x (and y z))"; //case with expression on th right side 
val str3 = "(and (and x y) z)"; //case with expression ont he left side 

var i = 0; //just counter used to loop through the finished parsed array to make a list 
//var position = 0; //this is used for when passing it in the parser to start off at zero 
var hold = new ArrayBuffer[String]();//finished array should be here 

def stringParse (exp: String, expreshHolder: ArrayBuffer[String]): ArrayBuffer[String] = { //takes two arguments, string, arraybuffer 
    var b = 0; //position of where in the expression String I am currently in 
    var temp = expreshHolder; //holder of expressions without parens 
    var arrayCounter = 0; 
    if(temp.length == 0) 
     b = 0; 
     else { 
      b = temp(temp.length-1).toInt; 
      temp.remove(temp.length-1); 
      arrayCounter = temp.length; 
     } //this sets the position of wherever the string was read last plus removes that check from the end of the ArrayBuffer 
    //just counts to make sure an empty spot in the array is there to put in the strings 

    if(exp(b) == '(') { 
     b = b + 1; 

     while(exp(b) == ' '){b = b + 1;} //point of this is to just skip any spaces between paren and start of expression type 
     if(exp(b) == 'a') { 
      //first create the 'and', 'or', 'not' expression types to figure out 
      temp += exp(b).toString; 
      b = b+1; 
      temp(arrayCounter) = temp(arrayCounter) + exp(b).toString; //concatenates the second letter 
      b = b+1; 
      temp(arrayCounter) = temp(arrayCounter) + exp(b).toString; //concatenates the last letter for the expression type 
      //arrayCounter+=1; 
      //this part now takes the symbols and puts them in an array 
      b+=1; 

      while(exp(b) == ' ') {b+=1;} //just skips any spaces until it reaches the FIRST symbol 
      if(exp(b) == '(') { 
       temp += b.toString; 
       temp = stringParse(exp, temp); 
       b = temp(temp.length-1).toInt; 
       temp.remove(temp.length-1); 
       arrayCounter = temp.length-1 
       } else { 
        temp += exp(b).toString; 
        arrayCounter+=1; b+=1; } 

      while(exp(b) == ' ') {b+=1;} //just skips any spaces until it reaches the SECOND symbol 
      if(exp(b) == '(') { 
       temp += b.toString; 
       temp = stringParse(exp, temp); 
       b = temp(temp.length-1).toInt; 
       temp.remove(temp.length-1); 
       arrayCounter = temp.length-1 
       } else { 
        temp += exp(b).toString; 
        arrayCounter+=1; 
        b+=1; 

     } 
    temp; 
    } else { var fail = new ArrayBuffer[String]; fail +="failed"; fail;} 

} 
hold = stringParse(str2, ho); 
for(test <- hold) println(test); 
+0

摆脱行尾的所有分号。你不需要它们。 – dhg 2012-04-05 04:47:53

回答

2

temp包含什么?您的代码假定它包含String s,可以将其转换为Int s,但您似乎在其中有String"z"。这将产生错误:

scala> "z".toInt 
java.lang.NumberFormatException: For input string: "z" 
... 

这里是什么temp可能看起来像一个娱乐:

val temp = ArrayBuffer("1", "2", "z") 
temp(temp.length-1).toInt //java.lang.NumberFormatException: For input string: "z" 

所以,你需要弄清楚为什么有些String"z"正在步入temp

编辑:

所以你加入 “表情”,以temptemp += exp(b).toString),并且还加入指数(temp += b.toString)。那么你认为temp只保留指数(b = temp(temp.length-1).toInt)。您需要决定temp的用途,然后专门用于此目的。

+0

嗯,我会看看它。如果你想我可以张贴代码。在这样做之前,我会重新检查,但这不应该发生。它运行了我想要做的没有问题的简化版本。 – Andy 2012-04-05 01:50:01

+0

我发布了我的代码,如果你可以请看看它,如果它不是太麻烦。我一直在看它几个小时,但我不明白为什么存在这个错误。我会说这个。当它递归时,错误就在那里。但是从我写的内容来看,“z”如何以这种方式进入温度是没有意义的。我的逻辑应该工作。它适用于str。 – Andy 2012-04-05 04:40:49

+0

@安迪,编辑... – dhg 2012-04-05 04:46:59

1

不,toInt不会更改对象,它将该对象作为参数并返回一个整数,使对象保持原样。

1

我不明白你的问题,因为我不懂你的代码。 让我们试着简化你的代码。

首先:你有一个操作数的表达式类型,并列出了一些表达式:

scala> :paste 
// Entering paste mode (ctrl-D to finish) 

abstract sealed class Operand 
case class IdentOperand(name: String) extends Operand { override def toString(): String = name } 
case class IntOperand(i: Int) extends Operand { override def toString(): String = i.toString() } 
case class ExprOperand(expr: Expression) extends Operand { override def toString(): String = expr.toString() } 
case class Expression(exprType: String, operands: Seq[Operand]) { 
    override def toString(): String = operands.mkString("(" + exprType + " ", " ", ")") 
} 

// Exiting paste mode, now interpreting. 

defined class Operand 
defined class IdentOperand 
defined class IntOperand 
defined class ExprOperand 
defined class Expression 

scala> Expression("and", Seq(IdentOperand("x"), IdentOperand("y"))) 
res0: Expression = (and x y) 

scala> Expression("and", Seq(IdentOperand("x"), ExprOperand(Expression("and", Seq(IdentOperand("y"), IdentOperand("z")))))) 
res1: Expression = (and x (and y z)) 

scala> Expression("and", Seq(ExprOperand(Expression("and", Seq(IdentOperand("x"), IdentOperand("y")))), IdentOperand("z"))) 
res2: Expression = (and (and x y) z) 

现在我们就来解析字符串这种类型的表达式:

scala> import scala.util.parsing.combinator._ 
import scala.util.parsing.combinator._ 

scala> object ExspessionParser extends JavaTokenParsers { 
    | override def skipWhitespace = false; 
    | 
    | def parseExpr(e: String) = parseAll(expr, e) 
    | 
    | def expr: Parser[Expression] = "(" ~> exprType ~ operands <~ ")" ^^ { case exprType ~ operands => Expression(exprType, operands) } 
    | def operands: Parser[Seq[Operand]] = rep(" "~>operand) 
    | def exprType: Parser[String] = "and" | "not" | "or" 
    | def operand: Parser[Operand] = variable | exprOperand 
    | def exprOperand: Parser[ExprOperand] = expr ^^ (ExprOperand(_)) 
    | def variable: Parser[IdentOperand] = ident ^^ (IdentOperand(_)) 
    | } 
defined module ExspessionParser 

scala> ExspessionParser.parseExpr("(and x y)") 
res3: ExspessionParser.ParseResult[Expression] = [1.10] parsed: (and x y) 

scala> ExspessionParser.parseExpr("(and x (and y z))") 
res4: ExspessionParser.ParseResult[Expression] = [1.18] parsed: (and x (and y z)) 

scala> ExspessionParser.parseExpr("(and (and x y) z)") 
res5: ExspessionParser.ParseResult[Expression] = [1.18] parsed: (and (and x y) z) 

如今(作为就我所了解的代码而言),我们必须用整数值替换字符串操作数(x,y,z)。让我们这2项方法添加到Expression类:

def replaceOperands(ints: Seq[Int]): Expression = replaceOperandsInner(ints)._2 

    private def replaceOperandsInner(ints: Seq[Int]): (Seq[Int], Expression) = { 
    var remainInts = ints 
    val replacedOperands = operands.collect{ 
     case n: IdentOperand => 
     val replacement = remainInts.head 
     remainInts = remainInts.tail 
     IntOperand(replacement) 
     case ExprOperand(e) => 
     val (remain, replaced) = e.replaceOperandsInner(remainInts) 
     remainInts = remain 
     ExprOperand(replaced) 
    } 

    (remainInts, Expression(exprType, replacedOperands)) 
    } 

现在我们可以这样做:

scala> ExspessionParser.parseExpr("(and (and x y) z)").get.replaceOperands(Seq(1, 2, 3)) 
res7: Expression = (and (and 1 2) 3) 

如果你以字符串形式有整数值,那么你可以将它们转换第一:

scala> Seq("1", "2", "3") map { _.toInt } 
res8: Seq[Int] = List(1, 2, 3) 
+0

对于模糊性我表示歉意。你的代码更好,因为它更容易解析。但我必须以它所处的形式解析它。 – Andy 2012-04-05 13:58:39