Rozwiązania. Arkusz egzaminacyjny INF.04. Czerwiec 2023
INF 04 egzamin praktyczny Rozwiązanie arkusza czerwiec 2023
Poniżej treści problemów i ich rozwiązania.Część I. Aplikacja konsolowa
Korzystając z opisu algorytmu sita Eratostenesa, przekształć pseudokod algorytmu do aplikacji konsolowej szukającej liczb pierwszych w przedziale 2..n, gdzie n = 100.
Ze zbioru liczb naturalnych z przedziału [2, n], tj. {2,3,4,... ,n} wybieramy najmniejszą, czyli 2, i wykreślamy wszystkie jej wielokrotności większe od niej samej, to jest 4, 6, 8, ... . Z pozostałych liczb wybieramy najmniejszą niewykreśloną liczbę (3) i wykreślamy wszystkie jej wielokrotności większe od niej samej: 6, 9, 12, ... . Według tej samej procedury postępujemy dla liczby 5. Następnie dla 7 aż do sprawdzenia wszystkich niewykreślonych wcześniej liczb. Wykreślanie powtarzamy do momentu, gdy liczba i, której wielokrotność wykreślamy, będzie większa niż √n.
Wskazówka:
Pseudokod
Niech A będzie tablicą wartości typu logicznego indeksowaną liczbami
całkowitymi od 2 do n (indeksy 0 i 1 nie są brane pod uwagę w czasie
działania algorytmu), początkowo wypełniona wartościami true
for i := 2, 3, 4, ..., nie więcej niż √n:
if A[i] = true:
for j := 2*i, 3*i, 4*i, ..., nie więcej niż n :
A[j] := false
Wyjście: wartości i takie, że A[i] zawiera wartość true
Założenia programu
- Program wykonywany w konsoli
- Język programowania zgodny z zainstalowanym na stanowisku egzaminacyjnym, jeden z: C++, C#, Java, Python
- Program szuka liczb w przedziale 2..100 (n = 100)
- Wypełnianie tablicy odbywa się w osobnej funkcji przyjmującej tablicę jako argument i nie zwracającej żadnej wartości
- Liczby pierwsze są wyświetlane na ekranie, rozdzielone dowolnym separatorem oraz poprzedzone znaczącym komunikatem
- Program powinien być zapisany czytelnie, z zachowaniem zasad czystego formatowania kodu, należy stosować znaczące nazwy zmiennych i funkcji
- Dokumentacja do programu wykonana zgodnie z wytycznymi z części III zadania egzaminacyjnego
Kod aplikacji przygotuj do nagrania na płytę. W podfolderze konsola powinno znaleźć się archiwum całego projektu o nazwie konsola.zip, plik z kodem źródłowym programu oraz plik wykonywalny, jeżeli istnieje.
Część II. Aplikacja desktopowa
Za pomocą środowiska programistycznego dostępnego na stanowisku egzaminacyjnym, wykonaj aplikację desktopową będącą fragmentem aplikacji do obsługi poczty. Wykorzystaj umieszczone na pulpicie materiały o nazwie materialy.zip zabezpieczone hasłem: %Twoj@Paczka
Źródło CKE
Obraz 1. Aplikacja desktopowa, zaznaczono pole radio ?List? i wybrano przycisk ?Sprawdź Cenę?
Opis wyglądu aplikacji
- Okno dialogowe o nazwie ?Nadaj Przesyłkę? i szerokości dopasowanej do kontrolek wewnątrz. W nazwie okna należy wstawić także numerem zdającego.
- Okno zawiera kontrolki rozmieszczone zgodnie z obrazem 1. Są to:
- grupa pól radio: Pocztówka, List, Paczka; pola są zgrupowane w dowolny dostępny element grupujący (np. GroupBox), w stanie początkowym zaznaczone jest pole Pocztówka
- trzy pola edycyjne poprzedzone etykietami o treści Ulica z numerem, Kod pocztowy, Miasto; zgrupowane w dowolny dostępny element grupujący
- przycisk o treści Sprawdź Cenę
- obraz w stanie początkowym wyświetlający obraz pocztowka.png
- etykieta o treści Cena:, o cechach: napis pogrubiony i czcionka widocznie większa względem pozostałych napisów
- przycisk o treści: Zatwierdź
Działanie aplikacji
- pola radio działają w grupie, jednocześnie może być wybrane tylko jedno pole
- po wybraniu przycisku Sprawdź cenę aplikacja sprawdza, które pole radio jest zaznaczone i zależnie od wyboru wyświetla odpowiedni dla pola obraz oraz cenę, odpowiednio:
- pole radio Pocztówka: obraz pocztowka.png, Cena: 1 zł
- pole radio List: obraz list.png, Cena: 1,5 zł
- pole radio Paczka: obraz paczka.png, Cena: 10 zł
- po wybraniu przycisku Zatwierdź jest walidowane pole kodu pocztowego oraz wyświetlany komunikat.
Dla uproszczenia zadania należy przyjąć, że kod składa się tylko z 5 cyfr (bez znaku '-').
- komunikat dla poprawnego kodu pocztowego: Dane przesyłki zostały wprowadzone
- komunikat, gdy jest mniej lub więcej niż 5 znaków: Nieprawidłowa liczba cyfr w kodzie pocztowym
- komunikat, gdy przynajmniej jeden znak nie jest cyfrą: Kod pocztowy powinien się składać z samych cyfr
Założenia aplikacji
- Pliki obrazów zapisane w zasobach aplikacji
- Aplikacja obsługuje dwa zdarzenia: kliknięcie dla każdego z przycisków
- Po wybraniu przycisku Zatwierdź aplikacja jedynie wyświetla komunikat. Nie jest wymagane, aby dane z okna zostały zapisane do struktury w programie.
- Aplikacja powinna być zapisana czytelnie, z zachowaniem zasad czystego formatowania kodu, należy stosować znaczące nazwy zmiennych i funkcji
Podejmij próbę kompilacji i uruchomienia aplikacji. Wykonaj zrzut ekranowy zgodnie z wytycznymi z III części zadania.
Kod aplikacji przygotuj do nagrania na płytę. W podfolderze desktop powinno znaleźć się archiwum całego projektu o nazwie desktop.zip oraz plik (lub pliki) z kodem źródłowym modyfikowanym w czasie egzaminu.
Część III. Dokumentacja utworzonych aplikacji
Wykonaj dokumentację do aplikacji utworzonych na egzaminie. W kodzie źródłowym aplikacji konsolowej utwórz nagłówek funkcji wypełniającej tablicę, według wzoru. Nagłówek powinien znaleźć się w kodzie źródłowym nad funkcją. W miejscu nawiasów <> należy podać nazwę funkcji, nazwy parametrów (lub słowo brak) oraz zwięzłe informacje (co realizuje funkcja?) ? zgodnie z listingiem 1. W miejscu autor należy podać numer zdającego
UWAGA: Dokumentację umieścić w komentarzu (wieloliniowym lub kilku jednoliniowych). Znajdujący się w listingu 1 wzór dokumentacji jest bez znaków początku i końca komentarza, gdyż te są różne dla różnych języków programowania
Listing 1. Wzór dokumentacji funkcji. Źródło CKE
Wykonaj zrzuty ekranu dokumentujące uruchomienie aplikacji utworzonych podczas egzaminu. Zrzuty powinny obejmować cały obszar ekranu z widocznym paskiem zadań. Jeżeli aplikacja uruchamia się, na zrzucie należy umieścić okno z wynikiem działania programu oraz otwarte środowisko programistyczne z projektem lub okno z kompilacją projektu. Jeżeli aplikacja nie uruchamia się z powodu błędów kompilacji, należy na zrzucie umieścić okno ze spisem błędów i widocznym otwartym środowiskiem programistycznym.
Nazwy zrzutów ekranu:
- dowolna liczba zrzutów ekranowych z aplikacji konsolowej nazwane konsola1, konsola2 itd.
- dowolna liczba zrzutów ekranowych z aplikacji desktopowej nazwane desktop1, desktop2 itd.
W edytorze tekstu pakietu biurowego utwórz plik z dokumentacją i nazwij go egzamin. Dokument powinien zawierać podpisane zrzuty ekranu, a następnie zapisane informacje:
Zrzuty ekranu i dokument umieść w folderze o nazwie dokumentacja.
Rozwiązanie części I: aplikacja konsolowa
Rozwiązanie rozpoczniemy o przygotowania dwóch zmiennych: rozmiaru dla tablicy i tablicę typu prawda/ fałsz
Wskazówka:
//rozmiar
static int n;
//tablica prawda/ fałsz
static bool[] t;
W głównej metodzie Main() odczytamy rozmiar tablicy podany z klawiatury. Przypiszemy rozmiar do tablicy i wypełnimy jej zawartość wartościami true
Wskazówka:
static void Main(string[] args)
{
Console.Write("Podaj rozmiar tablicy n=");
n=int.Parse(Console.ReadLine());
//buduj tablice o podanym rozmiarze n
//rozmiar n jest jednocześnie zakresem szukania liczb pierwszych
t = new bool[n];
//przypisz wartości true każdemu elemntowi tablicy
for (int i = 0; i < n; i++) t[i] = true;
Console.ReadKey();
}
Piszemy funkcję wykreślającą te liczby, czyli indeksy, które nie są liczbami pierwszymi. Wykreśleniem jest zmiana stanu z true na false
Wskazówka:
static void Wykreslaj(bool[] tab,int n)
{
//pierwiastkuj i zaokrąglij do całkowitej
//niewiększej niż pierwiastek z rozmiaru
int granica=(int)Math.Round(Math.Sqrt(n));
int j;
for(int i = 2; i <= granica; i++)
{
if (tab[i]==true)
for(j=2*i;j<n;j+=i)
tab[j] = false;
}
}
Podana funkcja działa zgodnie z podanym pseudokodem w treści zadania. Teraz zostaje napisani drugiej funkcji, której zadaniem jest wyświetlenie tych indeksów z podanego zakresu, które są liczbami pierwszymi. Czyli wystarczy, że sprawdzimy w tablicy elementy równe logicznej prawdzie (true).Za separator wyświetlanych liczb przyjmiemy znak przecinka i spacji (, )
Wskazówka:
static void WypiszPierwsze(bool[] tab,int n)
{
Console.WriteLine("Liczby pierwsze to:");
int i = 2;
do {
if (tab[i] == true) Console.Write(String.Format("{0}, ",i));
//lub prościej
//Console.Write(i+", ");
i++;
}
while (i < n);
}
Wywołamy obie funkcje w głównej metodzie aplikacji
Wskazówka:
static void Main(string[] args)
{
Console.Write("Podaj rozmiar tablicy n=");
n=int.Parse(Console.ReadLine());
//buduj tablice o podanym rozmiarze n
//rozmiar n jest jednocześnie zakresem szukania liczb pierwszych
t = new bool[n];
//przypisz wartości true każdemu elemntowi tablicy
for (int i = 0; i < n; i++) t[i] = true;
Wykreslaj(t,n);
//pokaz liczby pierwsze z podanego zakresu
WypiszPierwsze(t,n);
Console.ReadKey();
}
Uruchamiamy aplikację i sprawdzamy efekt działania
Pełny kod rozwiązania
Wskazówka:
using System;
namespace czerwiec_2023_problem_1_sito_eratostenesa
{
internal class Program
{
//rozmiar
static int n;
//tablica prawda/ fałsz
static bool[] t;
static void Wykreslaj(bool[] tab,int n)
{
//pierwiastkuj i zaokrąglij do całkowitej
//niewiększej niż pierwiastek z rozmiaru
int granica=(int)Math.Round(Math.Sqrt(n));
int j;
for(int i = 2; i <= granica; i++)
{
if (tab[i]==true)
for(j=2*i;j<n;j+=i)
tab[j] = false;
}
}
static void WypiszPierwsze(bool[] tab,int n)
{
Console.WriteLine("Liczby pierwsze to:");
int i = 2;
do {
if (tab[i] == true) Console.Write(String.Format("{0}, ",i));
//lub prościej
//Console.Write(i+", ");
i++;
}
while (i < n);
}
static void Main(string[] args)
{
Console.Write("Podaj rozmiar tablicy n=");
n=int.Parse(Console.ReadLine());
//buduj tablice o podanym rozmiarze n
//rozmiar n jest jednocześnie zakresem szukania liczb pierwszych
t = new bool[n];
//przypisz wartości true każdemu elemntowi tablicy
for (int i = 0; i < n; i++) t[i] = true;
Wykreslaj(t,n);
//pokaz liczby pierwsze z podanego zakresu
WypiszPierwsze(t,n);
Console.ReadKey();
}
}
}
Rozwiązanie części II: aplikacja desktopowa
Do rozwiązania pobierz załącznik z grafiką zamieszczoną w arkuszu (pobierz)
Załącznik zawiera trzy plik PNG z poniższą grafiką
Źródłow CKE
Układ komponentów
Rozwiązanie zadania rozpoczniemy od przygotowania układu kontrolek. Tekst informacyjny w kontrolkach wprowadź zgodnie z arkuszem zadań.
Przejdź do folderu projektu i skopiuj katalog wraz z załączonymi plikami graficznymi (list.png, paczka.png, pocztowka.png)
W projekcie osadź kontrolkę do przechowywania zasobów graficznych- ImageList
Odczytaj wymiary plików graficznych (wysokość i szerokość w pikselach). Wybierz i zapamiętaj największą parę.
W dołączonych zasobach wszystkie obrazy mają jednakowy rozmiar- 100x63 pikseli. Ten rozmiar podamy w kontrolce ImageList zanim dołączymy pliki graficzne do jej kolekcji.
Dołączamy grafikę do kolekcji. Wybierz zakładka Właściwości/ Images. Tak jak poniżej
Otworzy się okno dialogowe pozwalające dodać pliki z grafiką. Dodaj te trzy pliki graficzne z obrazem listu, paczki i kartki pocztowej. Zwróć uwagę na kolejność dodawania.
Pozycja na liście jest indeksem w kolekcji obrazów. Według tych indeksów w kodzie programu będziemy podmieniać zawartość kontrolki PictureBox. Zero (0) to pocztówka, jeden (1) to list, dwa (2) to paczka.
Wprowadź właściwy tekst informacyjny o roli użytych kontrolek.
Ustaw aktywność wyboru kontrolki RadioButton- pocztówka na wybraną (Checked ustaw na True)
Przy prawidłowym osadzeniu kontrolek RadioButton w obszarze kontrolki GroupBox wybór jednej z nich dezaktywuj poprzedni wybór. Tak więc odpada nam kodowanie aktywności zaznaczenia. Sprawdź to- skompiluj aplikację i poklikaj w przyciskach wyboru rodzaju przesyłki.
Przygotowujemy obsługę wyboru rodzaju przesyłki
W rozwiązaniu nie jest narzucony sposób wykorzystania rodzaju i typów zmiennych. Najłatwiej dla wyboru rodzaju przesyłki i przejrzystości kodu jest zastosowanie typu wyliczeniowego enumeratora zbioru.
Przejdź do głównego pliku kodu (Form1.cs) i wprowadź poniższy kod
Wskazówka:
public partial class Form1 : Form
{
enum PRZESYLKA {POCZTOWKA,LIST,PACZKA};
private PRZESYLKA przesylka = PRZESYLKA.POCZTOWKA;
public Form1()
{
InitializeComponent();
}
}
Kontrolkom RadioButton przypisz unikatowe indeksy. Po tych indeksach będziemy rozróżniać w jednym wspólnym zdarzeniu kliknięcia, który przycisków jest aktyny. Czyli jaką przesyłkę wybrano. W odpowiednich polach Tag wpisz: idPocztowka, idList, idPaczka. Pisownia jest ważna i nie używaj polskich znaków.
Obsługujemy zdarzenie Click kontrolek RadioButton. Przytrzymaj klawisz Shift i zaznacz kontroli RadioButton. Zwróć uwagę czy tylko te trzy kontrolki są obramowane stanem zaznaczenia.
Przejdź do zakładki Właściwości/ Zdarzenia i dwa razy szybko kliknij w obszarze metody Click()
Do metody Click wprowadzamy poniższy kod. Kod rozpoznaje (po przypisanym tagu) jaka kontrolka RadioButton została kliknięta.
Wskazówka:
private void radioButton1_Click(object sender, EventArgs e)
{
//rzutuj obiekt sender na typ RadioButton
RadioButton radioButton = (RadioButton)sender;
//wybór aktywnej opcji rodzaju przesyłki
//rozpoznaj po Tag-u kontrolki RadioButton
switch (radioButton.Tag)
{
case "idPocztowka": przesylka = PRZESYLKA.POCZTOWKA;break;
case "idList": przesylka = PRZESYLKA.LIST;break;
case "idPaczka": przesylka = PRZESYLKA.PACZKA; break;
}
}
Funkcja podmieniająca obrazek i tekst
Podmiana obrazu i tekstu odbywa się według poleceń zadania po kliknięciu w przycisk Button z napisem Sprawdź cenę. Napiszemy funkcje, która zrealizuje tę podmianę. Funkcja będzie bardzo prosta, bez żadnych parametrów i nie będzie zwracać typu.
Wskazówka:
private void ZmienObraz_i_Tekst()
{
switch (przesylka)
{
case PRZESYLKA.POCZTOWKA:
label1.Text="Cena: 1 zł";
pictureBox1.Image = imageList1.Images[0];
break;
case PRZESYLKA.LIST:
label1.Text = "Cena: 1,5 zł";
pictureBox1.Image = imageList1.Images[1];
break;
case PRZESYLKA.PACZKA:
label1.Text = "Cena: 10 zł";
pictureBox1.Image = imageList1.Images[2];
break;
default:
label1.Text = "Cena: 1 zł";
pictureBox1.Image = imageList1.Images[0];
break;
}
}
Jej działanie już możesz sprawdzić zanim zostanie obsłużone klikanie w przycisk. Do metody Form1/Load, którą zainicjujesz jak poniżej (dwa razy szybko kliknij w pustym obszarze metody Load)
Wprowadź poniższy kod
Wskazówka:
private void Form1_Load(object sender, EventArgs e)
{
ZmienObraz_i_Tekst();
}
Skompiluj i sprawdź działanie aplikacji. Aplikacja po starcie ustawi aktywność wyboru pocztówki.
Wywołanie tej funkcji ustawimy również w zdarzeniu Click() dla przycisku Sprawdź cenę. Inicjujemy metodę zdarzenia Click() dla tego przycisku
I wprowadzamy poniższy kod
Wskazówka:
private void button1_Click(object sender, EventArgs e)
{
ZmienObraz_i_Tekst();
}
Skompiluj program i sprawdź jego działanie. Po zmianie opcji wyboru kontrolek RadioButton i kliknięciu przycisku Sprawdź cenę zauważysz zmianę tekstu i obrazu.
Obsługa klawisza Zatwierdź
Obsługa klawisza Zatwierdź wykonamy w zdarzeniu Click() tej kontrolki. Napiszemy funkcję, która sprawdzi podane warunki na kod pocztowy. W wyniku sprawdzenia funkcja wyświetli odpowiedni komunikat w standardowym oknie dialogowym systemu Windows
Wskazówka:
void SprawdzKod()
{
string komunikat = "Dane przesyłki zostały wprowadzone";
//odczytaj kod
string kod = textBox2.Text;
if (kod.Length != 5)
{
komunikat = "Nieprawidłowa liczba cyfr w kodzie pocztowym";
}else
// sprawdź czy wszystkie znaki to cyfry
{
int i = 0;
do
{
char znak = kod[i];
//jeżeli jest błędny to
if (znak < '0' || znak > '9')
{
komunikat = "Kod pocztowy powinien składać się z samych cyfr";
//wyskocz bo nie ma sensu dalej sprawdzać poprawności kodu
break;
}
i++;
} while (i < kod.Length);
}
//wyświetl komunikat
MessageBox.Show(komunikat,
"Stan przesyłki",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
Po zainicjowaniu zdarzenia Click() dla przycisku zatwierdź wywołamy tę funkcję
Wskazówka:
private void button2_Click(object sender, EventArgs e)
{
SprawdzKod();
}
Skompiluj program i sprawdź efekt działania. Poniżej okno komunikatu dla kodu zawierającego znak, który nie jest cyfrą.
Sprawdźmy pozostałe możliwości wprowadzania błędnego kodu pocztowego
Pełny kod rozwiązania
Wskazówka:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace czerwiec_2023_problem_2_nadaj_przesylke
{
public partial class Form1 : Form
{
enum PRZESYLKA {POCZTOWKA,LIST,PACZKA};
private PRZESYLKA przesylka = PRZESYLKA.POCZTOWKA;
public Form1()
{
InitializeComponent();
}
private void radioButton1_Click(object sender, EventArgs e)
{
//rzutuj obiekt sender na typ RadioButton
RadioButton radioButton = (RadioButton)sender;
//wybór aktywnej opcji rodzaju przesyłki
//rozpoznaj po Tag-u kontrolki RadioButton
switch (radioButton.Tag)
{
case "idPocztowka": przesylka = PRZESYLKA.POCZTOWKA;break;
case "idList": przesylka = PRZESYLKA.LIST;break;
case "idPaczka": przesylka = PRZESYLKA.PACZKA; break;
}
}
private void ZmienObraz_i_Tekst()
{
switch (przesylka)
{
case PRZESYLKA.POCZTOWKA:
label1.Text="Cena: 1 zł";
pictureBox1.Image = imageList1.Images[0];
break;
case PRZESYLKA.LIST:
label1.Text = "Cena: 1,5 zł";
pictureBox1.Image = imageList1.Images[1];
break;
case PRZESYLKA.PACZKA:
label1.Text = "Cena: 10 zł";
pictureBox1.Image = imageList1.Images[2];
break;
default:
label1.Text = "Cena: 1 zł";
pictureBox1.Image = imageList1.Images[0];
break;
}
}
private void button1_Click(object sender, EventArgs e)
{
ZmienObraz_i_Tekst();
}
private void Form1_Load(object sender, EventArgs e)
{
ZmienObraz_i_Tekst();
}
void SprawdzKod()
{
string komunikat = "Dane przesyłki zostały wprowadzone";
//odczytaj kod
string kod = textBox2.Text;
if (kod.Length != 5)
{
komunikat = "Nieprawidłowa liczba cyfr w kodzie pocztowym";
}else
// sprawdź czy wszystkie znaki to cyfry
{
int i = 0;
do
{
char znak = kod[i];
//jeżeli jest błędny to
if (znak < '0' || znak > '9')
{
komunikat = "Kod pocztowy powinien składać się z samych cyfr";
//wyskocz bo nie ma sensu dalej sprawdzać poprawności kodu
break;
}
i++;
} while (i < kod.Length);
}
//wyświetl komunikat
MessageBox.Show(komunikat,
"Stan przesyłki",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
private void button2_Click(object sender, EventArgs e)
{
SprawdzKod();
}
}
}