2012-08-28 14 views
5

Rozważmy tę funkcję pisałem bardzo szybko znaleźć ostatnie wystąpienie danego char w ciąg i powrócić to pozycja w tablicy znaków, że fizycznie jest ciąg:najbardziej wydajnym sposobem znalezienia ostatnie wystąpienie char

size_t strlstchar(const char *str, const char ch) 
{ 
    char *chptr = strrchr(str, ch); 
    return chptr - str; 
} 

Po prostu napisałem to naprawdę szybko (nie skompilowałem ani nie dodałem) tylko dlatego, że mam pytania dotyczące kilku rzeczy.

Dla mnie wydaje się to najprostszym rozwiązaniem, aby dowiedzieć się, który element tablicy zawiera ostatnie wystąpienie określonego znaku, ale nie mam pojęcia, jak to działa. Zrobiłem to po dokumentacji strrchr, więc technicznie strrchr wykonuje całą pracę. Po prostu nie mogę sobie wyobrazić, że jest to najlepszy sposób (jeśli chodzi o wydajność), aby to osiągnąć, i miałam nadzieję, że ktoś mógłby dać jakiś wkład w to, co byłoby najlepszym sposobem na zrobienie tego.

Czy strrchr to skuteczny sposób na zrobienie tego? A może strrchr najlepiej zostawić do innego użytku?

+0

strrchr może zwrócić wartość NULL, co sprawia, że ​​wynik twojej funkcji jest trudny do przewidzenia, kiedy nie uda się znaleźć znaku. Zazwyczaj "-str" może być postrzegana jako liczba losowa, a następnie przekształcana na size_t, skąd będziesz wiedzieć, że nie udało ci się znaleźć znaku? – xryl669

Odpowiedz

4

Zastosowane podejście jest całkowicie w porządku - niestety operacje tablicowe są drogie. Strrchr w większości implementacji po prostu przechodzi przez ciąg zaczynając od końca, aż znajdzie pasujący znak. To jest czas O(n). Następnie wykonuje się odjęcie, które jest O(1). To nie jest takie złe.

+0

Ciekawe, i dziękuję za szybką odpowiedź, po prostu zawsze czuję się niezdecydowany, aby użyć funkcji ciągów, domyślam się, że jest to habbit lub coś, co nie jest do końca pewne, dlaczego jest wywiercony w moim mózgu, że "jeśli używasz funkcji zdefiniowanej w string.h ty "Robię to źle" –

+1

@KeithMiller to źle. Te funkcje istnieją w określonym celu. Gdyby istniał magiczny, stały sposób rozwiązywania wszystkich problemów algorytmicznych, implementatorzy libc by to wykorzystali.I zawsze pamiętaj o zdaniu, które Linus Torvalds napisał: "Każdy rozsądny człowiek wie, że K & R miał rację" :) –

+1

Ciągi są bardzo powolne w C, ze względu na ich specyficzną naturę (bycie 0x00 zakończone): strrchr() przechodzi od początku do końca string (albo przez wywołanie strlen(), aby poznać koniec ciągu, który przemierza cały ciąg, a następnie biorąc go od końca, aż znajdzie znak, albo robiąc to w prostym przejściu do końca ciągu). Gdziekolwiek znajduje się twoja postać, cały ciąg jest skanowany! – Parallelis

3

Od docs:

zwraca wskaźnik do ostatniego wystąpienia znaku w str C strun.

Więc robi dokładnie to, co chcesz. Celem jego istnienia jest to.

Czy strrchr to skuteczny sposób na zrobienie tego?

Jest prawie na pewno napisana co najmniej tak dobrze lub lepiej, niż można to zrobić samodzielnie.

Lub czy strrchr najlepiej pozostawić do innego użytku?

Nie. Napisano dokładnie w tym celu.

0

Będzie szybciej, jeśli będziesz mógł podać długość struny, a następnie po prostu pętlę do tyłu. Kiedy znajdziesz pierwsze wystąpienie postaci, od razu powróć.

Jeśli nie znasz długości, użyj strrchr.

+0

Tak właśnie myślałem, ale w jakim przypadku nie wiedziałbym, długość struny chyba że zawierał znaki NULL lub coś takiego, czy byłby w tym momencie traktowany jako ciąg znaków? A może tylko kawałek danych? A jeśli byłoby to bardziej skuteczne, dlaczego nie jest tak w standardowej bibliotece? Wydaje się to takie proste? Dlatego jestem zdezorientowany, ponieważ czasami rzeczy po prostu nie mają dla mnie sensu :( –

+0

Zwykle w C nie znasz długości struny, więc lepiej nie uwzględniać długości w strrchr. Trzeba zrobić strlen, aby uzyskać długość za każdym razem, gdy używasz strrchr.Ale jest też wiele funkcji, które zwracają długość, gdy są skuteczne jak scanf.Jeśli twój kod naprawdę musi być bardziej wydajny, możesz pętnąć do tyłu. –

Powiązane problemy