0

ここでは、長さ 1 の配列で開始し、ユーザーが配列にエントリを作成できるようにし、ユーザーがエントリを作成するたびに配列のサイズを 2 倍にして、java.lang.ArrayIndexOutOfBoundsExceptionを回避するプログラムを用意しています。エラー。コードが以下に記述されている方法では、2 番目のユーザー エントリの後、コンピュータはelseをスキップし、 Sorry, database is fullに直行します。最初のelse ifブロックにnewRecords = recordsを追加すると、 java.lang.ArrayIndexOutOfBoundsExceptionエラーが発生します。

public class PhoneDirectory5 {
    public static void main(String args[]) {
        **PhoneRecord[] records= new PhoneRecord[1];
        int numRecords = 0;**

        // Display list of commands
        System.out.println("Phone directory commands: \n" +
                " a - Add a new phone number\n" +
                " f - Find a new phone number\n" +
                " q - Quit\n" +
                " d - Delete record\n");

        // Read and execute commands
        while (true) {

            // Prompt user to enter a command
            SimpleIO.prompt("Enter command (a, f, d, or q): ");
            String command = SimpleIO.readLine().trim();

            // Determine whether command is "a", "f", "q", or
            // illegal. Execute command if illegal.
            **if (command.equalsIgnoreCase("a"))** {

                // Command is "a". prompt user for name and number,
                // then create a phone record and store it in the
                // database.
                **if (numRecords < records.length) {
                    SimpleIO.prompt("Enter a new name: ");
                    String name = SimpleIO.readLine().trim();
                    SimpleIO.prompt("Enter new phone number: ");
                    String number = SimpleIO.readLine().trim();
                    records[numRecords] =
                            new PhoneRecord(name, number);
                    numRecords++;
                } else if (numRecords == records.length) {
                    PhoneRecord[] newRecords = new PhoneRecord[records.length*2];
                    System.arraycopy(records, 0, newRecords, 0, records.length);
                    SimpleIO.prompt("Enter a new name: ");
                    String name = SimpleIO.readLine().trim();
                    SimpleIO.prompt("Enter new phone number: ");
                    String number = SimpleIO.readLine().trim();
                    newRecords[numRecords] =
                            new PhoneRecord(name, number);
                    numRecords++;**
                } else
                    System.out.println("Sorry, database is full.");

            } else if (command.equalsIgnoreCase("f")) {

                // Command is "f". Prompt user for search key.
                // Search the database for records whose name begins
                // with the search key. Print these names and the
                // corresponding phone numbers.
                SimpleIO.prompt("Enter name to look up: ");
                String key = SimpleIO.readLine().trim().toLowerCase();
                for (int i = 0; i < numRecords; i++) {
                    String name = records[i].getName().toLowerCase();
                    if (name.startsWith(key)) {
                        System.out.println(records[i].getName() + " " +
                                records[i].getNumber());
                        break;
                    } else if (i == numRecords - 1)
                        System.out.println("Sorry, your search did not" +
                                " match any records.");
                }
            } else if (command.equalsIgnoreCase("d")) {
                SimpleIO.prompt("Enter the name of the record to delete: ");
                String key = SimpleIO.readLine().trim().toLowerCase();
                for (int i = 0; i < numRecords; i++) {
                    String name = records[i].getName().toLowerCase();
                    if (name.startsWith(key)) {
                        records[i] = new PhoneRecord("", "");
                        break;
                    } else if (i == numRecords - 1)
                        System.out.println("Sorry, your search did not match" +
                                " any records.");
                }

            } else if (command.equalsIgnoreCase("q")) {
                // Command is "q".. Terminate program
                System.out.println("You have elected to exit the phone directory.");
                return;

            } else {
                // Command is illegal. Display error message.
                System.out.println("Command was not recognized; " +
                        "please enter only a, f, d or q.");
            }
            System.out.println();
        }
    }
}

// Represents a record containing a name and a phone number
class PhoneRecord {
    private String name;
    private String number;

    // Constructor
    public PhoneRecord(String personName, String phoneNumber) {
        name = personName;
        number = phoneNumber;
    }

    // Returns the name stored in the record
    public String getName() {
        return name;
    }

    // Returns the phone number stored in the record
    public String getNumber() {
        return number;
    }
}

そうは言っても、この方法で新しい配列スペースを割り当てたとき...

else if (numRecords == records.length) {
                    PhoneRecord[] newRecords = new PhoneRecord[records.length*2];
                    for (int i = 0; i < records.length; i++)
                        newRecords[i] = records[i];
                    records = newRecords;
                    SimpleIO.prompt("Enter a new name: ");
                    String name = SimpleIO.readLine().trim();
                    SimpleIO.prompt("Enter new phone number: ");
                    String number = SimpleIO.readLine().trim();
                    newRecords[numRecords] =
                            new PhoneRecord(name, number);
                    numRecords++;

...プログラムは、私が必要としていたことを正確に実行しました。つまり、ユーザーエントリごとに配列のサイズを2倍にし、「申し訳ありませんが、データベースがいっぱいです」というメッセージを出力しませんでした。私の質問は、.arraycopyメソッドでプログラムを動作させることができないのはなぜですか? どんな助けでも大歓迎です。

これをすると…

else if (numRecords == records.length) {
                    PhoneRecord[] newRecords = new PhoneRecord[records.length*2];
                    System.arraycopy(records, 0, newRecords, 0, records.length);
                    **newRecords = records;**
                    SimpleIO.prompt("Enter a new name: ");
                    String name = SimpleIO.readLine().trim();
                    SimpleIO.prompt("Enter new phone number: ");
                    String number = SimpleIO.readLine().trim();
                    newRecords[numRecords] =
                            new PhoneRecord(name, number);
                    numRecords++;

... arrayindexoutofbounds エラーが発生したときです。

4

3 に答える 3

3

Java では、配列は固定長です。ゼロからプログラミングするのではなく、動的な長さの配列が必要な場合は、標準 API で指定されているものを使用する必要があります: java.util.ArrayList. ここのドキュメントを見てください: http://download.oracle.com/javase/6/docs/api/java/util/ArrayList.html。このクラスは Java コレクション API の一部であり、Java プログラマーが知っておく必要があります。Java チュートリアルでそれらの使用方法を学びます。

a ではなく、s のPhoneRecord[]リストがあります。PhoneRecord

List<PhoneRecord> records = new ArrayList<PhoneRecord>();

で新しいレコードを追加できます

records.add(newRecord);

配列リストでラップされた配列は、必要に応じて自動的に拡張されます。

そして、特定のインデックスにアクセスできます

PhoneRecord record = records.get(index);

array を使用する場合と同様に、リストを反復処理することもできます。

for (PhoneRecord record : records) {
    // ...
}
于 2011-03-04T08:04:57.360 に答える
0

これを回避する最も簡単な方法は、例外のtry/catchを作成することだと思います。例外が発生したら、新しいアレイを作成します。arraycopyを機能させることができない場合は、いつでもループを作成して、古い配列から新しい配列に要素をコピーできます。

于 2011-03-07T01:33:02.233 に答える
0

System.arraycopy の例では、newRecords をレコードに割り当てていません。

編集: JB Nizet に同意します。代わりに ArrayList を使用する必要があります。

于 2011-03-04T07:50:55.310 に答える