Rozwiązania. Arkusz egzaminacyjny INF.04. Styczeń 2023
INF 04 egzamin praktyczny Rozwiązanie arkusza styczeń 2023Część 1. Aplikacja konsolowa
Za pomocą narzędzi do tworzenia aplikacji konsolowych zaimplementuj algorytm Euklidesa do szukania największego wspólnego dzielnika z dwóch liczb NWD(a, b). Algorytm przedstawiono na schemacie.
Źródło CKE
Założenia aplikacji:
- Obiektowy język programowania zgodny z zainstalowanym na stanowisku egzaminacyjnym: C++ lub C#, lub Java, lub Python
- Implementacja algorytmu w pełni zgodna z przedstawionym na schemacie algorytmem
- Liczby a i b należą do zbioru liczb całkowitych dodatnich (odpowiedni typ lub kontrola poprawności wpisanej liczby)
- Szukanie NWD zaimplementowane w funkcji o dwóch argumentach i zwracanej wartości największego wspólnego dzielnika. Funkcja nie może zawierać operacji wejścia - wyjścia
- Program główny testuje działanie funkcji i zawiera operacje wejścia - wyjścia
- Program powinien być zapisany czytelnie, z zachowaniem zasad czystego formatowania kodu, należy stosować nazwy zmiennych zgodne z nazwami zastosowanymi na schemacie blokowym, pozostałe nazwy muszą być znaczące
- Do kodu należy dołączyć dokumentację, która została opisana w części III zadania egzaminacyjnego.
Kod aplikacji przygotuj do nagrania na płytę. W folderze konsola powinno znaleźć się archiwum całego projektu o nazwie konsola.zip, plik z kodem źródłowym programu oraz plik uruchomieniowy, jeżeli istnieje.
Część 2. Aplikacja desktopowa
Za pomocą dostępnego na stanowisku egzaminacyjnym środowiska programistycznego wykonaj aplikację desktopową do wprowadzania danych pracownika z możliwością generowania hasła.
Źródło CKE
Na obrazie 1 przedstawiono ideę aplikacji desktopowej. W zależności od użytego środowiska programistycznego wygląd może nieznacznie się różnić.
Opis wyglądu aplikacji
- Okno o nazwie ?Dodaj pracownika?. W nazwie okna należy wstawić także numer zdającego
- Kontrolki rozmieszczone zgodnie z obrazem 1
- Kontrolki w grupie Dane Pracownika:
- pole edycyjne poprzedzone etykietą o treści Imię
- pole edycyjne poprzedzone etykietą o treści Nazwisko
- lista rozwijalna podpisana Stanowisko z elementami: Kierownik, Starszy programista, Młodszy programista, Tester
- Kontrolki w grupie Generowanie hasła:
- pole edycyjne poprzedzone etykietą o treści Ile znaków?
- trzy pola wyboru podpisane: Małe i wielkie litery, Cyfry, Znaki specjalne. Pierwsze pole jest domyślnie zaznaczone
- przycisk o treści Generuj hasło
- Na dole okna znajduje się przycisk Zatwierdź, jest on wyraźnie dłuższy niż przycisk do generowania hasła
- Okno ma tło koloru LightSteelBlue (#B0C4DE)
- Przyciski mają tło koloru SteelBlue (#4682B4) i biały kolor czcionki
Działanie aplikacji po wybraniu przycisku Generuj hasło:
- Generowane jest hasło o liczbie znaków określonej w polu edycyjnym
- Poszczególne znaki hasła są wybierane losowo z zestawu małych liter
- Jeżeli zaznaczono checkbox Małe i wielkie litery, jeden ze znaków jest losowany z zestawu wielkich liter
- Jeżeli zaznaczono checkbox Cyfry, jeden ze znaków hasła jest losowany z zestawu cyfr
- Jeżeli zaznaczono checkbox Znaki specjalne, jeden ze znaków hasła jest losowany z zestawu znaków specjalnych
- Dla uproszczenia zadania można przyjąć zawsze określony znak (np. pierwszy), który jest losowany z cyfr. Podobnie należy postąpić ze znakami specjalnymi (np. drugi znak)
- Hasło jest wypisywane jako komunikat zgodnie z obrazem 2 po wybraniu przycisku Generuj hasło
- Za zestaw liter przyjmuje się wszystkie litery z klawiatury małe i wielkie alfabetu łacińskiego
- Za zestaw cyfr przyjmuje się kolejne cyfry od 0 do 9
- Za zestaw znaków specjalnych przyjmuje się znaki !@#$%^&*()_+-=
- Hasło oraz zestawy znaków są przechowywane w zmiennych typu napisowego
Działanie aplikacji po wybraniu przycisku Zatwierdź:
- Wyświetlany jest komunikat z wypełnionymi danymi pracownika oraz wygenerowanym wcześniej hasłem, zgodnie z obrazem 3
UWAGA: dla uproszczenia aplikacji nie trzeba sprawdzać czy pole edycyjne jest wypełnione i czy liczba znaków w haśle jest wystarczająca dla wstawienia małych, wielkich liter, liczb i znaków specjalnych
Aplikacja powinna być zapisana czytelnie, z zasadami czystego formatowania kodu, należy stosować znaczące nazwy zmiennych i funkcji.
Podejmij próbę kompilacji i uruchomienia aplikacji. Informacje dotyczące dokumentacji i zrzutu ekranowego umieszczono w części III zadania. Kod aplikacji przygotuj do nagrania na płytę. W folderze desktopowa powinno znaleźć się archiwum całego projektu o nazwie desktopowa.zip, pliki źródłowe, które były modyfikowane (interfejs użytkownika i logika aplikacji) oraz plik uruchomieniowy, jeżeli to możliwe.
Część III. Dokumentacja utworzonych aplikacji
Wykonaj dokumentację do aplikacji utworzonych na egzaminie. W kodzie źródłowym aplikacji konsolowej utwórz nagłówek funkcji wyznaczającej NWD, według wzoru. Nagłówek powinien znaleźć się nad definicją funkcji. W miejscu nawiasów <> należy podać odpowiednie opisy. 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
Źródło CKE
Wykonaj zrzuty ekranu dokumentujące uruchomienie aplikacji utworzonych podczas egzaminu. Zrzuty powinny obejmować cały obszar ekranu monitora 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 terminala 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. Wykonać należy co najmniej tyle zrzutów, ile interakcji podejmuje aplikacja (np. stan początkowy, po wypisaniu hasła, po wyświetleniu danych itd.) Wymagane zrzuty ekranu:
- Aplikacja konsolowa zrzuty nazwane: konsola1, konsola2, ...
- Aplikacja desktopowa zrzuty nazwane: desktop1, desktop2, ...
W edytorze tekstu pakietu biurowego utwórz plik z dokumentacją i nazwij go egzamin. Dokument powinien zawierać podpisane zrzuty ekranu oraz zapisane informacje:
- Nazwę systemu operacyjnego, na którym pracował zdający,
- Nazwy środowisk programistycznych, z których zdający korzystał na egzaminie,
- Nazwy języków programowania,
- Opcjonalnie komentarz do wykonanej pracy.
Zrzuty ekranu i dokument umieść w podfolderze dokumentacja.
Rozwiązanie części I: aplikacja konsolowa
Z podanych warunków zadania wynika, że mamy do czynienia z bardzo prostym problemem. Przedstawiony schemat algorytmu pozwala w bardzo szybko zaimplementować funkcję zgodną z wymaganiami przygotowanymi przez Centralną Komisję Egzaminacyjną. Przygotowanie rozwiązani rozpoczniemy od wybrania w kompilatorze Visual Studio modułu kompilacji dla Aplikacja konsoli (.NET Framework)
Definiujemy zmienne
Przed implementacją funkcji w kodzie programu definiujemy dwie zmienne x i y typu całkowitego, które będą podane i odczytane z klawiatury. Dodatkowo w kodzie programu głównej funkcji implementujemy teksty informujące użytkownika co ma robić oraz dodajemy linijkę kodu, która wstrzyma zakończenie działania aplikacji.
Wskazówka:
using System;
namespace styczen_2023_problem_1_NWD_Euklides
{
internal class Program
{
static int x,y;
static void Main(string[] args)
{
Console.WriteLine("Witaj w CzD! Program obliczający NWD");
Console.Write("Podaj a=");
x=int.Parse(Console.ReadLine());
Console.Write("Podaj b=");
y = int.Parse(Console.ReadLine());
Console.ReadKey();
}
}
}
Implementujemy funkcję obliczająca NWD
Warunki podane w arkuszu egzaminacyjnym podają, ze funkcja ma posiadać dwa argumenty typu całkowitego oraz zwracać wynik typu całkowitego, który jest największym wspólnym dzielnikiem. Poniżej bardzo prosty kod działający zgodnie z podanym schematem blokowym algorytmu NWD.
Wskazówka:
static int NWD(int a, int b)
{
while (a !=b)
if (a >b)a-= b;
else b-=a;
return a;
}
Wywołanie funkcji NWD
Teraz zostaje nam wywołać funkcję w głównej metodzie aplikacji. Zauważ, ze wynik działania funkcji jest podany jako parametr łańcucha formatującego. Oczywiście można w inny sposób wyświetlić wynik działania programu, ale ten sposób jest najkrótszy
Wskazówka:
static void Main(string[] args)
{
Console.WriteLine("Witaj w CzD! Program obliczający NWD");
Console.Write("Podaj a=");
x=int.Parse(Console.ReadLine());
Console.Write("Podaj b=");
y = int.Parse(Console.ReadLine());
Console.WriteLine(String.Format("NWD {0} i {1} to {2}",x,y, NWD(x,y)));
Console.ReadKey();
}
Po skompilowaniu aplikacji wynik działania dla wartości 123 i 45 jest NWD=3
Pełny kod rozwiązania
Poniżej przedstawiam pełny kod rozwiązania
Wskazówka:
using System;
namespace styczen_2023_problem_1_NWD_Euklides
{
internal class Program
{
static int x,y;
static int NWD(int a, int b)
{
while (a !=b)
if (a >b)a-= b;
else b-=a;
return a;
}
static void Main(string[] args)
{
Console.WriteLine("Witaj w CzD! Program obliczający NWD");
Console.Write("Podaj a=");
x=int.Parse(Console.ReadLine());
Console.Write("Podaj b=");
y = int.Parse(Console.ReadLine());
Console.WriteLine(String.Format("NWD {0} i {1} to {2}",x,y, NWD(x,y)));
Console.ReadKey();
}
}
}
Rozwiązanie części II: aplikacja desktopowa
Rozwiązanie rozpoczniemy od przygotowani projektu głównego okna formatki aplikacji
Układ kontrolek
Ułóż kontrolki zgodnie z propozycją przedstawioną w arkuszu egzaminacyjnym.
Tekst w kontrolkach wprowadź zgodnie z arkuszem zadań. Zawartość kontrolki ComboBox wypełnimy przez dodanie w kolekcji podanych nazw stanowisk pracowniczych. Zaznacz kontrolkę ComboBox i wybierz Właściwości/ Items, kliknij na wielokropku kolekcji.
W oknie dialogowym Kolekcja wprowadź kolejne wiersze z nazwami stanowisk i zatwierdź przyciskiem OK
Zablokuj możliwość edycji stanowisk w kolekcji kontrolki ComboBox. Blokowanie wykonasz przez zmianę wartości właściwości DropDownStyle na DropDownList. Patrz poniższa ilustracja.
Skompiluj program i sprawdź zachowanie kontrolki ComboBox. Prawidłowo działająca kontrolka nie pozwoli na edycję jej zawartości. Można tylko wybrać jedną wartość z listy.
Przejdź do grupy kontrolek Generowanie hasła i zaznacz pierwsze pole jako domyślnie wybrane. Czyli dla kontrolki checkBox1 ustaw właściwość Checked na True. Patrz poniższa ilustracja.
Ustaw wymagane kolory (tak jest w poleceniu zadania) tła okna na LightSteelBlue (#B0C4DE), a przycisków na SteelBlue (#4682B4) i biały kolor czcionki.
Uwaga. Zmianę koloru najszybciej zrobisz wpisując nazwę koloru z arkusza egzaminacyjnego do pola BackColor (nie popełnij błędu w pisowni)
Czynność powtórz dla przycisków. Zaznacz obie kontrolki Button i zmień BackColor na SteelBlue.
Teraz zmień w obu przyciskach kolor czcionki na biały.
Formatka po zmianach powinna prezentować się jak poniżej.
Generowanie hasła
Z warunków zadania wynika, że hasło jest (może być) kombinacją małych i dużych liter, cyfr i znaków specjalnych. Długość jak i losowy zestaw znaków zależy od wybranych ustawień. Do generowania przygotujemy odpowiednie ciągi znaków zapisanych w łańcuchu znaków typu string. Odpowiedni znak będzie wybrany przez wylosowanie indeksu z tego ciągu.
Przechodzimy do pliku Form1.cs i wprowadzamy deklaracje generatora liczb losowych, łańcuchy zestawów znaków oraz zmienną na hasło. UWAGA. W treści zadania podano dopuszczalny ciąg znaków specjalnych.
Wskazówka:
public partial class Form1 : Form
{
Random los=new Random();
string male = "qwertyuiopasdfghjklzxcvbnm";
string duze = "QWERTYUIOPASDFGHJKLZXCVBNM";
string cyfry = "0123456789";
string specjalne = "!@#$%^&*()_+-=";
string haslo = "";
public Form1()
{
InitializeComponent();
}
}
Funkcja generująca hasło powinna zwracać typ string, który jest wygenerowanym łańcuchem znaków tworzących hasło. Parametrem tej funkcji powinna być wartość typu całkowitego, która określa długość hasła podana przez użytkownika aplikacji.
Wskazówka:
string RobHaslo(int dlugosc)
{
string _haslo = "";
while (_haslo.Length < dlugosc)
{
if (checkBox1.Checked)
{
_haslo += duze[los.Next(0, duze.Length)];
if(_haslo.Length == dlugosc)return _haslo;
}
if (checkBox2.Checked)
{
_haslo += cyfry[los.Next(0, cyfry.Length)];
if (_haslo.Length == dlugosc) return _haslo;
}
if (checkBox3.Checked)
{
_haslo += specjalne[los.Next(0, specjalne.Length)];
if (_haslo.Length == dlugosc) return _haslo;
}
//małe są zawsze losowane, tak wynika z warunków zadania
_haslo += male[los.Next(0, male.Length)];
}
return _haslo;
}
Podana funkcja sprawdza, które warunki generowania hasła są wybrane przez użytkownika. Sprawdzanie odbywa się w pętli do momentu, dopóki hasło jest krótsze niż podana długość. Zauważ, że generator losowań zmienia górny zakres granicy losowania przez odczytanie długości aktywnego łańcucha znaków. Patrz funkcja los.Next(). Jednocześnie wynik losowania jest indeksem wybranego znaku. Dlatego w kodzie programu wywołujemy ją w nawiasach kwadratowych [].
Komunikat wygenerowanego hasła
Dla klawisza Generuj hasło w zdarzeniu Click() wywołamy funkcję generującą hasło. Wynik prześlemy do standardowego okna komunikatu, tak jak pokazuj eto ilustracja nr 2 z arkusza egzaminacyjnego.
Inicjujemy zdarzenie Click() dla przycisku generującego hasło. Przejdź do okna Własciwości/ Zdarzenia i dwa razy szybko kliknij w pustym obszarze zdarzenia Click.
Do ciała funkcji obsługującej zdarzenie Click() wprowadź poniższy kod
Wskazówka:
private void button1_Click(object sender, EventArgs e)
{
//odczytaj podaną długość hasła
int ile=Convert.ToInt32(textBox3.Text);
//w tersci zadania podano, że hasło ma byc przechowywane
//w zmiennej typu napisowego
haslo=RobHaslo(ile);
MessageBox.Show(haslo,"Wygenerowane hasło",MessageBoxButtons.OK);
}
Skompiluj program i sprawdź efekt działania.
Obsługa klawisza Zatwierdź
Przechodzimy do ostatniego etapu tworzenia aplikacji. Inicjujemy zdarzenie Click() dla klawisza Zatwierdź. Robimy to analogicznie jak dla klawisza Generuj hasło.
Przechodzimy do pliku kodu i wprowadzamy poniższy kod.
Wskazówka:
private void button2_Click(object sender, EventArgs e)
{
//imię
string i=textBox1.Text;
//nazwisko
string n=textBox2.Text;
//stanowisko
string s = comboBox1.Text;
string dane = String.Format("Dane pracownika: {0} {1} {2} Hasło: {3}",i,n,s,haslo);
MessageBox.Show(dane, "Wynik", MessageBoxButtons.OK);
}
Działanie kodu jest bardzo proste. Pierwsze trzy linijki odczytują imię (zmienna i), nazwisko (zmienna n), stanowisko (zmienna s). Hasło jest już wcześniej wygenerowane i zapisane do zmiennej haslo w zdarzeniu Cick() przycisku Generuj hasło. Wynik jest przeniesiony do zmiennej dane (typ string) przy wykorzystaniu formatowania łańcucha znaków. Patrz String.Format().
Uruchamiamy aplikację i sprawdzamy efekt działania.
Pełny kod aplikacji
Poniżej przedstawiam pełny kod aplikacji. UWAGA. W kodzie nie ma informacji o parametrach ustawień koloru, zawartości itemów kontrolki ComboBox itp.
Wskazówka:
using System;
using System.Windows.Forms;
namespace styczen_2023_problem_2_dane_pracownika
{
public partial class Form1 : Form
{
Random los=new Random();
string male = "qwertyuiopasdfghjklzxcvbnm";
string duze = "QWERTYUIOPASDFGHJKLZXCVBNM";
string cyfry = "0123456789";
string specjalne = "!@#$%^&*()_+-=";
string haslo = "";
string RobHaslo(int dlugosc)
{
string _haslo = "";
while (_haslo.Length < dlugosc)
{
if (checkBox1.Checked)
{
_haslo += duze[los.Next(0, duze.Length)];
if(_haslo.Length == dlugosc)return _haslo;
}
if (checkBox2.Checked)
{
_haslo += cyfry[los.Next(0, cyfry.Length)];
if (_haslo.Length == dlugosc) return _haslo;
}
if (checkBox3.Checked)
{
_haslo += specjalne[los.Next(0, specjalne.Length)];
if (_haslo.Length == dlugosc) return _haslo;
}
//małe są zawsze losowane, tak wynika z warunków zadania
_haslo += male[los.Next(0, male.Length)];
}
return _haslo;
}
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//odczytaj podaną długość hasła
int ile=Convert.ToInt32(textBox3.Text);
//w tersci zadania podano, że hasło ma byc przechowywane
//w zmiennej typu napisowego
haslo=RobHaslo(ile);
MessageBox.Show(haslo,"Wygenerowane hasło",MessageBoxButtons.OK);
}
private void button2_Click(object sender, EventArgs e)
{
//imię
string i=textBox1.Text;
//nazwisko
string n=textBox2.Text;
//stanowisko
string s = comboBox1.Text;
string dane = String.Format("Dane pracownika: {0} {1} {2} Hasło: {3}",i,n,s,haslo);
MessageBox.Show(dane, "Wynik", MessageBoxButtons.OK);
}
}
}