Чи можна написати узагальнену функцію зворотного рядка, яка працює для всіх локалізацій та типів рядків?


16

Я тільки дивився презентацію Джона Скіта (з Тоні Поні) від Dev-Days.

Хоча "записувати функцію зворотного рядка" є інтерв'ю 101 кодування - я не впевнений, що насправді можливо записати загальну функцію зворотного рядка, звичайно не ту, яка працює у всіх локалізаціях та всіх типах рядків.

Крім визначення того, чи є вхідна рядок ascii, UTF8, UTF16 (фіксованою та змінною довжиною) тощо.
Існує код "застосувати акцент до наступного символу" (U + 0301), який підкреслив Джон. Потім з’являються лігатури, які можуть бути, а можуть і не відображатися, або кодуватися як подвійні символи.

Здається, що "зворотний рядок" насправді є однією з найскладніших завдань інформатики!


Ні, спробуй зупинити щось на крок у скруті, але простіше пояснити людям.
Король JB

Будучи несуб'єктивним, технічним питанням, я б ризикнув сказати, що це краще підходить для StackOverflow (будь ласка, не перекладайте його там, хоча воно буде автоматизовано, якщо достатньо людей проголосує, щоб закрити його тут).
Péter Török

1
Залежить від мови програмування. Наприклад, у Ruby це так просто, як "stressed".reverse: p
Marcelo

Велике філософське питання. FWIW, StringBuilder Java отримує сурогати право, але не комбайнери
kdgregory

2
"Поверніть цю рядок на місці за допомогою Java" - це хороший трюковий питання. :)
Скотт C Вілсон

Відповіді:


5

Так. Якщо ми отримаємо рядок, ми можемо напевно перевернути кожен символ.

Як зазначає Джон, проблема полягає в тому, чи має зміна сенс і чи відповідає він мовним та культурним правилам, символам та кодуванню. Вода стає каламутнішою, чим глибше ви йдете.

Якщо ви робите будь-який тип маніпуляцій з рядками в C #, використовуйте культуру Інваріант під час запису та читання, таким чином ви можете сміливо ними маніпулювати. В іншому випадку підготуйтеся до відмови турецької служби підтримки.

ToUpper () виглядає так невинно, але це епічна невдача, яка чекає цього.


2
Інше питання - для чого хтось коли-небудь використовує зворотний рядок (крім інтерв'ю Q)? Мені це колись було потрібно для маніпуляції буфером низького рівня в портах вводу / виводу - і навіть тоді майже ніколи фактично з рядками
Мартін Беккет,

@Martin - Погодився. Можливо, для програми з англійської мови знайти палітроми? Я не думаю, що я використовував це, крім вирішення питання вікторини.
Джон Рейнор

@Martin правда. Я думаю, що це робиться лише іронічно. :)
Скотт C Вілсон

2

Взагалі, коли це питання задається, він передбачає, що US-ASCII. Сенс не в тому, щоб перевірити знання людини про Unicode (хоча це було б цікавим подальшим продовженням), а не для того, щоб зрозуміти, чи розуміють вони, як працюють покажчики. Дивовижна кількість людей не може виконати подібну арифметику вказівника.


2
"Як би це не вдалося з Unicode?" - це гарне подальше запитання
Мартін Беккет,

Добре, але, можливо, дещо вдосконалено - адже "перевернути цей рядок на місці" - питання інтерв'ю початкового рівня. Напевно, ви б не попросили досвідченого людини чогось такого простого, якщо, можливо, вони не були дуже сором’язливими, і ви намагалися зігріти їх.
Скотт C Вілсон

1

Як запитання про інтерв'ю, його зазвичай задають лише про технічні біти здійснення заміни 8-бітних елементів на місці, щоб змінити їх порядок (незалежно від того, які символи вони можуть насправді представляти).

У той же час, особливо якщо ви берете інтерв'ю щодо відносно старшої людини, ви можете, принаймні, сподіватися почути деякі питання щодо специфікації та точної форми вводу. Навіть якщо ви повернете їх до простого випадку просто обмінюватися 8-бітовими елементами, знаючи, чи вони думають ширше, ніж це може бути цінним.

Якщо вам доводиться мати справу з широким спектром входів, вам просто потрібно думати з точки зору "стека", трохи схожого на мережевий стек. Ви повинні будувати своє програмне забезпечення в декількох шарах, кожен з яких застосовує досить специфічний набір перетворень у певному порядку. Це дозволяє вам тримати кожну частину трансформації досить простою, щоб ви могли тримати її під контролем, і мати обґрунтований шанс зробити так, щоб вона відповідала її вимогам.

Я окреслю одну можливість, яку я вважаю принаймні дещо реальною. Я перший, хто визнає, що можуть бути й інші, хто має кращі ідеї. Принаймні, це здається трохи схожим на грубу силу інженерії, мало реальної елегантності.

Зазвичай ви хочете почати з перетворення будь-якого іншого представлення в UCS-4 (він же UTF-32). Для цього ви, як правило , вважаєте за краще покладатися на дані користувача, ніж намагаєтесь розібратися в цьому самостійно. У деяких випадках ви можете бути впевнені, що певна послідовність октетів не дотримується правил певної схеми кодування, але ви можете рідко (якщо взагалі) бути впевненими, що вона дотримується певної схеми кодування.

Наступний крок не є обов'язковим. Ви можете нормалізувати вхід до однієї з чотирьох форм нормалізації Unicode. У цьому випадку ви, мабуть, захочете застосувати перетворення "NFKC": декомпозиція сумісності з подальшим канонічним складом. Це (де можливо) перетворить комбінуючі діакритичні форми (наприклад, U + 301, про які згадував Джон), в єдині кодові точки (наприклад, "A" з "U + 301" буде перетворено на "латинську столицю А з гострою" , U + 00C1).

Потім ви проходите через усі символи від початку до кінця, розбиваючи рядок на фактичні символи - і якщо є (все-таки) комбінування діакритичних знаків, зберігаючи їх із зміненими ними символами. Результатом цього буде, як правило, індекс фактичних символів у рядку, таких як положення та довжина кожного.

Ви повертаєте порядок цих повних символів, як правило, використовуючи індекс, створений на попередньому кроці.

Потім ви (знову ж, необов'язково) застосовуєте інший процес нормалізації Unicode, такий як NFD (канонічне розкладання). Це поверне вищезгадану "латинську A з гострим" назад у дві кодові точки - "латинську столицю А" та "поєднання гострого". Якщо вхід відбулося містити U + 00C1 , щоб почати с, однак, було б також перетворити , що в двох точках коду , а також.

Потім ви кодуєте послідовність кодових точок UCS-4 в потрібне кодування (UTF-8, UTF-16 тощо)

Зауважте, що кроки нормалізації Unicode можуть / змінять кількість точок коду, необхідних для зберігання рядка, тому, якщо ви включите їх, ви більше не зможете планувати розміщення результативного рядка в оригінальному сховищі. Очевидно, що отримані кодові точки можуть також не відповідати безпосередньо вхідним кодовим точкам.


Я не натрапив на U + 301 ще до того, як Джон підніс це. Я не можу зрозуміти, навіщо це потрібно в унікоді з гліфами для всіх наголошених символів - я думаю, це зворотна сумісність
Мартін Бекетт

@Martin: Насправді існує досить велика кількість діакритичних засобів (весь діапазон від U + 0300 до U + 036F, хоча від U + 0363 до U + 036F в кращому випадку застарілий). Попередньо складені символи надаються для деяких найпоширеніших можливостей та поєднують діакритику для всього іншого, що потрібно.
Джері Коффін

Занадто багато додаткового зберігання, нормалізації та перетворення. Просто повторіть символи та відмініть порядок складових кодових одиниць на місці. Потім поверніть порядок всіх кодових одиниць на місці.
Дедуплікатор
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.