Problem znany mi doskonale. No cóż, na początek Cię pocieszę. W C++ sprawa nie wygląda łatwiej - wszystkie te streamy operujące na plikach też tak średnio współpracują z UTF-8. Lecz tak jak ja rozwiązałem ten problem w C++, tak samo da się w C.
https://pl.wikipedia.org/wiki/UTF-8
Trochę teorii. UTF-8 ma to do siebie, że zapisuje znaki z jak najmniejszą liczbą bajtów. A zostanie zapisane za pomocą jednego, Ą za pomocą dwóch, € za pomocą trzech. Czterobajtowe sekwencje też się znajdą.
Czyli to co trzeba zrobić to odkodować te 1-4 bajtowe sekwencje znaków i wpisać je do tablicy intów (int = 4 bajty) lub int*. I tak otrzymane znaki można już porównywać. W C++ ja to zapisuję do std::basic_string<unsigned int>.
W wyżej załączonym linku do wikipedii w kategorii Sposób kodowania masz ładnie opisane i pokazane na czym polega to kodowanie. Najprościej mówiąc, musisz rozpoznać na podstawie bitów, które nie są x'ami, ile bajtów przypada na znak, następnie wymazać ten bity (nie x'y). To co zostanie (czyli same x'y) poprzesuwać za pomocą << lub >> i poskładać za pomocą | (or bitowy) znak/liczbę w całość.
Zagmatwane to jest co prawda, ale programowanie to także tworzenie algorytmów. W razie wątpliwości - pytaj.