2014-11-23 46 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