Tüm yerelleştirmeler ve dize türleri için çalışan genelleştirilmiş bir dize ters işlevi yazmak mümkün müdür?


16

Sadece Dev-Days'in Jon Skeet (Tony the Pony ile) sunumunu izliyordum .

Her ne kadar "bir dize ters fonksiyonu yazmak" kodlama röportaj 101 olsa da - Aslında tüm yerelleştirme ve tüm dize türlerinde çalışan bir değil, genel bir dize ters fonksiyonu yazmak mümkün olduğundan emin değilim.

Giriş dizesinin ascii, UTF8, UTF16 (sabit ve değişken uzunluk) vb. Olup olmadığını tespit etmenin yanı sıra,
Jon'un vurguladığı 'sonraki karaktere vurgu uygula' (U + 0301) kodu vardır. Sonra görüntülenebilen veya gösterilemeyen veya çift karakter olarak kodlanan bitişik harfler vardır.

"Bir dize ters" aslında zor bilgisayar bilimi görevlerinden biri gibi görünüyor!


Hayır, zorlanmayı zorlaştıran ama insanlara açıklamak daha basit bir şey için durma problemini deneyin.
JB King

Hedefsiz, teknik bir soru olarak, bunun StackOverflow'a daha uygun olacağını söylemek için girişimde bulunacağım (lütfen orada tekrar yayınlamayın, yeterince insan burada kapatmak için oy verirse otomatikleştirilecektir).
Péter Török

1
Programlama diline bağlıdır. Örneğin Ruby'de bu kadar kolay "stressed".reverse: p
Marcelo

Büyük felsefi soru. FWIW, Java'nın StringBuilder vekilleri doğru alır ancak birleştiricileri değil
kdgregory

2
"Java kullanarak yerinde bu dizeyi tersine çevirmek" iyi bir hiledir. :)
Scott C Wilson

Yanıtlar:


5

Evet. Bir dize alırsak, her karakteri kesinlikle tersine çevirebiliriz.

Jon'un belirttiği sorun, tersinmenin mantıklı olması ve dil ve kültürel kurallara, karakterlere ve kodlamaya uymasıdır. Su gittikçe derinleşiyor.

C # 'da herhangi bir dize manipülasyonu yapıyorsanız, yazma ve okuma sırasında Değişmez kültürünü kullanın, bu şekilde onları güvenle işleyebilirsiniz. Aksi takdirde, Türk destek çağrısı başarısızlığına hazırlanın.

ToUpper () çok masum görünüyor, ama gerçekleşmesini bekleyen destansı bir başarısızlık.


2
Diğer soru şudur: Herkes dize tersini ne için kullanır (görüşme Q dışında)? I / O portlarının düşük seviyeli tampon manipülasyonu için buna hiç ihtiyacım vardı - ve hatta o zamanlar neredeyse hiç dizelerle değil
Martin Beckett

@Martin - Kabul etti. Belki bir İngilizce dil programı için palidromes bulmak için? Sınav sorusunu çözmek dışında kullandığımı sanmıyorum.
Jon Raynor

@Martin true. Bence sadece ironik bir şekilde yapılıyor. :)
Scott C Wilson

2

Genel olarak, bu soru sorulduğunda US-ASCII olduğunu varsayar. Mesele, kişinin Unicode bilgisini test etmek için çok fazla değildir (bu ilginç bir takip olmasına rağmen), işaretçilerin nasıl çalıştığını anladıklarını görmek için. Şaşırtıcı sayıda insan bu tür işaretçi aritmetiği yapamaz.


2
"Bu unicode ile nasıl başarısız olur?" iyi bir soru
Martin Beckett

İyi ama belki biraz ileri - sonuçta, "bu dizeyi tersine çevirmek" bir giriş seviyesi görüşme sorusudur. Muhtemelen çok utangaç olmadıkça ve onları ısıtmaya çalışmadıkça, deneyimli bir kişiye bu kadar basit bir şey sormazsınız.
Scott C Wilson

1

Bir röportaj sorusu olarak, genellikle siparişlerini tersine çevirmek için 8 bit öğelerin yerinde takas yapmanın teknik bitleri hakkında sorulur (gerçekte hangi karakterleri temsil edebileceğinden bağımsız olarak).

Aynı zamanda, özellikle nispeten üst düzey bir kişiyle görüşüyorsanız, en azından spesifikasyon ve girdinin kesin şekli hakkında bazı sorular duymayı umabilirsiniz. Onları sadece 8 bitlik öğeleri değiştirmenin basit bir örneğine yönlendirseniz bile, bundan daha geniş anlamda düşünüp düşünmediklerini bilmek değerli olabilir.

Geniş bir girdi yelpazesi ile uğraşmak zorunda kalırsanız, bir ağ yığını gibi bir "yığın" açısından düşünmek zorundasınız. Yazılımınızı, her biri belirli bir sırada oldukça belirli bir dönüşüm kümesi uygulayan bir dizi katman halinde oluşturmanız gerekir. Bu, dönüşümün her bir bölümünü kontrol altında tutabileceğiniz kadar basit tutmanıza ve gereksinimlerini karşılaması için makul bir şansa sahip olmanıza izin verir.

En azından biraz işe yarayabilir bulduğum bir olasılığı özetleyeceğim. Yine de daha iyi fikirleri olan başkalarının olabileceğini kabul eden ilk kişi benim. En azından benim için, bu biraz gerçek zarafetle kaba kuvvet mühendisliğine benziyor.

Normalde başka bir temsili UCS-4'e (diğer adıyla UTF-32) dönüştürerek başlamak istersiniz. Bunun için, genellikle kendi başına anlamaya çalışmak yerine kullanıcıdan gelen girdilere güvenmeyi tercih edersiniz . Bazı durumlarda, emin gelmez sekizli belirli bir dizisi olabilir değil , belirli bir kodlama şemasının kurallara uyar, ancak nadiren (hiç değilse) belirli bir kodlama şemasını takip eder emin olabilirsiniz.

Bir sonraki adım isteğe bağlıdır. Girişi dört Unicode normalleştirme formundan birine normalleştirebilirsiniz. Bu durumda, muhtemelen "NFKC" dönüşümünü uygulamak istersiniz: uyumluluk ayrışımı ve ardından standart kompozisyon. Bu, (mümkünse) aksan biçimlerini birleştirerek (Jon'un bahsettiği U + 301 gibi) tek kod noktalarına (örneğin, "U + 301" olan bir "A" "akut ile Latin sermayesi A" ya dönüştürülür) , U + 00C1).

Daha sonra, dizeyi gerçek karakterlere ayırarak baştan sona tüm karakterleri dolaşırsınız ve aksan işaretlerini (hala) birleştirerek varsa, değiştirdikleri karakterlerle birlikte tutarsınız. Bunun sonucu genellikle dizgideki her birinin konumu ve uzunluğu gibi gerçek karakterlerin bir dizini olacaktır.

Bu karakterlerin sırasını, genellikle önceki adımda oluşturduğunuz dizini kullanarak tersine çevirirsiniz.

Daha sonra (isteğe bağlı olarak) NFD (kanonik ayrışma) gibi başka bir Unicode normalleştirme işlemi uygularsınız. Bu, yukarıda bahsedilen "akut ile Latin A" yı iki kod noktasına dönüştürecektir - "Latin başkenti A" ve "Akut'u birleştiren". Girişinizi ancak başlangıç için bir U + 00C1 içerdiği olduysa, o da dönüştürmek istiyorum bu iki kod noktaları içine de.

Daha sonra UCS-4 kod noktaları dizisini istenen kodlamaya (UTF-8, UTF-16, vb.)

Unicode normalleştirme adımlarının, dizeyi saklamak için gereken kod noktalarının sayısını değiştirebileceğini / değiştireceğini unutmayın; böylece bunları eklerseniz, artık orijinal depolama alanına sığacak sonuç dizesini planlayamazsınız. Açıkça, sonuçta ortaya çıkan kod noktaları doğrudan giriş kodu noktalarına karşılık gelmeyebilir.


Jon uyandırmadan önce U + 301 ile karşılaşmamıştım. Tüm vurgulu karakterler için neden glifli unicode'da gerekli olduğunu göremiyorum - geriye dönük uyumluluk olduğunu hayal ediyorum
Martin Beckett

@Martin: Aslında çok sayıda birleştirici aksan vardır (U + 0300'den U + 036F'ye kadar tüm aralık, ancak U + 0363'den U + 036F'ye kadar en iyi eskimektir). Önceden oluşturulmuş karakterler, en yaygın olasılıkların bazıları için ve diakritikleri ihtiyaç duyulan her şey için birleştirerek sağlanır.
Jerry Coffin

Çok fazla depolama, normalleştirme ve dönüşüm. Sadece karakterleri tekrarlayın ve yerinde kod birimlerinin sırasını tersine çevirin. Ardından, yerinde tüm kod birimlerinin sırasını tersine çevirin.
Tekilleştirici
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.