Parse input without using anything but System.in.r

2019-05-06 12:53发布

I'm having a hard time finding details on how exactly System.in.read(); works, maybe somebody could help me out. Seems like Scanner would be preferable, but I'm not allowed to use it.

I was given an assignment where I'm supposed to read console user input in the form Boolean-Operator-Boolean, e.g. T^F or T&T via System.in.read() and simply print what the statement returns.

Normal people would probably use a different method, but the assignment specifically states that only System.in.read() and System.out.println() are allowed.

Here's my attempt at solving it:

import java.io.*;

public static void main(String[] args) {

  String error = "Reading error, please use T or F";

  boolean a = true;  //char: 84 or 116 for T and t
  boolean b = false; //char: 70 or 102 for F and f
  int userChar1;
  int userOperator;
  int userChar2;
  int chosenOperator = 0;

  try {

    //Get first char
    System.out.println("Enter the first value (T or F):");
    userChar1 = System.in.read();

    if((userChar1==84)||(userChar1==116)) { // T or t
      a = true;
    } else if ((userChar1==70)||(userChar1==102)) { // F or f
      a = false;
    } else {
      System.out.println(error);
    }


    //Get second char
    System.out.println("Select an operator:  &  |  ^");
    userOperator = System.in.read();

    if(userOperator==38) { // &
      chosenOperator = 0;
    } else if (userOperator==124) { // |
      chosenOperator = 1;
    } else if (userOperator==94) { // ^
      chosenOperator = 2;
    } else {
      System.out.println(error);
    }


    //Get third char 
    System.out.println("Enter the second value:");
    userChar2 = System.in.read();
    System.in.close();
    if((userChar2==84)||(userChar2==116)) {
      b = true;
    } else if ((userChar2==70)||(userChar2==102)) {
      b = false;
    } else {
      System.out.println(error);
    }


    //Figure out result
    boolean result;
    switch (chosenOperator) {
    case 0:
      result = a&b;   
    case 1:
      result = a|b;
    case 2:
      result = a^b;

      System.out.println(result);

    }

  } catch(IOException e) {

  }
}

Executing this code makes the console wait for user input after the first System.in.read() and has it check the char input correctly. After that however, all succeeding System.in.read() are ignored and the program terminates.

I found a piece of code that used System.in.close(), so still not knowing what exactly the methods do I spliced that in after every System.in.read(). This results in the programs termination when the first System.in.read() after a System.in.close() is called.

So, what is going on exactly? How would you use System.in.read() correctly?

标签: java input io
3条回答
我只想做你的唯一
2楼-- · 2019-05-06 13:29

Have a look at the following part of code:

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

String input = null;

//  read the input from the command-line; need to use try/catch with the
//  readLine() method
try {
input = br.readLine();
} catch (IOException e) {
      System.out.println("IO error trying to read your input!");
      System.exit(1);
}
System.out.println("your input: "+input);

If your not allowed to use the bufferReader, i sugest you look at the source code of the bufferReader.

查看更多
做个烂人
3楼-- · 2019-05-06 13:33

The problem is not with System.in.read(), but with the console. The console is usually buffered, that means data is sent to your program (and thus readable by System.in.read()) only after the enter key is pressed. So you would have to switch the console to an unbuffered mode, but there is no portable way to do this, because there are so much different types of consoles (unix shell, cmd window, Eclipse console etc.).
If you are not allowed to use anything other than System.in.read() and System.out.println() methods, you have to let the user enter the complete term in a line, press enter and then you can process the characters entered, e.g:

public static void main(String[] args) throws IOException {
    boolean a = true; // char: 84 or 116 for T and t
    boolean b = false; // char: 70 or 102 for F and f
    int userChar1;
    int userOperator;
    int userChar2;

    System.out.println("Please enter the term, e.g. T&F:");

    userChar1 = System.in.read();
    userOperator = System.in.read();
    userChar2 = System.in.read();

    a = userChar1 == 'T' || userChar1 == 't';
    b = userChar2 == 'T' || userChar1 == 't';

    switch (userOperator) {
    case '&':
        System.out.println(a & b);break;
    case '|':
        System.out.println(a | b);break;
    case '^':
        System.out.println(a ^ b);break;
    default:
        System.out.println("unknow operator");
    }
}
查看更多
男人必须洒脱
4楼-- · 2019-05-06 13:44

Personally I had no problem with running your code, but it had some strange effects that I had to study.

The main problem with this approach (using System.in.read()) is that when user inputs some character, he has to press enter and thus you have 2 characters instead of 1 that you expect -- the first character that user inputs (let's assume, T or F in your case) and new line character.

I managed to get your code working with minor changes. You need to invoke overloaded version of read() method -- read(byte[] b) which reads some number of bytes from the input stream and stores them into the buffer array.

Here's the first part of your code, modified:

byte[] input = new byte[10];
System.out.println("Enter the first value (T or F):");
System.in.read(input);
userChar1 = input[0];
if ((userChar1 == 84) || (userChar1 == 116)) { // T or t
    a = true;
} else if ((userChar1 == 70) || (userChar1 == 102)) { // F or f
    a = false;
} else {
    System.out.println(error);
}

Note, we don't care about what read() returns, we only care of the first char from input array. The rest of the code is modified in the same way, you can even use the same buffer array (input) and query for 0-th element.

查看更多
登录 后发表回答