Na oko, wydają się całkiem niezłe?
Mam parę zastrzeżeń, ale kluczowe pętle na oko wydają się być napisane poprawnie.
Pierdoła: skąd te przerwy co linię? Zakładam że to jakiś artefakt przy kopiowaniu na tą stronę, a nie w Twoim kodzie, bo dziwnie to wygląda.
Nie zrobiłaś też "dodaj kilka przykładów prezentujących możliwości i działanie powyższych funkcji".
int remove_by_val(node_t *head, int val) {
if (num < 1 || head == NULL) {
To się nie kompiluje, nie ma zmiennej 'num'.
if (num == 1) {
return remove_first(&head);
Nie wiem co mówił nauczyciel, ale zazwyczaj w programowaniu indeksuje się od zera - czyli argument num==0 (a nie 1) rozumiałbym jako usunięcie pierwszego elementu.
No i ogólnie obie funkcje błędnie się zachowają jeśli będą usuwały pierwszy element - zastanów się, dlaczego funkcja remove_first bierze wskaźnik na wskaźnik zamiast "pojedynczego" wskaźnika i czy może podobnie nie powinno być też w Twoich funkcjach.
TBH najbardziej mnie niepokoi ta nie kompilująca się zmienna 'num', bo to sugeruje że nie próbowałaś kompilować i testować tego kodu. Tak było? Zdecydowanie sugeruję testować kod na bieżąco, a nie na ślepo oddawać zadanie i mieć nadzieję że działa ;)