Câu trả lời:
Họ là những nhân vật khác nhau. \r
là vận chuyển trở lại, và \n
là nguồn cấp dữ liệu.
Trên các máy in "cũ", \r
gửi đầu in trở lại đầu dòng và \n
nâng giấy lên một dòng. Cả hai đều cần thiết để bắt đầu in trên dòng tiếp theo.
Rõ ràng điều đó bây giờ có phần không liên quan, mặc dù tùy thuộc vào bảng điều khiển, bạn vẫn có thể sử dụng \r
để di chuyển đến đầu dòng và ghi đè lên văn bản hiện có.
Quan trọng hơn, Unix có xu hướng sử dụng \n
như một dấu tách dòng; Windows có xu hướng sử dụng \r\n
như một trình phân tách dòng và máy Mac (tối đa OS 9) được sử dụng để \r
phân tách dòng. (Mac OS X là Unix-y, vì vậy sử dụng \n
thay thế; có thể có một số tình huống tương thích \r
được sử dụng thay thế.)
Để biết thêm thông tin, xem bài viết mới Wikipedia .
EDIT: Đây là ngôn ngữ nhạy cảm. Ví dụ, trong C # và Java, \n
luôn có nghĩa là Unicode U + 000A, được định nghĩa là nguồn cấp dữ liệu. Trong C và C ++, nước có phần lầy hơn, vì ý nghĩa là đặc thù của nền tảng. Xem ý kiến để biết chi tiết.
\n
được đảm bảo là dòng mới (phần 2.4.4.4). Tất nhiên, sẽ rất tuyệt nếu OP đã chỉ định nền tảng ... Bên cạnh đó, tôi nghĩ mức độ chi tiết này sẽ khó hiểu hơn là hữu ích cho ai đó chỉ hỏi sự khác biệt.
Trong C và C ++, \n
là một khái niệm, \r
là một ký tự và \r\n
(hầu như luôn luôn) là một lỗi di động.
Hãy nghĩ về một teletype cũ. Đầu in được định vị trên một số dòng và trong một số cột. Khi bạn gửi một ký tự có thể in tới teletype, nó sẽ in ký tự đó ở vị trí hiện tại và di chuyển đầu đến cột tiếp theo. (Đây là khái niệm giống như một máy đánh chữ, ngoại trừ việc máy chữ thường di chuyển giấy đối với đầu in.)
Khi bạn muốn hoàn thành dòng hiện tại và bắt đầu dòng tiếp theo, bạn phải thực hiện hai bước riêng biệt:
ASCII mã hóa các hành động này dưới dạng hai ký tự điều khiển riêng biệt:
\x0D
(CR) di chuyển đầu in trở lại đầu dòng. (Unicode mã hóa cái này là U+000D CARRIAGE RETURN
.)\x0A
(LF) di chuyển đầu in xuống dòng tiếp theo. (Unicode mã hóa cái này là U+000A LINE FEED
.)Trong thời của teletypes và máy in công nghệ đầu tiên, mọi người thực sự đã tận dụng thực tế rằng đây là hai hoạt động riêng biệt. Bằng cách gửi CR mà không theo dõi nó bởi một LF, bạn có thể in qua dòng bạn đã in. Điều này cho phép các hiệu ứng như dấu, kiểu in đậm và gạch chân. Một số hệ thống được in đè nhiều lần để ngăn mật khẩu hiển thị trong bản cứng. Trên các thiết bị đầu cuối CRT nối tiếp ban đầu, CR là một trong những cách để kiểm soát vị trí con trỏ để cập nhật văn bản đã có trên màn hình.
Nhưng hầu hết thời gian, bạn thực sự chỉ muốn đi đến dòng tiếp theo. Thay vì yêu cầu cặp ký tự điều khiển, một số hệ thống chỉ cho phép cái này hoặc cái kia. Ví dụ:
U+0085 NEXT LINE
, nhưng giá trị EBCDIC thực tế là 0x15
.Tại sao các hệ thống khác nhau chọn các phương pháp khác nhau? Đơn giản vì không có tiêu chuẩn chung. Trường hợp bàn phím của bạn có thể nói "Enter", bàn phím cũ hơn được sử dụng để nói "Trả lại", viết tắt của từ Vận chuyển. Trong thực tế, trên một thiết bị đầu cuối nối tiếp, nhấn Return thực sự sẽ gửi ký tự CR. Nếu bạn đang viết một trình soạn thảo văn bản, sẽ rất hấp dẫn nếu chỉ sử dụng ký tự đó khi nó đến từ thiết bị đầu cuối. Có lẽ đó là lý do tại sao các máy Mac cũ chỉ sử dụng CR.
Bây giờ chúng ta có các tiêu chuẩn , có nhiều cách hơn để biểu diễn các ngắt dòng. Mặc dù cực kỳ hiếm trong tự nhiên, Unicode có các ký tự mới như:
U+2028 LINE SEPARATOR
U+2029 PARAGRAPH SEPARATOR
Ngay cả trước khi Unicode xuất hiện, các lập trình viên muốn có những cách đơn giản để biểu diễn một số mã điều khiển hữu ích nhất mà không phải lo lắng về bộ ký tự cơ bản. C có một số chuỗi thoát để biểu diễn mã kiểm soát:
\a
(để cảnh báo) rung chuông teletype hoặc làm cho thiết bị đầu cuối phát ra tiếng bíp\f
(đối với nguồn cấp dữ liệu mẫu) di chuyển đến đầu trang tiếp theo\t
(đối với tab) di chuyển đầu in sang vị trí tab ngang tiếp theo(Danh sách này là không đầy đủ có chủ ý.)
Ánh xạ này xảy ra vào thời gian biên dịch - trình biên dịch nhìn thấy \a
và đặt bất kỳ giá trị ma thuật nào được sử dụng để rung chuông.
Lưu ý rằng hầu hết các bản ghi nhớ này có mối tương quan trực tiếp với mã kiểm soát ASCII. Ví dụ, \a
sẽ ánh xạ tới 0x07 BEL
. Một trình biên dịch có thể được viết cho một hệ thống sử dụng một cái gì đó không phải ASCII cho bộ ký tự máy chủ (ví dụ: EBCDIC). Hầu hết các mã điều khiển có khả năng ghi nhớ cụ thể có thể được ánh xạ thành mã kiểm soát trong các bộ ký tự khác.
Huzzah! Tính di động!
Vâng, gần như vậy. Trong C, tôi có thể viết printf("\aHello, World!");
những tiếng chuông (hoặc tiếng bíp) và phát ra một thông báo. Nhưng nếu tôi muốn sau đó in một cái gì đó trên dòng tiếp theo, tôi vẫn cần biết nền tảng máy chủ yêu cầu gì để chuyển sang dòng đầu ra tiếp theo. CR CR? LF? NL? Thứ gì khác? Quá nhiều cho tính di động.
C có hai chế độ cho I / O: nhị phân và văn bản. Trong chế độ nhị phân, bất kỳ dữ liệu nào được gửi đều được truyền đi. Nhưng trong chế độ văn bản, có một bản dịch thời gian thực chuyển đổi một ký tự đặc biệt thành bất cứ thứ gì nền tảng máy chủ cần cho một dòng mới (và ngược lại).
Tuyệt, vậy nhân vật đặc biệt là gì?
Chà, điều đó cũng phụ thuộc vào việc triển khai, nhưng có một cách độc lập với việc triển khai để chỉ định nó : \n
. Nó thường được gọi là "nhân vật dòng mới".
Đây là một điểm tinh tế nhưng quan trọng: \n
được ánh xạ tại thời điểm biên dịch thành giá trị ký tự do xác định thực hiện , sau đó (ở chế độ văn bản) sẽ được ánh xạ lại vào thời gian chạy tới ký tự thực (hoặc chuỗi ký tự) được yêu cầu bởi nền tảng bên dưới để di chuyển đến dòng tiếp theo.
\n
khác với tất cả các nghĩa đen gạch chéo khác vì có hai ánh xạ liên quan. Ánh xạ hai bước này tạo ra \n
sự khác biệt đáng kể so với chẵn \r
, chỉ đơn giản là ánh xạ thời gian biên dịch sang CR (hoặc mã điều khiển tương tự nhất trong bất kỳ bộ ký tự cơ bản nào).
Điều này làm tăng nhiều lập trình viên C và C ++. Nếu bạn đã bỏ phiếu 100 trong số họ, ít nhất 99 sẽ cho bạn biết điều đó \n
có nghĩa là nguồn cấp dữ liệu. Điều này không hoàn toàn đúng. Hầu hết (có lẽ là tất cả) các triển khai C và C ++ sử dụng LF làm giá trị trung gian kỳ diệu cho \n
, nhưng đó là một chi tiết triển khai. Việc trình biên dịch sử dụng một giá trị khác là khả thi. Trên thực tế, nếu bộ ký tự máy chủ không phải là siêu ký tự của ASCII (ví dụ: nếu là EBCDIC), thì \n
gần như chắc chắn sẽ không phải là LF.
Vì vậy, trong C và C ++:
\r
nghĩa đen là một sự trở lại xe ngựa.\n
là một giá trị ma thuật được dịch (ở chế độ văn bản) tại thời điểm chạy đến / từ ngữ nghĩa dòng mới của nền tảng máy chủ.\r\n
hầu như luôn luôn là một lỗi di động. Trong chế độ văn bản, điều này được dịch sang CR theo sau là chuỗi dòng mới của nền tảng - có thể không phải là mục đích. Trong chế độ nhị phân, điều này được dịch sang CR theo sau là một số giá trị ma thuật có thể không phải là LF - có thể không phải là mục đích.\x0A
là cách dễ mang theo nhất để chỉ ra ASCII LF, nhưng bạn chỉ muốn làm điều đó ở chế độ nhị phân. Hầu hết các cài đặt chế độ văn bản sẽ đối xử như thế \n
.\r\n
thực sự là cách duy nhất tôi có thể phân chia các dòng thành các thành phần danh sách riêng biệt. Nó khiến tôi tự hỏi liệu đây có phải là một tạo phẩm HTML kỳ lạ hay không, hay nó có liên quan đến cách Python ăn chuỗi từ request
đối tượng của tôi không .
"\ n" => Dòng mới hoặc Linefeed (ngữ nghĩa)
Các hệ thống dựa trên Unix chỉ sử dụng "\ n" để kết thúc một dòng văn bản.
\r
được sử dụng để trỏ đến điểm bắt đầu của một dòng và có thể thay thế văn bản từ đó, ví dụ:
main()
{
printf("\nab");
printf("\bsi");
printf("\rha");
}
Sản xuất đầu ra này:
hai
\n
là cho dòng mới.
Nói tóm lại, \ r có giá trị ASCII 13 (CR) và \ n có giá trị ASCII 10 (LF). Mac sử dụng CR làm dấu phân cách dòng (ít nhất, nó đã làm trước đây, tôi không chắc chắn cho các máy Mac hiện đại), * nix sử dụng LF và Windows sử dụng cả hai (CRLF).
\ r là Vận chuyển trở lại; \ n là Dòng mới (Nguồn cấp dữ liệu) ... tùy thuộc vào hệ điều hành cho từng phương tiện. Đọc bài viết này để biết thêm về sự khác biệt giữa '\ n' và '\ r \ n' ... trong C.
\ r được sử dụng để vận chuyển trở lại. (Giá trị ASCII là 13) \ n được sử dụng cho dòng mới. (Giá trị ASCII là 10)
'\n'
.