Java 程序布局-通过System.in.read创建大小合适的阵列

Java 程序布局-通过System.in.read创建大小合适的阵列,java,arrays,loops,Java,Arrays,Loops,下面的内容显然非常不切实际,但我的讲师坚持要教我们对编程的基本理解。他给我们的练习是这样的: private static char[] readInput() throws IOException { System.out.println("type something terminated with '|'"); char[] input = new char[0]; int count = 0; int read; for

下面的内容显然非常不切实际,但我的讲师坚持要教我们对编程的基本理解。他给我们的练习是这样的:

    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;
    }
仅使用System.in.read、int、char和循环,创建一个读取 用户从命令行输入并返回一个char[],该char[]正好与数量一样大 输入的字符数。不要使用System.arraycopy()或其他库方法

我不懂。由于似乎没有办法缓冲System.in.read输入,因此在解析任何字符之前,必须完全调整数组的大小。这到底是怎么回事

创建一个从命令行读取用户输入并返回char[]的方法

再想一想,我假设您应该通过自己生长一个
char[]
数组来完成自己的输入缓冲。这应该是提到
System.arraycopy()
的原因

增长阵列的工作原理如下

  • 创建比现有阵列长1项的新阵列
  • 对于旧数组中的每个字符
    • 将字符从旧数组复制到新数组,保持位置不变
  • 将旧阵列替换为新阵列
如果您将其与从inputstream读取所有字符的循环相结合,您将了解以下内容,并且应该完成分配

  • 从长度为0的数组开始
  • 而字符可从inputstream获得
    • 将阵列放大一倍
    • 将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);

那么手动阵列复制呢,文本中没有提到这一点?如果允许,您可以这样做:

    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;
    }
private static char[]readInput()引发IOException{
System.out.println(“键入以“|”结尾的内容”);
字符[]输入=新字符[0];
整数计数=0;
int-read;
对于(;;){
read=System.in.read();
如果(读=='|'){
打破
}否则{
char[]tmp=新字符[input.length+1];
for(int i=0;i

您也可以检查
read==-1
而不是
read=='|'
,但输入字符的结尾因系统而异。除了在每次迭代中复制char[],您还可以每x次迭代复制一次,然后在最后创建一个大小正确的数组。你也可以使用while循环


但是,按照
zapl
的建议,返回一个正确大小的空数组肯定会更有趣:)

我假设您的讲师的意思是:

  • 字符[]应包含从System.in读取的字符(不仅仅是正确的大小)
  • System.in.read
    ”仅指
    InputStream#read()
    ,而不指
    InputStream
    上其他重载的
    read
    方法,因此您只能一次读取一个字符
您应该看看
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);
}
/**
*将指定的元素追加到此列表的末尾。
*
*要附加到此列表的@param e元素
*@return true(由{@link Collection#add}指定)
*/
公共布尔加法(E){
确保RecapacityInternal(大小+1);//递增modCount!!
elementData[size++]=e;
返回true;
}
私有网络容量内部(int minCapacity){
modCount++;
//有溢出意识的代码
如果(最小容量-elementData.length>0)
增长(生产能力);
}
/**
*增加容量,以确保它至少可以容纳
*最小容量参数指定的元素数。
*
*@param minCapacity所需的最小容量
*/
私人空间增长(单位容量){
//有溢出意识的代码
int oldCapacity=elementData.length;
int newCapacity=oldCapacity+(oldCapacity>>1);
if(新容量-最小容量<0)
新容量=最小容量;
if(新容量-最大阵列大小>0)
新容量=大容量(最小容量);
//minCapacity通常接近大小,因此这是一个胜利:
elementData=Arrays.copyOf(elementData,newCapacity);
}
由于无法使用
System.arraycopy()
,因此需要编写自己的方法来完成此操作。这只是一个
for
循环

事实上,这并不是那么低效。正如javadoc所描述的,
ArrayList#add(E)
在摊销固定时间内运行


如果您严格遵循
ArrayList
策略,那么生成的数组将比需要的数组大,因此在最后,您需要在最后再进行一次数组调整,以将其截断为输入大小。或者,您可以在每次读取字符时将数组增加1,但在输入长度中,运行时间将是二次的(n^2),而不是线性的(n)。

了解输入的字符数。创建了一个大小相同的字符数组。不知道问题是什么。(坚持对编程有一个非常基本的理解有什么错?)我想他打算让你自己做自定义缓冲。您不限于制作一个字符数组和一个字符数组。如果您只有一个字符数组,则无法缓冲内容