Có thể viết một hàm đảo ngược chuỗi tổng quát hoạt động cho tất cả các kiểu cục bộ và kiểu chuỗi không?


16

Tôi chỉ xem bài thuyết trình của Jon Skeet (với Tony the Pony) từ Dev-Days.

Mặc dù "viết hàm đảo ngược chuỗi" là mã phỏng vấn 101 - Tôi không chắc rằng thực sự có thể viết hàm đảo ngược chuỗi chung, chắc chắn không phải là hàm hoạt động trong tất cả các kiểu địa phương và tất cả các kiểu chuỗi.

Ngoài việc phát hiện nếu chuỗi đầu vào là ascii, UTF8, UTF16 (chiều dài cố định và biến đổi), v.v.,
còn có 'dấu nhấn áp dụng cho mã ký tự tiếp theo' (U + 0301) mà Jon đã tô sáng. Sau đó, có các chữ số có thể hoặc không thể được hiển thị hoặc được mã hóa thành hai ký tự.

Có vẻ như "đảo ngược một chuỗi" thực sự là một trong những nhiệm vụ khoa học máy tính khó hơn!


Không, hãy thử vấn đề tạm dừng cho một điều gì đó một bước khó khăn nhưng đơn giản hơn để giải thích với mọi người.
JB King

Là một câu hỏi kỹ thuật, không có tính từ chối, tôi muốn nói rằng điều này sẽ phù hợp hơn với StackOverflow (xin đừng đăng lại nó ở đó, mặc dù vậy, nó sẽ được tự động hóa nếu có đủ người bỏ phiếu để đóng nó ở đây).
Péter Török

1
Phụ thuộc vào ngôn ngữ lập trình. Ví dụ: trong Ruby, nó dễ như "stressed".reverse: p
Marcelo

Câu hỏi triết học lớn. FWIW, StringBuilder của Java được thay thế ngay nhưng không phải là người kết hợp
kdgregory

2
"Đảo ngược chuỗi này tại chỗ bằng cách sử dụng Java" là một câu hỏi mẹo hay. :)
Scott C Wilson

Câu trả lời:


5

Đúng. Nếu chúng ta nhận được một chuỗi, chúng ta hoàn toàn có thể đảo ngược từng ký tự.

Vấn đề như Jon chỉ ra là sự đảo ngược có ý nghĩa hay không và nó có phù hợp với các quy tắc ngôn ngữ và văn hóa, nhân vật và mã hóa. Nước càng đục càng sâu.

Nếu bạn đang thực hiện bất kỳ loại thao tác chuỗi nào trong C #, hãy sử dụng văn hóa Bất biến khi viết và đọc, theo cách đó bạn có thể thao tác chúng một cách an toàn. Nếu không, chuẩn bị cho thất bại cuộc gọi hỗ trợ Thổ Nhĩ Kỳ.

ToUpper () trông rất ngây thơ, nhưng đó là một thất bại tuyệt vời đang chờ xảy ra.


2
Câu hỏi còn lại là - bất cứ ai cũng từng sử dụng chuỗi đảo ngược để làm gì (ngoài Q phỏng vấn)? Tôi chỉ cần nó để thao tác bộ đệm ở mức thấp của các cổng I / O - và thậm chí gần như không bao giờ thực sự có dây
Martin Beckett

@Martin - Đồng ý. Có lẽ cho một chương trình ngôn ngữ tiếng Anh để tìm palidromes? Tôi không nghĩ rằng tôi đã sử dụng nó ngoài việc giải một câu hỏi đố.
Jon Raynor

@Martin đúng. Tôi nghĩ rằng nó chỉ được thực hiện trớ trêu. :)
Scott C Wilson

2

Nói chung, khi câu hỏi này được hỏi, nó giả sử US-ASCII. Vấn đề không phải là quá nhiều để kiểm tra kiến ​​thức về Unicode của người đó (mặc dù đây sẽ là một cách tiếp theo thú vị), để xem họ có hiểu cách con trỏ hoạt động không. Một số người đáng ngạc nhiên không thể làm loại số học con trỏ này.


2
"Làm thế nào điều này sẽ thất bại với unicode?" là một câu hỏi tiếp theo hay
Martin Beckett

Tốt nhưng có lẽ hơi tiên tiến - xét cho cùng, "đảo ngược chuỗi này tại chỗ" là một câu hỏi phỏng vấn cấp nhập cảnh. Bạn có thể sẽ không hỏi một người dày dạn điều gì đó đơn giản như vậy, trừ khi có lẽ họ rất ngại ngùng và bạn đang cố gắng làm ấm họ.
Scott C Wilson

1

Như một câu hỏi phỏng vấn, người ta thường chỉ hỏi về các bit kỹ thuật khi thực hiện hoán đổi tại chỗ các vật phẩm 8 bit để đảo ngược thứ tự của chúng (bất kể các ký tự đó có thể đại diện cho những ký tự nào).

Đồng thời, đặc biệt nếu bạn đang phỏng vấn một người tương đối cao cấp, ít nhất bạn có thể hy vọng được nghe một số câu hỏi về đặc điểm kỹ thuật và hình thức chính xác của đầu vào. Ngay cả khi bạn hướng chúng trở lại trường hợp đơn giản chỉ cần hoán đổi các mục 8 bit, việc biết liệu chúng có nghĩ theo nghĩa rộng hơn có thể có giá trị hay không.

Nếu bạn phải đối phó với một loạt các đầu vào, bạn chỉ cần nghĩ về "ngăn xếp", giống như một ngăn xếp mạng. Bạn phải xây dựng phần mềm của mình theo một số lớp, mỗi lớp áp dụng một bộ biến đổi khá cụ thể theo một thứ tự cụ thể. Điều này cho phép bạn giữ cho mỗi phần của phép biến đổi đủ đơn giản để bạn có thể kiểm soát nó và có cơ hội hợp lý để làm cho nó đáp ứng các yêu cầu của nó.

Tôi sẽ phác thảo một khả năng mà tôi đã tìm thấy ít nhất là khả thi. Tôi là người đầu tiên thừa nhận rằng có thể có những người khác có ý tưởng tốt hơn. Ít nhất với tôi, điều này có vẻ hơi giống với kỹ thuật vũ phu, với rất ít sự thanh lịch thực sự.

Bạn thường muốn bắt đầu bằng cách chuyển đổi bất kỳ đại diện nào khác sang UCS-4 (còn gọi là UTF-32). Đối với điều này, bạn thường thích dựa vào đầu vào từ người dùng hơn là cố gắng tự mình tìm ra. Trong một số trường hợp, bạn có thể chắc chắn một chuỗi các octet cụ thể không tuân theo các quy tắc của sơ đồ mã hóa cụ thể, nhưng bạn hiếm khi (nếu có) chắc chắn rằng nó tuân theo một sơ đồ mã hóa cụ thể.

Bước tiếp theo là tùy chọn. Bạn có thể chuẩn hóa đầu vào thành một trong bốn biểu mẫu chuẩn hóa Unicode. Trong trường hợp này, có lẽ bạn muốn áp dụng phép chuyển đổi "NFKC": phân rã tương thích theo sau là thành phần chính tắc. Điều này sẽ (nếu có thể) chuyển đổi kết hợp các hình thức dấu phụ (như U + 301 mà Jon đã đề cập) thành các điểm mã đơn (ví dụ: "A" với "U + 301" sẽ được chuyển đổi thành "vốn A Latin với cấp tính" , U + 00C1).

Sau đó, bạn đi qua tất cả các ký tự từ đầu đến cuối, ngắt chuỗi thành các ký tự thực tế - và nếu có (vẫn) kết hợp các dấu phụ, giữ chúng với các ký tự mà chúng sửa đổi. Kết quả của điều này thường sẽ là một chỉ mục của các ký tự thực trong chuỗi, chẳng hạn như vị trí và độ dài của mỗi ký tự.

Bạn đảo ngược thứ tự của các ký tự hoàn chỉnh đó, thường bằng cách sử dụng chỉ mục bạn đã tạo ở bước trước.

Sau đó, bạn (một lần nữa, tùy chọn) áp dụng một quy trình chuẩn hóa Unicode khác, chẳng hạn như NFD (phân tách chính tắc). Điều này sẽ biến "Latin A với cấp tính" đã nói ở trên thành hai điểm mã - "vốn A Latin" và "Acute kết hợp". Tuy nhiên, nếu đầu vào của bạn có chứa U + 00C1 để bắt đầu, thì nó cũng sẽ chuyển đổi thành hai điểm mã.

Sau đó, bạn mã hóa chuỗi các điểm mã UCS-4 thành mã hóa mong muốn (UTF-8, UTF-16, v.v.)

Lưu ý rằng các bước chuẩn hóa Unicode có thể / sẽ thay đổi số lượng điểm mã cần thiết để lưu trữ chuỗi, vì vậy nếu bạn bao gồm các điểm đó, bạn không còn có thể lập kế hoạch cho chuỗi kết quả phù hợp với bộ lưu trữ ban đầu. Rõ ràng là đủ, các điểm mã kết quả có thể không tương ứng trực tiếp với các điểm mã đầu vào.


Tôi đã không bắt gặp U + 301 trước khi Jon đưa nó lên. Tôi không thể hiểu tại sao cần có unicode với glyphs cho tất cả các ký tự có dấu - Tôi tưởng tượng đó là khả năng tương thích ngược
Martin Beckett

@Martin: Thực sự có một số lượng lớn kết hợp các dấu phụ (toàn bộ phạm vi từ U + 0300 đến U + 036F, mặc dù từ U + 0363 đến U + 036F đều lỗi thời). Các ký tự được phân tách được cung cấp cho một số khả năng phổ biến nhất và kết hợp các dấu phụ cho bất cứ điều gì khác cần thiết.
Jerry Coffin

Quá nhiều lưu trữ thêm, bình thường hóa và chuyển đổi. Chỉ cần lặp lại các ký tự và đảo ngược thứ tự của các đơn vị mã cấu thành tại chỗ. Sau đó đảo ngược thứ tự của tất cả các đơn vị mã tại chỗ.
Ded
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.