Přednáška: Úterý, 17:20, N1 (Pavel Ježek)
Cvičení:
Pondělí, 10:40, SW2 (Filip Kliber)
Středa, 14:00, SU2 (Filip Kliber)
Středa, 15:40, SW2 (Pavel Ježek)
Čtvrtek, 12:20, SU2 (Filip Kliber, Jan Pacovský)
Čtvrtek, 14:00, SU2 (Radek Zikmund)
Pátek, 9:00, SW2 (Jan Pacovský)
Stránka v SIS: NPRG035
Zakončení: Zkouška a zápočet
Table of contents
- Náplň přednášek
- Náplň cvičení
- Informace o zkoušce
- Informace o zápočtu
- Uznávání povinností z minulých let
[in English] This page contains information for Czech students of the Programming in C# Language course. For english, switch the language in the page header.
Náplň přednášek
1. přednáška
- Představení předmětu, zkouška
- Rozdíly v reprezentaci proměnných v paměti v jazycích Python, C++ a C#
- Rozdíly referenčních a hodnotových typů, předávání argumentů hodnotou
- Paměťový overhead u referenčních typů, třída
Type
record (class)
,record struct
Materiály
2. Přednáška
- Připomenutí rozdílu referenčních a hodnotových typů, rozhodnut při deklaraci typu
- Příklady typicky referenčních, resp. typicky hodnotových typů
- Implicitní typované proměnné (
var
),new
bez jména typu v kontextu kde je to zřejmé (parametr, deklarace) - Položky (field) vs. vlastnosti (property) v typech,
readonly
- Automaticky implementované vlastnosti
- Alokace na GC haldě, nulování paměti, konstruktory, initializers
init
settery u vlastnosti (C#9), klíčové slovorequired
(C#11)- Primary constructor pro
record class
arecord struct
- Nullable hodnotové typy,
is null
operátor
Materiály
- Slidy
- 02.0a-PersonClassColorStruct.zip
- 02.0b-PersonStructColorClass.zip
- 02.1-PropertiesVsFieldsSyntax.zip
- 02.2-PersonConstruction.zip
- 02.3-RecordSimplePrimaryConstructor.zip
- 02.4-Vector3DConstruction.zip
- 02.5-NullableValueTypes.zip
3. Přednáška
- Připomenutí nullable hodnotových typů
null
v běhovém prostředí .NET (CLR) a přístup knull
jakoNullReferenceException
- Nullable referenční typy (C#8)
- Duck typing v Pythonu, dynamicky typované jazyky
- Interface v C#, tabulka interface
I
u typuA : I
a najití metody několika dereferencemi v situaciI i = new A(); i.m1();
- Překryté metody klíčovým slovem
new
a hledání správné metody, která se bude volat - Operátor
is
aInvalidCastException
i v lepší variantěvariable is Type newVariable
- Vlastnosti=Properties (ne položky=fields) jakou součástí kontraktu v interface
Materiály
- 03.1-TraditionalCSharpNullable.zip
- 03.2-NullableReferenceTypes.zip
- 03.3-DuckPostPython.zip
- 03.4-InterfacesInClassHierarchy.zip
- 03.5-DuckPostCSharpContracts.zip
- 03.6-NamePropertyInDuckPostCSharpContracts.zip
4. Přednáška
- Nepřenositelnost (závislost na platformě) u přeloženého C++
- Řešení přenositelnosti pomocí universal executable (fat binary) na MacOS
- Překlad C# kódu (
csc.exe
) do (přenositelné) assembly (.dll) a následně JIT (Just in time) překlad na specifické platformě - Možnosti optimalizace v situacích JIT nebo AOT (Ahead of time) překladu
- CIL (Common intermediate language), metadata v assemly
- Spouštění C# programu přes příkaz
dotnet
a přes přeložené.exe
(windows only) - Nástoroje
ildasm
(součást .NET SDK) ailspy
(standalone nástroj), ladící informace (soubor.pdb
) - Dědičnost v C#, volání instančních metod (schovaný parametr
this
) - Abstraktní třída, společný předek
object
, volání konstruktoru předka přesbase
- Operátor
is
, třídaType
, metodaGetType()
a operátortypeof
- Operátor
is
a pattern-matching (C#9) - Operátory
?.
,?[]
(null-conditional operátor)
Materiály
- Slidy
- 04.1-LetsStudyMetadataConsoleApp.zip
- 04.2-IsPatternBasics.zip
- 04.3-StructuralIsPatterns.zip
- 04.4-CastNullabilityAway.zip
5. Přednáška
- Konstanty
readonly
,readonly static
,const
- Optimalizace překladače na
const
, konstanta na úrovni CIL const
pro základní typy astring
- Class (static) constructor,
.cctor
- Delegování konstruktoru pomocí
: this()
, pořadí inicializace - Nulování paměti před voláním konstruktoru díky GC
- Klíčové slovo
nameof
, podtržítko (_
) v číselném literálu enum
,System.Enum
, metodaToString
, atribut[Flags]
,enum.Parse
using
alias astruct
jako alternativa kenum
Materiály
- 05.1-ConstVsReadonly.zip
- 05.2-ConstructorsCore.zip
- 05.3-CtorNameLeakingInExceptionsCore.zip
- 05.4-OperatorNameof.zip
- 05.5-EnumBasics.zip
- 05.6-EnumFeatures.zip
6. Přednáška
- JIT optimalizace
- Tiered (1, 2) compilation
- Dynamic PGO (profile guided optimizations)
- (micro)benchmark
- ✖ struktura
DateTime
a vlastnostNow
- ✔ třída
System.Diagnostics.StopWatch
a metodyStartNew
,Stop
a vlastnostEllapsed
- BenchmarkDotNet a NuGetové balíčky
- ✖ struktura
- Překlad funkce (prolog, tělo, epilog), method inlining
System.Runtime.CompilerServices.MethodImpl
,MethodImplOptions
- hot-path, cold-path
- Výjimky, třída
Exception
, C# příkazthrow
(a CIL instrukcethrow
)try
-catch
blok, vyhození výjimky, zachytávání výjimky, stack-unrolling, vlastnostStackTrace
, dopad na výkon
7. Přednáška
- Deklarace/alokace proměnné, životnost proměnných, optimalizace, nutnost inicializace proměnné před čtením
- Životnost proměnných deklarovaných součástí pattern matchingu, omezení životnosti pomocí
{
a}
- klíčové slovo
params
- boxing, unboxing, boxování nullable hodnotových typů, nelze kombinovat unboxing s explicitním přetypováním
- Hodnoty proměnných v C#/.NET
- Hodnoty
- Reference
- Ukazatelé/pointers (nepoužívat)
- Tracking reference (archaický jazyk C++/CLI), klíčové slovo
ref
(více příště)
8. Přednáška
- Pokračování tracking referencí (
ref
) - Výstupní parametry (
out
; taky tracking reference) - Vstupní parametry (
in
; taky tracking reference) - Deklarace proměnné přímo v
out
parametru (podobně jakovalue is B b
) i jakovar
_
(podtržítko) jako jméno nepoužitého parametru (discard)- Klíčové slovo
goto
, výrazswitch
(ne příkaz) a pattern matching - Expression-bodied members (funkce
=>
tělo) - Metoda
Deconstruct
, generovaná vrecord
- Pattern matching pro seznam (C#11)
- Chybové stavy bez výjimek pomocí
Try*
metod aout
parametrů, pomocí nullable typů - Zachytávání výjimek,
catch
blok, znovu vyhození výjimek (throw;
) nebo zahození historie (throw ex;
) - Řetězení výjimek (
.InnerException
)
9. Přednáška
- Další povídání o výjimkách
- anotace
throws
v jazyce Java - Code Contracts (více na předmětu Program Analysis & Code Verification)
NullReferenceException
aIndexOutOfRangeException
vs.ArgumentNullException
aArgumentOutOfRangeException
finally
block, finalizer (více na Advanced .NET Programming II) a dispose pattern,IDisposable
aObjectDisposedException
, příkaz a blokusing
- anotace
- Textové řetězce (klíčové slovo
string
, typSystem.String
)- Internování stringů, řetězcové konstanty, imutabilita stringů
string
/char
literál, speciální znaky pomocí zpětného lomítka (\
,\x
,\u
)- konkatenace stringů,
StringBuilder
,string.Concat
,StringBuilder.Append
a fluent syntax
10. Přednáška
- Ještě pokračování stringů
- interpolované stringy (C#6.0;
$"{name} {age}"
),InterpolatedStringHandler
(C#10.0),string.Format
- interpolované stringy (C#6.0;
- Lokalizace aplikací
- resource soubory (.NET Resources;
.resx
),ResourceManager.GetString
- VS Build Action, VS Custom Tool
ResXFileCodeGenerator
, *.Designer.cs
- ISO-639 formát jazyka,
Thread.CurrentUICulture
- open source nástroj
ResXResourceManager
- satelite assembly
- resource soubory (.NET Resources;
- Globalizace aplikací
Thread.CurrentCulture
IFormattable
,IFormatProvider
, formáty (hex, měna, …),FormattableString
11. Přednáška
- Pokračování globalizace aplikací
- Konstruktor
CultureInfo
object.Equals
,object.ReferenceEquals
,IComparable<T>
,IComparer<T>
IComparable
na typustring
, resp.StringComparer
InvariantCulture
,CompareOrdinal
a case-sensitivity při porovnávání- Unicode, combining characters, grafémy,
IgnoreNonSpace
,NormalizationForm
- Konstruktor
- Volání metod
- zakrývání metod v potomkovi klíčovým slovem
new
, výběr metody za překladu (generování instrukcecall
) - virtuální metody (
virtual
),override
, tabulka virtuálních metod (vType
), volání metody za běhu (instrukcecallvirt
) abstract
implikujevirtual
a implikuje že typ musí býtabstract
,sealed override
- zakrývání metod v potomkovi klíčovým slovem
12. Přednáška
- Zakrývání členů v potomkovi (klíčové slovo
new
), warning vs. error - Syntaktický zápis virtuálních metod v jazycích C++, C# a Java a problémy s defaultně virtuálními metodami v Javě
- Optimalizace virtuálního volání
sealed override
metod asealed
typů (devirtualizace) - Tabulka virtuálních metod, interface tabulka a volání skrz interface
- Důvody pro explicitní
override
v C# oproti implicitnímu v C++ - Klíčové slovo
base
pro generování nevirtuálního volání z předka - Viditelnost členů třídy (
public
,protected
,private
,internal
,protected internal
,private protected
,file
) a implicitní viditelnost při deklaraci - Generování instrukce
callvirt
i při volání nevirtuálních metod - Volání virtuálních metod v konstruktoru
13. Přednáška
- Vlastnosti
- automaticky implementované (s backing field), obecné (obecný kód v
get
,set
), kontextové klíčové slovovalue
v implementaci setteru, metodyget_*
,set_*
- různé viditelnosti pro
get
/set
,get
nebo celá vlastnost jako expression-bodied members (a rozdíly mezi podobnou syntaxí) - rozdíl mezi vlastností a funkcí, požadavky na rychlost vlastností, konvence pojmenování
- parametrické vlastnosti (indexery), možnosti přetěžování (overloading) vlastností
- automaticky implementované (s backing field), obecné (obecný kód v
double.IsNaN
- I přesto, že
interface
formálně nedědí od objektu, tak se na něm dají volat metody objektu - Struktury
sealed
by deafult u hodnotových typů, nemožnost dědění u struktur, předávání struktur, volání instančních metod (ref this
, tracking reference)- Nutnost boxingu u struktur implementujících interface
- Rozdíl mezi
List
struktur a pole struktur (rozdíl mezi operátorem hranatých závorek a indexerem =get
) - A další problémy u mutable strukturami
- Vlastní bezparametrický konstruktor u struktur (C#9.0) a jeho (ne)volání v některých situacích, klíčové slovo
default
- Pole
- Nulování paměti u pole struktur
- Vždy referenčního typu, pomocná třída
Array
- Vícerozměrná pole (rectangular a jagged) a jejich efektivita (možnost změny mezí u obdélníkového pole)
Doporučená literatura
- Mark Michaelis with Eric Lippert: Essential C# 5.0, Addison-Wesley, 2013 (lze koupit např. na Amazon UK)
- Jeffrey Richter: CLR via C# (4th Edition), Microsoft Press, December 2012 (lze koupit např. na Amazon UK)
- Jon Skeet: C# in Depth (3rd Edition), Manning Publications, September 2013 (lze koupit např. na Amazon UK)
- blog Erica Lipperta (bývalý člen C# týmu v Microsoftu): Fabulous Adventures In Coding
- C# Language Specification 5.0
Případně
- Christian Nagel, Evjen, Jay Glynn, Karli Watson, Morgan Skinner: Professional C# 4.0 and .NET 4, Wrox, John Wiley & Sons, March 2010 (lze koupit např. na Amazon UK
Náplň cvičení
1. Cvičení
- Informace o předmětu, podmínky získáni zápočtu (k dispozici na této stránce)
- Připomenutí práce s Visual Studio (2019)
- Vyrobení projektu (.NET Framework / .NET Core), struktura projektu
- Konfigurace projektu, Intellisense, Bloková selekce, Dokumentační komentáře, Odsazení
- Překlad, Spuštění, Debugging (základy)
- Doplněk do visual studio, který přidá šablonu na vytváření projektů s nastavením podobným tomu v ReCodExu, je možné stáhnout zde
- Zadání úloh Počítání slov a Četnosti slov
2. Cvičení
- Čtení slov ze souboru:
- ✖
StreamReader.ReadToEnd
(problém s velkými soubory) - ✖
StreamReader.ReadLine
(problém s dlouhými řádkami) - ✔
StreamReader.Read
(po znacích)- Vrací
int
(extra-1
v rozsahu jako identifikace konce souboru) - Konverze do
char
přes standardní přetypování(char)
, ale až po kontrole== -1
konce souboru
- Vrací
- ✖
- Kontrola existence souboru, a faktu jestli se dá otevřít/číst jenom pomocí výjimek z konstruktoru třídy
StreamReader
File.Exists
není dostatečné, když v je v systému více processů s přístupem k filesystému
- Problémy se zachytáváním příliš velkého rozsahu výjimek (
catch (Exception)
schováOutOfMemoryException
) - Počítání slov
- Analýza
SortedDictionary
vsDictionary
vsSortedList
vs Vlastní DS - Záleží na poměru unikátních slov a všech slov v souboru
- Analýza
- Zadání úlohy Zarovnání do bloku
- Jeden řádek už se do paměti nevejde
3. Cvičení
- Drobné komentáře k úloze zarovnání do bloku
- Nástroj
diff
(Command Line)- Grafické: KDiff3, Visual Studio Code
- Testování aplikací
- Integrační testy
- UnitTesty (MSTest, xUnit, NUnit, MSDN tutorials (.NET Core))
- ArrangeActAssert
- Mock-up
- Příklad testů pro WordReader: ProgramTests s Mock-upy, WordReaderTests, Kompletní projekt pro .NET Core 3.1
- Nová úloha Vícesouborové zarovnání
- Rozšíření předchozí úlohy
- Za 5 bodů
- Extra 5 bodů nad rámec za rozumné UnitTesty
- UnitTesty je třeba odevzdat v separátním souboru a zakomentované (
/* ... */
, případně#if ... #endif
), aby to ReCodEx nepřekládal (nemá reference na unit testovací framework)
4. Cvičení
- Ukázka špatných unit testů jako integračních testů (místo testování kombinací vstupů jedné metody se testuje kombinace vstupů kombinací metod v mainu)
- Testování “zbytků” (glue-code)
- Separátní metoda
Run
která může dostat upravené argumenty - Testování
Console
přes použitíRun(TextWriter)
(z Mainu se dá volat jakoRun(Console.Out)
)
- Separátní metoda
- Komentáře k zarovnávání do bloku
- Základní verze s privátními metodami pro tisknutí zarovnaného textu (nelze unit testovat)
- Pokročilá verze se separátním
ILineJustifier
, který zároveň vede na hezký highlighting pomocíIStringWriter
, z čehož vznikne adaptor a wrapper design pattern.
- Nová úloha Internetové knihkupectví
- Zkusit využít návrhový vzor ModelViewController (MVC)
5. Cvičení
- Ještě dodělání Vícesouborového zarovnání do bloku:
- Zpracovávání více souborů pomocí návrhového vzoru factory
- Ukázkové řešení internetového knihkupectví
- Nová úloha Huffman I
- Strom je třeba mít uložený v paměti v nějaké objektové reprezentaci. Nestačí jej postupně tisknout.
6. Cvičení
- Komentáře k úloze Huffman I
- Uvědomění si, kde je kladen důraz na výkon (čtení souboru nebo stavění stromu)
- Rozdíly mezi
BinaryReader
aFileStream
, interní implementační detaily a možnost zefektivnění ještě dalším vlastním bufferováním (o velikosti 2n) - Přístupy k počítání frekvencí:
Dictionary<byte, long>
vs.new long[256]
(int
není dostatečně velký pro 1TiB soubory) - Reprezentace
HuffmanTree
: přímočarý přístup nebo více objektově orientovaný přístup - Stavění stromu:
PriorityQueue
(heap) vs. jednoduché dvě fronty (Queue
) pro listové a vnitřní uzly, případně jeden setříděný seznam a postupné zatřiďování nových uzlů (částečně insert sort) - Tisknutí stromu: rekurze vs. explicitní
Stack
- Možné řešení
- Nová úloha Huffman II
- Bitové operace v C#: or
|
, and&
, xor^
, not~
, left shift<<
right shift>>
(>>
je závislé na znaménkovosti typu) BinaryWriter
BitConverter
,byte[] GetBytes(int)
,GetInt32(byte[])
, …
- Bitové operace v C#: or
7. Cvičení
- Komentáře k úloze Huffman II
- Zase, uvědomění si, ve které části programu jde o výkon (čtení souboru vs. stavění stromu vs. čtení souboru podruhé vs. zapisování do souboru)
- Jak generovat bitové sekvence
- ✖ Jako
string
("1011" + "0"
), což alokuje novou paměť pro každou konkatenaci a musí kopírovat data z původních řetězců - ✖ Převod
string
u nabyte
pomocíConvert.ToByte("10110", 2)
, což je univerzální algoritmus, který podporuje více soustav, než jen binární, kterou nativně podporuje procesor- Můžeme si konverzi udělat sami Hornerovou metodou a přidáváním (bitový or) hodnot
- ✔ Pomocí bitových operací (or
|
, and&
, xor^
, not~
, left shift<<
right shift>>
)
- ✖ Jako
- Jak nastavit n-tý bit
value
na 1? Jakovalue | x
, kde binární reprezentacex
má samé nuly, kromě jedné1
na n-té pozici (což je nějaká druhá mocnina)- ✖
Math.Pow(2, x)
je zase univerzální funkce na mocniny, která podporuje i reálná čísla (tedy obecný algoritmus, neoptimalizovaný na mocniny dvojky) - ✔
1 << x
- ✖
- Jak od-nastavit n-th bit (nastavit jej na 0)
value
? Jakovalue & x
, kde binární reprezentacex
má samé jedničky, kromě jedné0
na n-té pozici, což je negace mocniny dvojky.value & ~(1 << n)
- Dává smysl si připravit cache kódů, abychom nemuseli znovu a znovu procházet strom
- Možné řešení
- Rozdíly mezi
byte[] BinaryReader.ReadBytes(int lenght)
aint FileStream.Read(byte[] buffer, int offset, int length)
, kde první možnost musí alokovat nový buffer, kdežto druhá možnost může opakovaně používat ten samý
- Použití symbolu
@
před jménem je způsob, jak vyrobit identifikátor, se stejným jménem jako je klíčové slovo v C# (např.int @while
nebovoid @else()
). verbatim identifier- Se hodí, při interakci s .NET jazykem L, ze kterého chceme použít identifikátor, který je rezervovaný v C#, ale ne v L
- Použití podtržítka v číselné konstantě jakožto oddělovat cifer pro čtenáře (např.
int price = 12_751;
neboulong bits = 0b10110010_10010101
). digit separator - Nástroje typu profiler v .NET, pro měření výkonu aplikace z pohledu CPU
- Sampling (vzorkování)
- Spustí program a v pravidelných intervalech jej zastavuje, aby se sebral vzorek — z ladících informací a instruction pointeru se dá vyčíst přesné místo v kódu, kde došlo k zastavení
- Z těchto vzorků se vyrobí statistika s myšlenkou, že více vzorků na stejném řádku značí, že vyhodnocení řádku trvá nějakou dobu
- Nefunguje pro sbírání vzorků z kódu OS (kernel), jako např. IO operace
- Malý overhead, nepřesné, generuje statistická data
- Instrumentace (instrumentation)
- Modifikuje existující program tak, že na začátek a konec každé funkce se dá volání profileru, které může měřit přesný čas, jak dlouho funkce trvala
- Tyto data jsou přesná (v rámci přesnosti měření, ale nejedná se o statistiku)
- Může měřit dobu systémových volání (např. IO operace)
- Obrovský overhead, přesné, generuje extrémní množství dat
- Je nutné výstupy brát s rezervou
- Sampling (vzorkování)
- Nová bonusová úloha Huffman III (deadline v letním semestru)
- Huffman II naruby — Dekomprese
- Nic nového, tudíž nekomentováno na cvičení a tedy s deadlinem až po zkouškovém
- Nová standardní úloha Excel
- Nesnažte se za běhu vypisovat výstup, ale první načtěte list, ten vyhodnoťte, a pak až vypište do souboru
- Nesnažte se podporovat vyhodnocování vzorců v jiném typu (např. v doublech)
- Nesnažte se podporovat jiné druhy vzorců (funkce, více operátorů, konstanty)
- Základní řešení dá pouze 80% bodů (12/15), pro 100% (15 bodů) je třeba naprogramovat i rozšíření
8. Cvičení
- Prodloužení deadline na Excel o jeden týden
- Rady jak se poprat s pamětí při řešení Excelu
- Buňky mají různý obsah (
13
,=A1+B2
,[]
, …). Je tedy logické, že budou v paměti reprezentované jinými typy - To automaticky šetří paměť, protože si každá buňka pamatuje jen to co potřebuje a ne sjednocení všeho (např. prázdná buňka si nepotřebuje pamatovat žádná data)
- Zároveň to vede na hezký návrh, který je jednoduše rozšířitelný. Když budeme chtít pokročilejší vzorce, stačí přidat nový typ, a není nutné měnit chování jiných buněk.
- Struktura sešitu v paměti by neměla být závislá na formátu vstupního souboru. Pokud se formát změní (např. budeme chtít podporovat
.xls
soubory Microsoftího excelu), tak nechceme měnit formát v jakém jsou data uložená v paměti. - Myslete na overhead datových struktur, které používáte. Např. overhead u
Dictionary
v použitíDictionary<string, Sheet>
je téměř nulový, kdežto uDictionary<string, int>
je to několik set procent paměti navíc. - Pokud nemáte ukázkové vstupy, tak si nějaké vyrobte. Nebude těžké naprogramovat jednoduchý program, který vyrobí složitý dokument, který má desítky tisíc řádků nebo sloupců nebo vyžaduje vyhodnocení o tisících krocích.
- Buňky mají různý obsah (
- Conditional compilation
- Možnost zařídit (ne)překládání části kódu v souboru v závislosti na jednoduché podmínce (např. pro ladění a produkci)
#define IDENT
,#if IDENT
,#else
,#endif
(tyto konstanty je možné definovat taky v nastavení projektu)#warning
,#error
- Task list ve visual studiu
- Speciální klíčová slova v komentářích (
HACK
,TODO
), které čte Visual Studio a zobrazuje je v Task List okně
- Speciální klíčová slova v komentářích (
- Úvod/Opakování nástrojů pro správu verzí (version control systems)
- Archaické SVN s Local Working Directory (commit/update) Central Repository
- Moderní Git/Hg s Local Working Directory (add/remove) Staging Area (commit/checkout) Local Repository (push/pull) Remote Repository
- Ukázka použití Gitu z grafického nástroje (Tortoise Git) nebo přímo z Visual Studia
- Jiné grafické nástroje: GitExtension (Windows, Git), SourceTree (Windows/Mac, Git/Hg)
- Používání Gitu z příkazové řádky (a dalších užitečných nástrojů pro vývoj SW) se učí v předmětu Nástroje pro vývoj software
- Nové bonusové úlohy (s deadline v prvním týdnu letního semestru)
- Hradlové sítě, 30 bodů
- Hradlové sítě II, 30 bodů
- Hradlové sítě III, 40 bodů
- Úlohy, které jsou jednoduché z pohledu algoritmu, ale velmi náročné na správné rozvrhnutí. Rozmyslet si správně strukturu programu je velmi důležité pro splnění těchto úkolů!
- Příklad simulace hradlové sítě nad specifickým vstupem
9. Cvičení
- Excel Impossible
- Komentáře k řešení Excelu
- Rozdíly ve využití paměti při ukládání hodnot jako
int
(1234
) nebostring
("1234"
) - Různé druhy buněk jsou reprezentované různými typy (
NumericCell : Cell
,FormulaCell : Cell
) - Rozdělení parsování souboru a jednotlivých algoritmů pro parsování různých typů buněk
- Parsování referencí ve vzorcích
- ✔ Hornerovo schéma
- ✖
int.Parse
; naparsuje také-10
nebo00123
- ✖ Regulární výrazy; špatně čitelné, těžkotonážní, parsování výrazu do automaty a pak obecný algoritmus na průchod automatem
- Možné řešení
- Rozdíly ve využití paměti při ukládání hodnot jako
- Nová úloha Vyhodnocování výrazů
- Výraz v prefixové formě je nutné naparsovat do nějakých rozumných datových struktur a pak až spustit vyhodnocovací algoritmus.
- Důraz na rozšiřitelnost o nové operátory, funkce, …
- Nesnažte se o řešení, které bude umět pracovat s libovolnými typy (
double
,string
, komplexní čísla, zlomky). Výrazy budou vždy přirozená čísla (int
). - Pro vyhodnocení použijte rekurzi, protože to pak vede na lepší design aplikace.
- 5 bodů za testy v ReCodExu, dalších 5 bodů za vhodnou reprezentaci výrazů v paměti.
10. Cvičení
- Komentáře k řešení Vyhodnocování výrazů I
- Reprezentace výrazů jako strom (což vede na jednoduchou manipulaci s pod-výrazy; Abstract Syntax Tree)
- Použití klíčových slov
sealed
aabstract
jako rady ostatním programátorům kde se má aplikace rozšiřovat/které typy se mají vyrábět. Zároveň to může použít i překladač pro nějaké micro-optimalizace - Nevýhody implementace pod-uzlů jako
Expression[] array
. Použití specifických tříd (BinaryOperator
, …) s danou aritou - Specifické třídy
PlusExpression
,MinusExpression
, … pro oddělení vyhodnocování výrazů a výpočtu hodnot - Parsování vstupu pomocí zásobníku ještě nedodělaných výrazů, což vyžaduje podporu v třídě
Operator
metodouAddOperand
(která ale nerozbíjí immutability) - Nevýhody použití
switch (token)
pro vytváření jednotlivých operátorů. Řešení tohoto problému nebylo prezentování (vizte Bonus níže) - Možné řešení
- Představení návrhového vzoru Visitor
- Nová úloha Vyhodnocování výrazů II
- 5 bodů za funkční řešení
- 5 bonusových bodů za využití návrhového vzoru visitor pro implementaci vyhodnocování v reálných číslech (originální algoritmus pro vyhodnocování v celých číslech není nutné předělávat)
- Bonus: 5 dalších bodů za implementaci parsovacího algoritmu takovým způsobem, který umožní jednoduché začlenění nových operátorů (jinými programátory, kteří používají naši knihovnu) bez nutnosti nějaké formy
switch (operator)
11. Cvičení
- Komentáře k řešení Vyhodnocování výrazů II
- Použití společného interface pro všechny visitory, což usnadňuje přidávání nových algoritmů
- Visit metody přijímají konkrétní operátory (
PlusExpression
, …) abychom se vyhnuli konstruktu jakoswitch (operator)
- Problémy s vracením hodnot z metod
Visit
aAccept
podle kvality (nejhorší po nejlepší)- ✖ Použití typu
double
protožeint
se vejde dodouble
(alestring
se dodouble
nevejde). - ✖ Použití typu
object
jako návratovou hodnotu, protože vše je potomkemobject
u. Vede na neefektivní řešení kvůli boxování a případné problémy sInvalidCastException
až za běhu u zákazníka - ✖ Použití explicitního zásobníku místo volacího zásobníku jako prostor, kam si můžu ukládat hodnoty
- ✖ Vícero interfaců a
Accept
metod, které vrací různé typy (int
,double
, …) - ✖ Použití jedné hodnoty, která je sdílená mezi voláními při vyhodnocování podvýrazů
- ✔ Nejlepší způsob řešení se dozvíme později
- ✖ Použití typu
- Bonus z minula (parsování) prodloužen do “příště”. Stále je možné ucházet se o body za šikovnou implementaci parsování
- Nová úloha Vyhodnocování výrazů III
- 5 bodů za základní funkční řešení
- 5 dalších bodů za implementaci nových algoritmů, které splňují následující pravidla:
- Přidání nového algoritmu nevyžaduje modifikaci existujících datových struktur
- Přidání nového typu operátoru způsobí, že se nepřeloží žádný existující algoritmus
- Bonus: 5 dalších bodů za implementaci parsovacího algoritmu takovým způsobem, který umožní jednoduché začlenění nových operátorů (jinými programátory, kteří používají naši knihovnu) bez nutnosti nějaké formy
switch (operator)
Informace o zkoušce
Zkouška probíhá primárně písemnou formou, a v každé zkouškové písemce je kolem 6 až 8 otázek (některé obsahují podotázky). U každé otázky, případně podotázky, je dole uvedeno, jaký maximální počet bodů (=N
) lze za správně odpovězenou otázku/podotázku získat: N
bodů získáte v případě, že je odpověď na otázku správně; 0,5 * N
bodu získáte, pokud odpověď není zcela kompletní, ale jinak je správná (tj. nějaká malá část odpovědi chybí nebo je nepřesná); v ostatních případech získáte 0
bodů (tj. pokud v odpovědi chybí větší část, nebo je odpověď na otázku plně nebo i jen z části nesprávná).
Celkem lze z každé písemky získat maximálně 10
bodů. Mapování získaných bodů na výslednou známku je následující:
Body z písemky | Výsledná známka |
---|---|
10 – 8,5 | 1 |
8 – 6,5 | 2 |
6 – 5 | 3 |
4.5 – 0 | 4 |
Každá zkoušková písemka trvá 150 minut, tj. ideálně 20 minut na každou otázku + 30 minut bezpečnostní rezerva. Po písemné části následuje ústní část, kde zkoušející se studentem prochází jeho písemku, a případně nepřesností/nejasností u některých odpovědí se ptá na doplňující otázky — na základě toho je určeno finální bodové hodnocení každé otázky. Základem hodnocení je ale vždy písemná část, tedy u otázky bez odpovědi nebo se špatnou odpovědí nelze ani po ústní části získat více než 0 bodů.
Níže budou pro ilustraci uvedena zadání vybraných písemek z již proběhlých termínů:
- 13.1.2023 (PDF)
- 9.1.2023 (PDF)
- 16.1.2019 (PDF) [příloha zadání (dokumentace List<T>.RemoveAt)]
- 16.1.2018 (PDF) [příloha zadání (dokumentace List<T>.Insert)]
- 25.1.2017 (PDF)
- 1.2.2016 (PDF)
- 27.1.2016 (PDF)
- 20.1.2016 (PDF)
Doplňkové informace o zkoušce
Kromě informací uvedených ve slidech z první přednášky navíc pro zkoušky z NPRG035, NPRG038, a NPRG057 platí následující 2 body:
- Pokud někdo bude zapsán na nějakém z termínů zkoušky a na termín se nedostaví, bude mu tento termín v SISu označen jako propadlý (tj. student přijde o jeden pokus). Cílem tohoto opatření je optimalizace vytíženosti jednotlivých termínů, aby všichni studenti měli možnost přijít až na 3 termíny zkoušky.
- Pokud někdo na zkoušce získá známku 2 nebo 3 a bude si chtít svůj výsledek zlepšit, může explicitně na místě během vyhodnocení zkouškové písemky požádat zkoušejícího o nezapsání známky. Zkušební termín mu pak bude v SISu označen jako propadlý. Takový student může pak později
- požádat o dodatečné zapsání získané známky, nebo
- přijít na jiný termín zkoušky (jakýmkoliv výsledkem této “opravné” zkoušky se ovšem anuluje předchozí získaná známka).
Modelový příklad 1:
Student X získá na 1. termínu známku 2 a odmítne ji. Na 2. termínu získá známku 3 a odmítne ji. Na 3. termínu získá známku 1.
Aktuální stav studenta X: 1. termín = propadlý, 2. termín = propadlý, 3. termín = 1, tj. student X zkoušku splnil s hodnocením 1.
Modelový příklad 2:
Student Y získá na 1. termínu známku 3 a odmítne ji. Na 2. termínu získá známku 4.
Aktuální stav studenta Y: 1. termín = propadlý, 2. termín = 4, tj. pokud chce zkoušku splnit, musí student Y přijít na 3. termín. Pokud na 3. termínu opět získá známku 4, tak zkoušku nesplnil.
Modelový příklad 3:
Student Z se nedostaví na 1. termín, na 2. termínu získá známku 3 a odmítne ji, na 3. termínu získá známku 4.
Aktuální stav studenta Z: 1. termín = propadlý, 2. termín = propadlý, 3. termín = 4, tj. student Z zkoušku nesplnil.
Informace o zápočtu
Pro získání zápočtu je nutné splnit tři podmínky:
1. Zápočtový test
Naprogramovat a odladit jeden jednoduchý příklad v časovém limitu 3 hodiny. Koná se během zkouškového období v počítačové laboratoři. Celkem pět pokusu na splnění testu, maximálně však tři během zimního zkouškového období (další pak případně v letním termínu).
2. Zápočtový program
Termíny NPRG035 (zima) i NPRG038 (léto), NPRG057 (léto), NPRG064 (léto):
- Specifikace: 7. 7. 2023
- Předvedení finální plně funkční verze (včetně uživatelské a programátorské dokumentace):
-
- deadline: 9. 8. 2023
-
- deadline: 8. 9. 2023
-
Požadavky na program z NPRG035, NPRG064 (zdrojového kódu v jazyce C# ⇒ nevygenerovaný (ručně psaný) rozumný kód včetně rozumných komentářů):
- Předvedeno do 1. deadline: minimálně 30 kB zdrojového kódu v jazyce C#
- Předvedeno do 2. deadline: minimálně 45 kB zdrojového kódu v jazyce C#
- Předvedeno po 2. deadline: minimálně 60 kB zdrojového kódu v jazyce C#
Požadavky na program z NPRG038, NPRG057 (zdrojového kódu v jazyce C# ⇒ nevygenerovaný (ručně psaný) rozumný kód včetně rozumných komentářů + netriviální a rozumné použití některé z „technologií“ probíraných v NPRG038, resp. NPRG057 [více viz dané předměty]):
- Předvedeno do 1. deadline: minimálně 45 kB zdrojového kódu v jazyce C#
- Předvedeno do 2. deadline: minimálně 60 kB zdrojového kódu v jazyce C#
- Předvedeno po 2. deadline: minimálně 90 kB zdrojového kódu v jazyce C#
Poznámka: Každý zápočtový program, který splňuje požadavky NPRG038, resp. NPRG057, splňuje i požadavky NPRG035 (tj. lze odevzdat jeden program za oba předměty).
Poznámka: rozumný/rozumné = na požádání posoudí cvičící
POZOR! Osobní předvedení je součástí odevzdání. Na předvádění si připravte několik slidů shrnujících: hlavní funkce programu + hlavní řešené problémy + nástin architektury.
3. Domácí úkoly
Na cvičeních se budou postupně zadávat domácí úkoly, za jejichž vyřešení obdržíte body. Povinnost vám bude uznána pokud získáte dostatečné množství bodů, podle toho, jestli se cvičení účastníte. Získání většího množství bodů vám může pomoct získat body i ke zkoušce dle tabulky níže. K uznání povinnosti je třeba získat alespoň 80b.
Všechny domácí úkoly postupně najdete v ReCodExu pro NPRG035. Tam je také řešte a odevzdávejte. POZOR: Na úkoly zadané na cvičení je standardní deadline 7 dní (tj. do začátku příštího cvičení)!
Upozornění: Domácí úkoly jsou samostatnou prací, jejímž cílem je zhodnotit schopnost studenta samostatně vypracovat složitější program v jazyce C#. Pokud bude zjištěno, že některý student odevzdal cizí řešení (např. několik studentů odevzdalo různé instance stejného řešení některého domácího úkolu, apod.), bude to považováno za pokus o podvod. Všichni takoví studenti nesplní předmět NPRG035 v tomto akademickém roce a přicházejí o možnost uznání splněných povinností v roce příštím; případně bude disciplinární komisi UK MFF doporučeno jejich vyloučení ze studia!
Za nadstandardní množství bodů z úkolů je možné získat body ke zkoušce, a sice takto:
- min. 80 bodů = úroveň “I Can Win” → splněn jeden z požadavků na zápočet, konkrétně bod “povinnosti ze cvičení”
- min. 100 bodů → získání 1,25 silných bodů do zkoušky z NPRG035
- min. 120 bodů = úroveň “Hardcore” → získání dalších 0,75 silného bodu do zkoušky z NPRG035
- min. 150 bodů = úroveň “Nightmare!” → získání 0,5 slabého bodu do zkoušky z NPRG035
- min. 200 bodů = úroveň “Mission Impossible” → získání dalšího 0,5 slabého bodu do zkoušky z NPRG035
- min. 228 bodů = “božská úroveň” → na 1 rok propůjčen titul “bohyně veškerého Csharpistva” nebo titul “bůh veškerého Csharpistva”
Celkem lze tedy získat až 2 silné bonusové body a až 1 slabý bonusové body do zkoušky z NPRG035 (hodnocení zkoušky viz slidy z první přednášky). Pozor — tyto silné bonusové body se budou započítávat pouze při 1. pokusu o složení zkoušky (tj. při svém 2. i 3. pokusu mají všichni 0 silných bonusových bodů). Nerozlišuje se z jakého důvodu student přichází na 2. nebo 3. termín (tj. zda např. odmítl známku na 1. termínu). Slabé bonusové body se budou započítávat při všech pokusech o složení zkoušky, ale pozor: slabé bonusové body nedokáží prorazit bariéru mezi známkou 4 a známkou 3 (tj. pokud po přičtení silných bonusových bodů stále vychází známka 4, tak se slabé bonusové body do výsledku zkoušky nezapočítávají).
Poznámka: Virtuální cvičení je určeno pro studenty, kteří nechtějí chodit na cvičení (např. protože minulý rok nestihli dodělat pouze zápočtový program, splnit zápočtový test, apod.).
Uznávání povinností z minulých let
Pokud jste tento předmět měli zapsaný loňský akademický rok a splnili jste pouze některé z povinností potřebných pro udělení zápočtu, může vám je po explicitním požádání (např. při předvádění zápočtového programu) uznat váš letošní cvičící (lze uznat splněnou docházku, domácí úkoly, zápočtový test, odevzdaný a schválený zápočtový program). Téma zápočtového programu (pokud ho ještě nemáte dokončený) nemusí být novým cvičícím uznáno. Pokud jste v loňském roce úspěšně složili zkoušku, ale nepodařilo se vám získat zápočet, opět po explicitním požádání vám může zkoušku uznat Pavel Ježek. Toto je iniciativa vyučujících tohoto předmětu a nelze ji požadovat po studijním oddělení!