Wczoraj skończyłem pisać mój skrypt w języku C, który przetworzył mi plik tekstowy zawierający ponad 4,5 miliona linii i stworzył ok. 20 tys. plików wynikowych.
UPDATE: Tutaj siedzi on sobie na GitHubie: https://github.com/devsilv/devsilv-detlan
Nic skomplikowanego; ot, skrypt wyszukuje linie spełniające podany warunek i kopiuje je do poszczególnych plików wynikowych.
Czas wykonywania głównej pętli: ok. 30 sekund. Uważam to za wynik świetny, porównując z moim poprzednim skryptem, w Bashu, który zamierzał robić to samo kilka godzin (przerwałem mu w połowie). (Pamiętajcie, że na Bashu mogę nie znać się za dobrze. Żeby właściwie porównać te języki, znajdźcie benchmarki inne niż moje skrypty :P).
Nie jestem doświadczony w języku C; wyszło, że taki nieskomplikowany skrypt to nic trudnego… powiedzmy. Wydaje się działać.
Właśnie. Ktoś mógłby zapytać, czy skrypt działa poprawnie. Przeglądałeś wszystkie pliki wynikowe linijka po linijce? Skąd wiesz, że jakiś znak występujący 3 razy na krzyż w pliku wejściowym nie został pominięty, ponieważ wśród 10 użytych funkcji użyłeś akurat jednej, która nie obsługuje odpowiedniego kodowania?
Słuszne uwagi. Nie wymagam wielkiej poprawności na tym etapie, więc przygotowałem sobie prosty jednolinijkowiec w Bashu, by sprawdzić poprawność plików:
for file in ./* ; do if [[ $(grep -o "here-i-typed-the-text-to-search-for" $file | wc -l) != 1 ]] ; then echo "$file is NOT OK" ; fi ; done
Wykonawszy ten test na plikach wynikowych, nie otrzymałem żadnego wyjścia (i tego właśnie oczekiwałem). — Przy okazji, jeśli oko Cię lekko zakuło od spojrzenia na konstrukcję for file in ./*
, to ja nie wiem, w ilu wypadkach jest bezpieczna (na pewno nie we wszystkich!). Niemniej, ciekawostka, Greg mówi, że jest w porządku: http://mywiki.wooledge.org/ParsingLs#Enumerating_files_or_doing_stuff_with_files A jeśli chcesz pisać lepsze skrypty w systemach *nix, moim zdaniem warto także przeczytać ten "esej" Davida A. Wheelera (m.in. pisze o tej konstrukcji; wyszukaj w tekście in ./*
lub in *
).
W razie czego (w miarę potrzeb) przygotuję sobie coś więcej.
W związku ze skończeniem pisania mojego skryptu mam kilka spostrzeżeń.
Do kompilacji nie użyłem makefile; wystarczyła mi historia poleceń linii komend. Nie wiem, czy to źle, czy dobrze. Do poprzedniego programu w C użyłem makefile. (Nie wspominam tego miło. Ale to pewnie dlatego, że nie chciało mi się wtedy uczyć tego języka. Wystarczyło mi do szczęścia samo przypominanie sobie C od podstaw).
Pisząc w C dobrze być pewnym, którego standardu / dialektu się używa, nadto – jawnie powiedzieć to kompilatorowi. Ot, bo różnorodność ich jest. Szczególnie jak jawnie używa się więcej niż jednej flagi kompilatora.
Mam dziwne wrażenie, że alokując pamięć w funkcjach i zwracając sam wskaźnik do niej, można by zrobić to lepiej – jakoś lepiej. Przecież to podatne na błędy (=dziwne) pisać przy każdej funkcji: "Uważaj: jeśli używasz tej funkcji, nie zapomnij zwolnić pamięci". A jak inaczej zasygnalizować użytkownikowi?
A używać funkcji, które operują na już zaalokowanej pamięci? To znów dla mnie nieintuicyjne. Nie napiszę przecież (choć w skrypcie napisałem):
const char *src = "Wesoły tekst o niczym";
const char *dst = malloc(strlen(src) + 1); // pamiętać: +1 to na kończący NULL
strcpy(src, dst);
free(dst);
tylko raczej wolę:
const char *src = "Wesoły tekst o niczym";
const char *dst = strdup(src); // przed C20 dostępne w dialektach GNU
choć oczywiście w tym drugim przypadku muszę tak samo na koniec:
free(dst);
(@alagner, dziękuję jeszcze raz).
Nie żebym* chciał wymyślać koło i implementować rozwiązanie pokroju garbage collectora, ale…
* To nie jest przytyk do nikogo. Po prostu mnie samemu ciężko zapamiętać wszystkie reguły, i tutaj bym zrobił błąd interpunkcyjny, gdybym nie sprawdził.
Przydałaby się obsługa wyjątków czy czegoś… Ogólnie: przejrzysty mechanizm obsługi błędów, niezależny od "logiki biznesowej". ( :P )
Do tej pory nie zauważyłem, by w C była jedna wartość, którą można zwrócić z funkcji o każdym typie, a dzięki temu można uznać za odpowiednik wyjątku.
Są co prawda inne sposoby…
Trzeba się ich nauczyć. Może nawet czasem lepsze niż wyjątki?
Szkoda, że nie trafiłem na jakąś stronę, która listuje, a najlepiej porównuje wszystkie możliwe sposoby.
(Dla zainteresowanych moją działalnością na naszym forum).
#c #skrypt #przetwarzanie-tekstu #text-processing #bash #język-programowania #spostrzeżenia
UPDATE: Dodałem link do GitHuba.
czemu foo
? Może to pomoże https://pl.wikipedia.org/wiki/Zmienna_metasyntaktyczna
@Mirai: mnie też czasem uderza, że coś jest po prostu konwencją – nie ma tego w żadnym standardzie. Mając do czynienia z tak ustrukturyzowaną wiedzą jak specyfikacje języków programowania, chciałoby się, by wszystko było opisane.