Ký tự '\n' biến mất như thế nào qua method nextLine()?

Bữa nay tui có tìm hiểu về vấn đề trôi dòng lệnh ở java ví dụ như sau:

...
{
Scanner scan = new Scanner( System.in );
int number = scan.nextInt();
String str = scan.nextLine();
...
}

Để giải quyết thì có nhiều cách (new lại scan, thêm nextLine(), hoặc chuyển hết qua xử lý chuỗi, etc). Trong đó có cách là dùng nextLine() làm tui hơi bị thắc mắc một chút, tui đã google cách hoạt động của nó như sau:

The nextLine() method of java.util.Scanner class advances this scanner past the current line and returns the input that was skipped. This function prints the rest of the current line, leaving out the line separator at the end.
Câu hỏi của tui là nó xử lý cái ‘\n’ như thế nào? Có giống cái nào dưới đây không? ( ngôn ngữ C )

char str[100];
scanf("%[^\n] %*c", str);// là cái này
scanf("%[^\n]", str); // hay là cái này

Tui đoán là cái scanf("%[^\n] %*c", str); nhưng không chắc nó có hoạt động như thế hay là kiểu khác. Tui có thử “đọc” phương thức nextLine() trong Scanner.java rồi nhưng trình không đủ để hiểu. Mong mọi người giải đáp.
Xin cảm ơn.

2 Likes

Java là ngôn ngữ đa nền nên có thể kí tự ngắt dòng/xuống dòng có thể là '\n', '\r' thậm chí là kết hợp "\r\n".

Việc “trôi lệnh” thì ngôn ngữ nào cũng gặp. Nó “trôi” do định dạng cần nhập thôi.
Người lập trình muốn người dùng nhập:

1234 6789 ghi

"1234\x206789\x20ghi" phân cách bằng khoảng trắng.
Người nhập lại nhập kiểu:

1234
6789
ghi

"1234\n6789\nghi" phân cách bằng kí tự dòng mới.
Có đúng định dạng cần nhập đâu.
cin.ignore() hay sc.nextLine() dùng để bỏ kí tự xuống dòng để nhận đúng chuỗi phía sau. Nhiều bạn hay dùng nó để “chống trôi lệnh”.

Còn nextLine() là để đọc 1 dòng. Tức là đọc từ vị trí hiện tại cho đến khi gặp kí tự xuống dòng thì dừng và trả về các kí tự đã đọc (không bao gồm kí tự xuống dòng - phớt lờ/loại bỏ kí tự xuống dòng).
Nếu đọc mà không dùng tới thì chẳng phải là nó “biến mất” à?
Biểu thức chính quy (Regex) trong Java cho cho việc đọc 1 dòng của Scanner:

    private static volatile Pattern separatorPattern;
    private static volatile Pattern linePattern;
    private static final String LINE_SEPARATOR_PATTERN =
                                           "\r\n|[\n\r\u2028\u2029\u0085]";
    private static final String LINE_PATTERN = ".*("+LINE_SEPARATOR_PATTERN+")|.+$";

    private static Pattern separatorPattern() {
        Pattern sp = separatorPattern;
        if (sp == null)
            separatorPattern = sp = Pattern.compile(LINE_SEPARATOR_PATTERN);
        return sp;
    }

    private static Pattern linePattern() {
        Pattern lp = linePattern;
        if (lp == null)
            linePattern = lp = Pattern.compile(LINE_PATTERN);
        return lp;
    }
6 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?