2014-11-23 48 views
0

我是编程新手,一直在尝试通过编写一个简单的程序来学习Java的基础知识,该程序将应用凯撒转换为一些文本。我已经能够做到这一点,迄今为止我的代码是这样的:尝试块内的代码被忽略,为什么?

  1. 询问用户他们想要移动文本的单位数。
  2. 提示用户输入一些文本。
  3. 通过该单位应用凯撒班次并打印结果。

这里是工作代码:

import java.util.Scanner; 
class Shift{ 

public static void main(String[] args){ 

    //This will scan for user input. 
    Scanner sc = new Scanner(System.in); 
    System.out.print("Shift by this many characters (0-25): "); 
    int shift = sc.nextInt(); 
    sc.nextLine();//Skips over the whitespace after the integer 
    System.out.print("Enter Text: "); 
    String input = sc.nextLine(); 
    sc.close(); 

    //Initialise a character array containing every letter in the alphabet. 
    char[] alphabetArray = {'a','b','c','d','e','f','g','h','i','j','k','l','m', 
          'n','o','p','q','r','s','t','u','v','w','x','y','z'}; 
    char[] alphabetArrayCaps = {'A','B','C','D','E','F','G','H','I','J','K','L','M', 
           'N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}; 

    //Initialise the two variables that will be used in the next step. 
    char[] constantArray = input.toCharArray(); 
    char[] output = input.toCharArray(); 

    //Implement a Caesar shift by the given number of units. 
    for (int i=0; i < constantArray.length; i++){ //cycles through the user input character by character 
     for (int j=0; j <= 25; j++){ //cycles through the alphabet 
      if (constantArray[i] == alphabetArray[j]){ 
        output[i] = alphabetArray[(j+shift)%26]; 
      } 
      else if (constantArray[i] == alphabetArrayCaps[j]){ 
         output[i] = alphabetArrayCaps[(j+shift)%26]; 
      } 
     } 
    } 
    System.out.println(output); 
    } 
    } 

这段代码的问题是,当用户被要求输入一个整数,就会有一个例外,如果输入别的。我认为这将是了解处理异常的好地方,并且已经提到this guide关于如何使用try-catch块来达到这个目的。

我遇到的问题是代码(下面)似乎完全忽略了我的尝试块。我认为这是因为我的try块包含整数“shift”被声明的行,并且当我向下滚动到代码中实际使用的“shift”的位置时,我得到一个警告,指出“shift无法解析为一个变量“,它无法编译。

下面是导致问题的代码,唯一的区别是我在try块中包含了一行,并在它后面添加了一个catch块,它应该会打印一条错误消息(尽管我没有将代码编译尚未有机会玩这个,看看它实际上做了什么)。

import java.util.Scanner; 
class Shift{ 

public static void main(String[] args){ 

    //This will scan for user input. 
    Scanner sc = new Scanner(System.in); 
    System.out.print("Shift by this many characters (0-25): "); 

    try { 
     int shift = sc.nextInt(); 
    } 
    catch (java.util.InputMismatchException e){ 
     System.err.println("InputMismatchException: " + e.getMessage());       
    } 

    sc.nextLine();//Skips over the whitespace after the integer 
    System.out.print("Enter Text: "); 
    String input = sc.nextLine(); 
    sc.close(); 

    //Initialise a character array containing every letter in the alphabet. 
    char[] alphabetArray = {'a','b','c','d','e','f','g','h','i','j','k','l','m', 
          'n','o','p','q','r','s','t','u','v','w','x','y','z'}; 
    char[] alphabetArrayCaps = {'A','B','C','D','E','F','G','H','I','J','K','L','M', 
           'N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}; 

    //Initialise the two variables that will be used in the next step. 
    char[] constantArray = input.toCharArray(); 
    char[] output = input.toCharArray(); 

    //Implement a Caesar shift by the given number of units. 
    for (int i=0; i < constantArray.length; i++){ //cycles through the user input character by character 
     for (int j=0; j <= 25; j++){ //cycles through the alphabet 
      if (constantArray[i] == alphabetArray[j]){ 
        output[i] = alphabetArray[(j+shift)%26]; 
      } 
      else if (constantArray[i] == alphabetArrayCaps[j]){ 
         output[i] = alphabetArrayCaps[(j+shift)%26]; 
      } 
     } 
    } 
    System.out.println(output); 
    } 
    } 

那么,为什么这一小小的变化突然停止了“宣告”的“转移”呢?

+0

不在这里给出答复,但它会如果你改变你的char数组声明为'char [] alphabetArray =“abcdefghijklmnopqrstuvwxyz”.toCharArray'和'char [] alphabetArrayCaps =“ABCDEFGHIJKLMNOPRSTUVWXYZ”.toCharArray();' – mirvine 2014-11-23 21:35:43

+0

@ itrollin98我在想,当我这样做时,必须有一个更简单的方法。这真是一个很棒的提示,谢谢。 – Peachy 2014-11-23 21:43:38

回答

6

变量仅限于他们在声明范围有关更多信息,请参见this nice little tutorial about variable scope in Java(或见JLS section 6.3,如果你想获得的技术,在您的情况下开始的行用“的范围。局部变量声明“是相关的)。

范围最简单的解释是{ ... }对他们宣布

你的情况:

... 
try { 
    int shift = sc.nextInt(); 
} ... 

变量shift不是try块的{ ... }外部可见。您必须在更高的范围内声明它,例如作为该方法的局部变量。然而,在try块的情况下,如果简单地向外移动的声明,你还是会碰到一个,因为在这个“变量可以使用未初始化的”警告:

int shift; 

try { 
    shift = sc.nextInt(); 
} catch (...) { 
    ... 
} 

代码所在路径nextInt()抛出一个例外仍然可以让shift未初始化。要解决,在这种情况下,一个选择是仅将其初始化:

int shift = 0; 

try { 
    shift = sc.nextInt(); 
} catch (...) { 
    ... 
} 

另一种选择是,以确保它得到即使抛出一个异常值:

int shift; 

try { 
    shift = sc.nextInt(); 
} catch (...) { 
    shift = 0; 
    ... 
} 

第三种选择是构建你的代码,这样的方式是shift从未尝试,如果有异常抛出使用,虽然这不太适合你的榜样(但是,为了完整):

int shift; 

try { 
    shift = sc.nextInt(); 
} catch (Exception x) { 
    throw x; 
} 

// shift can never be used uninitialized here 

和第四选项是构建你的代码中,使得shift不需要try块外:

try { 
    int shift = sc.nextInt(); 
    // do everything that needs to be done with shift here 
} catch (...) { 
    ... 
} 

// shift is unneeded here 
3

声明在块外移位。由于移动只在内部有范围发生问题。更改为:

int shift=0; 
try { 
    shift = sc.nextInt(); 
} 
+0

请注意,这将导致“移位可能会被使用未初始化”错误,除非您要么初始化它或确保'catch'块也给它一个值。 – 2014-11-23 21:39:04

+0

@JasonC你绝对正确。我没有注意到它。我改变了它。 – kriyeta 2014-11-23 21:42:57

1

的问题是,当你声明一个变量try块内部的变量的作用域是那个try块。一旦try块完成执行,所有在try块内声明的变量将被删除。您需要将该声明移至try块之外。就像这样:

int shift = 0; 
try { 
    shift = sc.nextInt(); 
} 
catch (java.util.InputMismatchException e){ 
    System.err.println("InputMismatchException: " + e.getMessage());       
} 

希望这有助于:)

0

在Java中,当你声明一个块中的变量,你正在做什么,我们称之为变量的局部声明。这意味着变量只能在您声明的块中可见。在这种情况下,由于您在try区块内宣布了您的shift,因此在try之外的任何地方都无法看到它。你可以做的解决仅仅是声明它的try块之外,像这样:

int shift; 
try { 
    shift = sc.nextInt(); 
} 
... 

你可以在这里了解更多关于声明的范围在Java中:https://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.3