Formatowanie i wcięcia
Warunek zaliczenia
Umiem, gdy w kodzie pisanym na czas nie ma ani jednej linii z dwiema instrukcjami, a wcięcia zagnieżdżeń są konsekwentne.
Warto wiedzieć
Kryteria R.1.1 i R.1.2. Wystarczy, że cecha jest zastosowana w 90 procentach przypadków.
Co dokładnie sprawdza egzaminator
Cytaty dosłowne z zasad oceniania. Brzmienie sprawdzone w 24 plikach zasad z sesji 2021 do 2026.
Kod źródłowy zapisano w sposób czytelny: instrukcje w osobnych liniach, stosowane spacje pomiędzy operatorami, konsekwentnie stosowana wybrana konwencja dla nawiasów klamrowych instrukcji blokowej
zasady oceniania INF.04-02-23.06-SG, arkusz kalkulacyjny CKEOd sesji Zima 2024 pierwsze słowa brzmią „Kod źródłowy zapisany” zamiast „zapisano”. Reszta zdania jest identyczna we wszystkich 24 przejrzanych plikach zasad.
Kod zapisano z wcięciami dla zagłębień bloków
zasady oceniania INF.04-02-23.06-SG, arkusz kalkulacyjny CKEW arkuszach od 2024 roku zamiast „zagłębień” stoi „zagnieżdżeń”. Znaczenie to samo, kryterium to samo.
Trzy uwagi ogólne, które zmieniają czytanie
- Tolerancja
- Wystarczy, że sprawdzaną cechę zastosowano dla większości (90%) przypadków w kodzie
- Zakres
- Kryteria dotyczą wyłącznie samodzielnie napisanego kodu
- Zastępstwo
- kryteria należy odnieść do aplikacji konsolowej, jeżeli ta nie istnieje, kryteria 1.1 do 1.6 zastosować do aplikacji mobilnej
Po co to jest
To są dwa kryteria z dwudziestu arkuszy na dwadzieścia. Nie ma sesji, w której by ich nie było, i nie ma wariantu, który by je pomijał.
Razem z pozostałymi kryteriami rezultatu 1 dają one od 20 do 21 procent punktów arkusza, a nie wymagają ani jednej linijki algorytmu. Dostaje się je za sposób zapisu, nie za to, co program liczy. Przy progu 75 procent, gdzie brakujące dwa kryteria potrafią zdecydować o wyniku, są to najtańsze punkty na całym egzaminie.
Katalog strat punktowych wymienia ten błąd jako E.5: kilka instrukcji w linii, brak spacji przy operatorach, mieszane klamry, brak wcięć. Wszystkie cztery naraz kosztują dwa kryteria, a każde z nich da się usunąć jednym skrótem klawiszowym w środowisku, które i tak stoi na stanowisku egzaminacyjnym.
Pojęcie
Słowo „czytelnie” brzmi jak sprawa gustu i to jest pierwsza rzecz, którą trzeba tu odrzucić. Kryterium R.1.1 nie mówi „ładnie”. Wymienia trzy sprawdzalne cechy, a R.1.2 dokłada czwartą. Egzaminator nie ocenia wrażenia, tylko zaznacza T albo N przy każdej z nich.
Pierwsza: instrukcje w osobnych liniach. Jedna instrukcja, jedna linia. Dwa przypisania rozdzielone średnikiem w tej samej linii łamią kryterium, nawet gdy są krótkie i oczywiste.
Druga: spacje pomiędzy operatorami. Chodzi o operatory dwuargumentowe: przypisanie, porównanie, działania arytmetyczne, w C++ także strumienie. Zapis a=b+c łamie kryterium, zapis a = b + c je spełnia.
Trzecia: konsekwentnie stosowana wybrana konwencja dla nawiasów klamrowych. To jest miejsce, w którym najwięcej osób się myli, bo czyta je jako „poprawna konwencja”. Nic takiego w zdaniu nie stoi. CKE nie ma zdania na temat tego, czy klamra otwierająca ma stać w tej samej linii co nagłówek, czy w następnej. Kryterium sprawdza, czy wybrałeś jedną i trzymałeś się jej. Plik, w którym połowa funkcji ma klamrę w tej samej linii, a połowa w następnej, łamie kryterium, choć każda z tych form osobno jest poprawna.
Czwarta, z kryterium R.1.2: wcięcia dla zagnieżdżeń bloków. Każdy blok wchodzący do środka innego bloku przesuwa się o jeden poziom w prawo. Ciało funkcji o jeden, ciało pętli wewnątrz funkcji o dwa, ciało warunku wewnątrz pętli o trzy. To nie jest ozdoba: głębokość wcięcia jest jedyną informacją o tym, gdzie kończy się blok, kiedy czyta się kod, a nie kompiluje.
Do tego dochodzi tolerancja, o której trzeba wiedzieć, żeby nie wpaść w panikę przy oddawaniu: uwaga ogólna do rezultatu 1 mówi, że wystarczy zastosować cechę w większości, czyli w 90 procentach przypadków. Jedna zapomniana spacja w stulinijkowym pliku nie kosztuje kryterium. Cała funkcja napisana bez wcięć już tak, bo to zwykle więcej niż jedna dziesiąta kodu.
Zobacz to dwa razy
Ten sam program, ten sam algorytm, te same nazwy zmiennych. Różni się wyłącznie zapis. Zadanie pochodzi z arkusza INF.04-01-23.01-SG, czyli z tego, na którym stoi pierwszy kamień planu.
#include <iostream>using namespace std; int nwd(int pierwsza,int druga){while(druga!=0){int reszta=pierwsza%druga;pierwsza=druga;druga=reszta;}return pierwsza;} int main(){int pierwsza,druga;cout<<"Podaj pierwsza liczbe: ";cin>>pierwsza;cout<<"Podaj druga liczbe: ";cin>>druga;cout<<"NWD wynosi: "<<nwd(pierwsza,druga)<<endl;return 0;}- ! linia 4Klamra otwierająca stoi w tej samej linii co nagłówek funkcji, a w linii 12 ta sama klamra stoi w linii osobnej. Dwie konwencje w jednym pliku łamią kryterium R.1.1, choć każda z nich osobno jest poprawna.
- ! linia 5Brak spacji wokół operatora różności i po słowie kluczowym pętli.
- ! linia 6Trzy instrukcje w jednej linii. Kryterium żąda instrukcji w osobnych liniach.
- ! linia 8Cała funkcja jest bez wcięć: ciało funkcji, ciało pętli i instrukcja zwrotu stoją na tym samym poziomie. To kryterium R.1.2.
- ! linia 14Brak spacji wokół operatorów strumienia oraz dwie instrukcje w jednej linii.
#include <iostream> using namespace std; int nwd(int pierwsza, int druga){ while (druga != 0) { int reszta = pierwsza % druga; pierwsza = druga; druga = reszta; } return pierwsza;} int main(){ int pierwsza; int druga; cout << "Podaj pierwsza liczbe: "; cin >> pierwsza; cout << "Podaj druga liczbe: "; cin >> druga; cout << "NWD wynosi: " << nwd(pierwsza, druga) << endl; return 0;}- + linia 6Klamra otwierająca w osobnej linii. Ta sama forma wraca w liniach 8 i 18, więc konwencja jest w całym pliku jedna.
- + linia 7Spacja po słowie kluczowym i wokół operatora różności.
- + linia 9Dwa poziomy wcięcia: pierwszy za wejście do ciała funkcji, drugi za wejście do ciała pętli.
- + linia 10Jedna instrukcja w linii. Trzy przypisania, które w złym zapisie stały w linii 6, stoją tu w trzech osobnych liniach.
Mostek: zdanie kryterium wobec linii kodu
| Fragment kryterium | Gdzie się łamie | Gdzie jest spełniony |
|---|---|---|
| instrukcje w osobnych liniach | linia 6 (trzy instrukcje) i linia 14 (dwie instrukcje) | linie 9 do 11 oraz 22 i 23, po jednej instrukcji na linię |
| stosowane spacje pomiędzy operatorami | druga!=0 w linii 5 oraz cout<<"..." w linii 14 | druga != 0 w linii 7 oraz cout << "..." w linii 22 |
| konsekwentnie stosowana wybrana konwencja dla nawiasów klamrowych | linia 4 ma klamrę w tej samej linii, linia 12 w osobnej | linie 6, 8 i 18 mają klamrę w osobnej linii, bez wyjątku |
| wcięcia dla zagłębień bloków (kryterium R.1.2) | linie 5 do 9 stoją przy lewej krawędzi, mimo dwóch poziomów zagnieżdżenia | linia 9 ma dwa poziomy wcięcia, bo siedzi w pętli wewnątrz funkcji |
Granice
Kod, którego nie napisałeś, się nie liczy. Uwaga ogólna mówi wprost: kryteria dotyczą wyłącznie samodzielnie napisanego kodu. Pliki wygenerowane przez środowisko, czyli szkielet projektu w Android Studio, pliki pośrednie Qt czy zawartość katalogu z zależnościami, nie są oceniane ani na plus, ani na minus. Nie ma sensu ich formatować i nie ma się czego bać, gdy wyglądają inaczej niż Twój kod.
Brak aplikacji konsolowej nie ratuje przed tymi kryteriami. Uwaga ogólna przenosi kryteria od 1.1 do 1.6 na aplikację mobilną, desktopową albo webową, zależnie od tego, co jest w arkuszu. Nie da się ich uniknąć, rezygnując z części pierwszej: przeniosą się na tę część, którą oddasz.
To nie jest kryterium o nazwach. Nazewnictwo funkcji i zmiennych to R.1.3 i R.1.4, czyli osobny dział A2. Kod z fatalnymi nazwami, ale wzorowo sformatowany, dostaje T przy R.1.1 i R.1.2, i odwrotnie. Przy nauce warto te dwie sprawy trzymać osobno, bo osobno są punktowane.
To nie jest kryterium o działaniu programu. R.1.1 i R.1.2 sprawdza się w pliku źródłowym. Program, który się nie kompiluje, nadal może dostać oba te punkty, a program działający bez zarzutu może ich nie dostać.
Nie-przykład, który mylnie wygląda na ten sam problem: kod poprawnie sformatowany, ale pozawijany przez edytor przy wąskim oknie. Zawinięcie widoku nie jest wcięciem w pliku i nie ma wpływu na kryterium. Znaczenie ma to, co jest w pliku, a nie to, jak wygląda na ekranie.
W czterech językach
Arkusz dopuszcza C++, C#, Javę i Pythona. Kryterium jest jedno, ale w każdym z nich wygląda trochę inaczej.
- C++
- Operatory strumieni też są operatorami:
cout << x, niecout<<x. Uważaj nai++w pętli, tam spacje nie są potrzebne, bo to operator jednoargumentowy. - C#
- Visual Studio formatuje dokument skrótem Ctrl+K, Ctrl+D i domyślnie stawia klamrę w osobnej linii. Nie zmieniaj tego ustawienia w trakcie pracy, bo połowa pliku zostanie w starej konwencji.
- Java
- Android Studio i IntelliJ formatują skrótem Ctrl+Alt+L, domyślnie klamra w tej samej linii. Ta konwencja jest równie dobra, o ile jest jedyna w pliku.
- Python
- Wcięcie jest tu częścią składni, więc kryterium R.1.2 spełnia się samo. Zostają dwa pozostałe żądania: jedna instrukcja w linii, czyli bez średników sklejających, oraz spacje wokół operatorów. Klamr nie ma, więc trzeci fragment kryterium nie ma zastosowania.
Procedura
Cztery żądania kryterium przekładają się na cztery przebiegi po kodzie plus jedno domknięcie skrótem klawiszowym. Kolejność ma znaczenie: konwencję klamr wybiera się przed napisaniem pierwszej linii, a formatowanie automatyczne uruchamia jako ostatnie.
- 1
Zanim napiszesz pierwszą linię, wybierz konwencję klamr i zapisz ją sobie na kartce.
to konwencja, bo kryterium sprawdza konsekwencję, a nie wybór, więc obie formy są dozwolone; decyzja podjęta w połowie pliku zostawia za sobą drugą połowę w starej formie.
- 2
Pisz jedną instrukcję w linii, także wtedy, gdy gałąź warunku ma tylko jedną instrukcję.
wolno tak, bo zapis
if (x) return;mieści dwie instrukcje w jednej linii, a kryterium nie robi wyjątku dla instrukcji krótkich. - 3
Wstaw spacje po obu stronach każdego operatora dwuargumentowego.
wolno tak, bo kryterium wymienia spacje między operatorami wprost, a operatory jednoargumentowe, jak
i++, nie są nimi objęte. - 4
Każde wejście do bloku przesuwa kod o jeden poziom wcięcia w prawo.
wolno tak, bo wcięcie jest jedyną informacją o zagnieżdżeniu przy czytaniu pliku, a egzaminator czyta plik, nie uruchamia go.
- 5
Zanim zrobisz zrzut ekranu, uruchom formatowanie automatyczne na każdym pliku źródłowym.
wolno tak, bo to jedyne miejsce w całym egzaminie, gdzie jeden skrót naprawia oba kryteria w całym pliku naraz; skróty to Ctrl+K, Ctrl+D w Visual Studio, Ctrl+Alt+L w IntelliJ i Android Studio, Shift+Alt+F w Visual Studio Code.
Co widzę, więc co robię
| Widzę | Robię |
|---|---|
| W linii stoi więcej niż jeden średnik kończący instrukcję | Rozbij na tyle linii, ile jest instrukcji |
| Operator dwuargumentowy dotyka z obu stron argumentów | Wstaw spację z każdej strony |
| Klamra otwierająca raz stoi w tej samej linii, raz w następnej | Wybierz jedną formę i popraw wszystkie pozostałe wystąpienia |
| Blok wewnątrz bloku zaczyna się na tej samej kolumnie | Przesuń go o jeden poziom w prawo |
| Kod jest gotowy i za chwilę robisz zrzut | Uruchom formatowanie automatyczne całego pliku |
Ostatni wiersz stoi na końcu, a nie na początku, bo formatowanie automatyczne uruchomione w połowie pracy zostanie zepsute przez kod dopisany po nim.
Ćwiczenia
Trzy stopnie, w każdym mniej pomocy niż w poprzednim. Odpowiedź jest schowana celowo: zajrzyj do niej po własnej próbie, nie przed.
1Przykład z omówieniem
Przeczytaj fragment i wypisz, które z czterech żądań kryterium są tu złamane. Uwaga: nie wszystkie.
Fragment sita Eratostenesa z arkusza INF.04-01-23.06-SG void sito(bool tablica[],int rozmiar){for(int i=2;i*i<rozmiar;i++){if(tablica[i]){for(int j=i*i;j<rozmiar;j+=i)tablica[j]=false;}}}Pokaż odpowiedź
Złamane są trzy z czterech: brak spacji przy operatorach, więcej niż jedna instrukcja w linii trzeciej oraz brak wcięć dla dwóch poziomów zagnieżdżenia. Konwencja klamr jest tu akurat konsekwentna, bo każda klamra otwierająca stoi w tej samej linii co nagłówek, więc tego fragmentu kryterium ten kod nie łamie.
Pokaż rozwiązanie w kodzie
Ten sam fragment po poprawieniu void sito(bool tablica[], int rozmiar) { for (int i = 2; i * i < rozmiar; i++) { if (tablica[i]) { for (int j = i * i; j < rozmiar; j += i) { tablica[j] = false; } } }}- + linia 1Konwencja klamry w tej samej linii została zachowana, bo w oryginale już taka była. Zmiana jej przy okazji poprawek byłaby niepotrzebnym ryzykiem.
2Znajdź resztę sam
Ten fragment ma poprawne wcięcia i jedną konwencję klamr. Znajdź dwa pozostałe uchybienia i podaj numery linii.
int main(){ int liczba; cout << "Podaj liczbe: "; cin >> liczba; if (liczba>0) { cout << "Liczba dodatnia" << endl; } return 0;}Wskazówka: Przejdź plik dwa razy, raz szukając średników w środku linii, raz szukając znaków operatorów bez spacji obok.
Pokaż odpowiedź
Linia 4: dwie instrukcje w jednej linii, wypisanie monitu i wczytanie. Linia 6: brak spacji wokół operatora większości, powinno być
liczba > 0. Wcięcia i konwencja klamr są tu poprawne, więc poza tymi dwoma miejscami nie ma czego zmieniać.3Zadanie
Przepisz poniższy fragment tak, żeby spełniał oba kryteria. Nie zmieniaj ani jednej nazwy i ani jednej instrukcji: zmieniasz wyłącznie zapis. Potem porównaj z rozwiązaniem i postaw sobie T albo N przy R.1.1 i R.1.2.
Sortowanie bąbelkowe z arkusza INF.04-02-23.06-SG, zapisane w jednej linii void sortuj(int tablica[],int rozmiar){for(int i=0;i<rozmiar-1;i++){for(int j=0;j<rozmiar-1-i;j++){if(tablica[j]>tablica[j+1]){int tmp=tablica[j];tablica[j]=tablica[j+1];tablica[j+1]=tmp;}}}}Pokaż odpowiedź
Powinno wyjść dziewięć albo dziesięć linii, w zależności od wybranej konwencji klamr, z czterema poziomami wcięcia w najgłębszym miejscu. Jeżeli Twoja wersja różni się od poniższej wyłącznie położeniem klamr, jest równie poprawna.
Pokaż rozwiązanie w kodzie
Jedno z poprawnych rozwiązań, konwencja klamry w tej samej linii void sortuj(int tablica[], int rozmiar) { for (int i = 0; i < rozmiar - 1; i++) { for (int j = 0; j < rozmiar - 1 - i; j++) { if (tablica[j] > tablica[j + 1]) { int tmp = tablica[j]; tablica[j] = tablica[j + 1]; tablica[j + 1] = tmp; } } }}- + linia 5Cztery poziomy wcięcia: funkcja, pętla zewnętrzna, pętla wewnętrzna, warunek. Zmienna `tmp` jest tu dozwolona, bo zasady oceniania wymieniają ją jako wyjątek przy kryterium nazewnictwa.
Laboratorium
Popraw poniższy fragment tak, żeby przeszedł oba kryteria, i sprawdź go przyciskiem. Możesz też wyczyścić pole i wkleić własny kod ze środowiska, w którym ćwiczysz: sprawdzarka pracuje na dowolnym kodzie w C++, C#, Javie albo Pythonie.
Sprawdzenie rusza dopiero po naciśnięciu przycisku, nie przy pisaniu. Na egzaminie takiego narzędzia nie będzie, więc próba ma być najpierw własna.
Edytor wczytuje się w przeglądarce.
Pułapka
„Formatowanie to kwestia gustu, a gustu nikt nie punktuje. Dopóki mój program się kompiluje i daje poprawny wynik, egzaminator nie ma podstawy, żeby postawić mi N przy zapisie kodu.”
Ta reguła jest błędna i kosztuje dwa kryteria w każdym arkuszu, czyli od 5 do 7 procent punktów.
Poniższy kod kompiluje się bez ostrzeżeń i sortuje tablicę poprawnie. Dostaje N przy R.1.1 i N przy R.1.2, bo ma wszystkie instrukcje w jednej linii, zero spacji przy operatorach i zero wcięć. Działanie programu nie jest tu żadnym argumentem.
void sortuj(int t[],int n){for(int i=0;i<n-1;i++)for(int j=0;j<n-1-i;j++)if(t[j]>t[j+1]){int p=t[j];t[j]=t[j+1];t[j+1]=p;}}Reguła poprawna
R.1.1 i R.1.2 są kryteriami inspekcyjnymi: egzaminator sprawdza je w pliku źródłowym, patrząc na zapis, a nie na wynik uruchomienia. Działa to w obie strony i druga strona jest dobrą wiadomością. Program, który się nie kompiluje, może dostać oba te punkty w całości, o ile kod jest zapisany czytelnie.
Sprawdź się
Odpowiadaj na głos albo na kartce, zanim odsłonisz. Odtworzenie z pamięci jest tym, co buduje trwałość, a przeczytanie odpowiedzi tylko przypomina, że się ją widziało.
- 1
Wymień cztery cechy zapisu, które sprawdzają kryteria R.1.1 i R.1.2.
z pamięci
Pokaż odpowiedź
Instrukcje w osobnych liniach, spacje pomiędzy operatorami, jedna konsekwentnie stosowana konwencja nawiasów klamrowych oraz wcięcia dla zagnieżdżeń bloków.
- 2
Ile odstępstw od reguły wolno mieć w kodzie, zanim kryterium przepadnie?
z pamięci
Pokaż odpowiedź
Uwaga ogólna do rezultatu 1 mówi, że wystarczy zastosować cechę w większości, czyli w 90 procentach przypadków. Pojedyncze odstępstwa się pomija, ale cała funkcja napisana inaczej niż reszta pliku zwykle przekracza tę granicę.
- 3
W Twoim pliku połowa funkcji ma klamrę otwierającą w tej samej linii co nagłówek, a połowa w linii następnej. Które kryterium jest zagrożone i co robisz?
wykonanie i uzasadnienie
Pokaż odpowiedź
Zagrożone jest R.1.1, fragment o konsekwentnie stosowanej wybranej konwencji. Obie formy są dopuszczalne, więc nie ma znaczenia, którą wybierzesz; wybierasz jedną i poprawiasz wszystkie wystąpienia drugiej, najszybciej formatowaniem automatycznym całego pliku.
- 4
Zabrakło Ci czasu i nie napisałeś aplikacji konsolowej. Czy kryteria R.1.1 i R.1.2 przepadają razem z nią?
wykonanie i uzasadnienie
Pokaż odpowiedź
Nie. Uwaga ogólna przenosi kryteria od 1.1 do 1.6 na aplikację mobilną, desktopową albo webową, zależnie od arkusza. Zapis kodu, który oddajesz, będzie oceniony tak samo, więc formatowanie części drugiej ma dokładnie tę samą wartość punktową.
- 5
Twój program nie kompiluje się z powodu jednego błędu, którego nie umiesz znaleźć. Czy warto jeszcze formatować kod przed oddaniem?
wykonanie i uzasadnienie
Pokaż odpowiedź
Tak, i to jest wtedy najlepiej opłacalna rzecz, jaką możesz zrobić. R.1.1 i R.1.2 sprawdza się w pliku źródłowym, niezależnie od tego, czy kod się uruchamia, więc te dwa kryteria są nadal do wzięcia w całości.
Kiedy umiem
Warunki obserwowalne. Dopóki któryś nie jest spełniony, dział zostaje w toku, nawet jeżeli materiał wydaje się oczywisty.
- Na kodzie pisanym na czas, trzy razy pod rząd, przeglądam plik i nie znajduję ani jednej linii z dwiema instrukcjami.
- Wymieniam z pamięci cztery cechy zapisu z kryteriów R.1.1 i R.1.2, bez zaglądania do tej lekcji.
- Znam skrót formatowania w środowisku, w którym będę zdawał, i używam go bez szukania w menu.
- Po co najmniej siedmiu dniach od tej lekcji, przy zamkniętym materiale, poprawiam podany fragment kodu i moja poprawka nie pomija żadnej z czterech cech.
- Po próbie arkusza stawiam sobie T przy R.1.1 i R.1.2 oraz wskazuję w kodzie konkretną linię, która to uzasadnia.
Źródła
- Zasady oceniania CKE do arkuszy INF.04, sesje 2021 do 2026, 24 pliki; brzmienie kryteriów R.1.1 i R.1.2 sprawdzone w każdym z nich
- Uwagi ogólne do rezultatu 1: tolerancja 90 procent, zakres samodzielnie napisanego kodu, przeniesienie kryteriów przy braku aplikacji konsolowej
- Katalog strat punktowych E.5 z pliku wiedzy 01, sekcja 10
- Treści zadań z arkuszy INF.04-01-23.01-SG, INF.04-01-23.06-SG i INF.04-02-23.06-SG