2012-12-29 16 views
10

Próbowałem zrozumieć zarówno z nich, ale nie mogę znaleźć żadnych różnic z wyjątkiem strcoll()this referencyjna mówi, żeJaka jest różnica między strcmp() i strcoll()?

porównuje dwa ciągi NUL według aktualnej lokalizacji zgodnie z definicją kategorii LC_COLLATE.

Po drugie myśli i wiem, że zadaję kolejne pytanie do szczegółowej odpowiedzi, co to dokładnie jest to ustawienie regionalne, zarówno dla C i C++?

+10

Sieć [przykład tutaj] (http://en.cppreference.com/w/cpp/string/byte/strcoll) wydaje mi się całkiem jasne. – Rapptz

+0

@Rapptz ... Ups ... powinienem widzieć ten link .... przed opublikowaniem ... – Recker

+0

hrnec przed chrt :) +1 – davak

Odpowiedz

25

strcmp() pobiera bajty ciągu jeden po drugim i porównuje je tak, jak wszystkie bajty.

strcoll() pobiera bajty, przekształca je za pomocą ustawień narodowych, a następnie porównuje wynik. Transformacja zmienia kolejność w zależności od języka. Po francusku akcentowane litery pojawiają się po nieakcentowanych. Tak é jest po e. Jednak é jest przed f. strcoll() robi to dobrze. strcmp() Nie tak dobrze.

Jednak w wielu przypadkach wystarczy strcmp(), ponieważ nie trzeba wyświetlać wyników uporządkowanych w języku (locale) w użyciu. Na przykład, jeśli potrzebujesz tylko szybkiego dostępu do dużej liczby danych zindeksowanych przez ciąg znaków, użyjesz mapy zindeksowanej przez ten ciąg. Prawdopodobnie jest całkowicie bezużyteczny do sortowania korzystających strcoll() który jest na ogół bardzo powolna (w porównaniu do strcmp() przynajmniej.)

Szczegółowe informacje na temat znaków można również sprawdzić na stronie internetowej Unicode.

Jeśli chodzi o ustawienia regionalne, jest to język. Domyślnie jest ustawiony na "C" (mniej więcej, brak ustawień regionalnych). Po wybraniu lokalizacji ustawienia regionalne są odpowiednio ustawione. Możesz również ustawić zmienną środowiskową LC_LOCALE. W rzeczywistości istnieje wiele takich zmiennych. Ale generalnie używasz predefiniowanych funkcji, które automatycznie uwzględniają te zmienne i robią to, co trzeba. (format daty/czasu, liczby formatów/miary, compute upper/lower case, itd.)

+1

+1 Próbki porównania postaci w tej odpowiedzi są bardzo ładnie przedstawione, szczególnie "Jednakże, is jest przed f." przykład. Podobnie, notatki dotyczące używania 'strcmp()' do wewnętrznego zarządzania sortowaniem względem wyświetlania są równie dobrze zrobione. Jest kilka odpowiedzi, które są zwięzłe i mówią głośno, i chciałbym móc głosować na nie więcej niż jeden raz. To jedna z nich. – WhozCraig

2

Z jakiegoś powodu we wszystkich loci unikodowych testowałem, w kilku różnych wersjach glibc, strcoll() zwraca zero dla dowolnych dwóch hiraganas. To łamie sortowania uniq i wszystko, co w jakiś sposób współdziała z kolejnością łańcuchów.

$ echo -e -n 'い \ n ろ \ n は \ n に \ n ほ \ n へ \ n と \ n' | sortuj uniq

który jest po prostu uszkodzony nie do naprawienia. Ludzie z różnych stron świata mogą mieć różne pomysły na to, czy "い" powinno być umieszczone przed lub po "ろ", ale nikt rozsądny nie uznałby ich za takiego samego.

I nie, ustawiania locale do japońskiego jednego nie ma znaczenia:

$ LC_ALL = ja_JP.utf8 LANG = ja_JP.utf8 LC_COLLATE = ja_JP.utf8 echo -e -n 'い \ n ろ \ n は \ n に \ n ほ \ n へ \ n と \ n' | sortuj uniq

Była dyskusja w jakiejś oficjalnej liście mailingowej, ale wiecie co, to było w 2002 roku i nigdy nie została ustalona, ​​ponieważ ludzie nie obchodzi: https://www.mail-archive.com/[email protected]/msg02658.html

To bug stało nas w jeden dzień i na końcu naszym jedynym wyjściem było ustawienie locale sortowania na "C" i poleganie na ładnych właściwościach kodowania utf-8. To straszne doświadczenie, ponieważ nie powinno się pracować w locale "C" podczas przetwarzania danych w całości po japońsku.

Tak więc ze względu na zdrowie psychiczne NIE używaj bezpośrednio strcoll. Bezpieczniejsze wariant może być:

int safe_strcoll(const char *a, const char *b) 
{ 
    int ret = strcoll(a, b); 
    if (ret != 0) return ret; 
    return strcmp(a, b); 
} 

tylko w przypadku strcoll() decyduje się wkręcić cię ...

+1

Miałem szczęście, że dostrzegłem problem. Twoja zmiana środowiska dotyczy tylko 'echo'. Powinieneś również zastosować zmianę języka do "sort" i "uniq"; najprostszy jest po prostu "eksportuj LANG". Działa doskonale z następującymi opcjami: '(eksportuj LANG = ja_JP.UTF-8; echo -e -n 'い \ n ろ \ n | \ n に \ n ほ \ n へ \ n と \ n' | sort | uniq)' . – qsantos

+1

Dziękuję za wskazanie tego. Z wyjątkiem tego, że podczas pierwszego eksperymentu korzystałem z eksportu LANG = ja_JP.UTF-8. Próbowałem ponownie na wielu komputerach i nadal mogę odtworzyć problem w niektórych, ale nie wszystkich z nich. Sądzę, że muszę trochę dalej kopać, co spowodowało różnicę. Wersja glibc nie jest jedyną zmienną, którą muszę kontrolować ... –

Powiązane problemy