0

以下は明らかに非常に非現実的ですが、私の講師はプログラミングの非常に基本的な理解を私たちに教えることを主張しています。彼が私たちに与えた運動は次のようになります:

System.in.read、int、char、およびloopsのみを使用して、コマンドラインからユーザー入力を読み取り、入力された文字数とまったく同じ大きさのchar[]を返すメソッドを作成します。System.arraycopy()または他のライブラリメソッドを使用しないでください。

私は無知です。System.in.read入力をバッファリングする方法がないように思われるため、文字を解析する前に配列のサイズを完全に設定する必要があります。これは世界でどのように機能するはずですか?

4

3 に答える 3

1

コマンドラインからユーザー入力を読み取り、char[]を返すメソッドを作成します。

考え直してみると、char[]配列を自分で拡張することによって、独自の入力バッファリングを行うことになっていると思います。System.arraycopy()それが言及される理由であるはずです。

アレイの成長は次のように機能します

  • 既存の配列より1項目長い新しい配列を作成します。
  • 古い配列の各文字に対して
    • 位置を維持したまま、古い配列から新しい配列に文字をコピーします
  • 古いアレイを拡張アレイに置き換えます。

これを入力ストリームからすべての文字を読み取るループと組み合わせると、次のことがわかり、割り当てを行う必要があります。

  • 長さ0の配列で開始
  • 一方、文字は入力ストリームから入手できます
    • アレイを1つ大きくします
    • inputstreamの文字を配列の最後のスロットに配置します
  • 配列を返す

ループや増大する配列なしでそれを行うことさえ可能です。正しいサイズの新しい配列を一度作成するだけです。

private static char[] readToCharArray(int length) throws IOException {
    int read = System.in.read();
    char[] result;
    if (read == -1 || read == '\r' || read == '\n' ) {
        result = new char[length];
    } else {
        result = readToCharArray(length + 1);
        result[length] = (char) read;
    }
    return result;
}

char[] myArray = readToCharArray(0);
于 2012-11-22T00:34:46.687 に答える
0

手動アレイコピーについてはどうですか、テキストはそれについて何も述べていませんか?それが許可されている場合は、次のようなことを行うことができます。

    private static char[] readInput() throws IOException {
      System.out.println("type something terminated with '|'");
      char[] input = new char[0];
      int count = 0;
      int read;
      for (; ; ) {
        read = System.in.read();
        if (read == '|') {
          break;
        } else {
          char[] tmp = new char[input.length + 1];
          for (int i = 0; i < input.length; i++) {
            tmp[i] = input[i];
          }
          input = tmp;
        }
        input[count] = (char) read;
        count++;
      }
      return input;
    }

read == -1代わりにチェックすることもできますがread == '|'、入力の終わりの文字はシステムごとに異なります。反復ごとにchar[]をコピーする代わりに、x回の反復ごとにコピーして、最後に正しいサイズの配列を作成することもできます。whileループを使用することもできます...

しかし、提案されているように、正しいサイズの空の配列を返す方が間違いなくもっと楽しいでしょうzapl:)

于 2012-11-22T00:36:15.633 に答える
0

あなたの講師は次のことを意味していると思います。

  • char []には、System.inから読み取られた文字が含まれている必要があります(適切なサイズだけではありません)
  • " "は、上の他のオーバーロードされたメソッドSystem.in.readのみを参照し、参照しないため、一度に1文字を読み取るように制限されます。InputStream#read()readInputStream

実装方法を確認する必要がArrayListあります。配列に支えられていますが、リストは任意にサイズ変更できます。リストのサイズが配列サイズを超えると、ArrayListより大きな新しい配列を作成し、古い配列の内容をその配列にコピーします。ここにいくつかの関連する抜粋がありますArrayList

/**
 * Appends the specified element to the end of this list.
 *
 * @param e element to be appended to this list
 * @return <tt>true</tt> (as specified by {@link Collection#add})
 */
public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

private void ensureCapacityInternal(int minCapacity) {
    modCount++;
    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

/**
 * Increases the capacity to ensure that it can hold at least the
 * number of elements specified by the minimum capacity argument.
 *
 * @param minCapacity the desired minimum capacity
 */
private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
}

は使用できないためSystem.arraycopy()、独自のメソッドを作成する必要があります。それはただのforループです。

これは実際にはそれほど非効率的ではありません。javadocで説明されているようにArrayList#add(E)、償却された定数時間で実行されます。

戦略に正確に従うとArrayList、結果の配列は必要以上に大きくなるため、最後に、入力サイズに正確に切り捨てるために、最後にもう1つ配列のサイズ変更を行う必要があります。または、文字を読み取るたびに配列を1ずつ増やすこともできますが、実行時間は入力長が線形(n)ではなく2次(n ^ 2)になります。

于 2012-11-22T00:38:12.133 に答える