Programmeermethoden 2024
Tweede programmeeropgave: Netjes
De
tweede programmeeropgave van het vak
Programmeermethoden
in het najaar van 2024
heet
Netjes;
zie ook het
vierde werkcollege,
vijfde werkcollege
(de betreffende WWW-bladzijde bevat handige
tips)
en
zesde werkcollege,
en lees geregeld deze pagina op WWW.
Er moet een programma worden
geschreven dat een foutloos te compileren C++-programma (bijvoorbeeld een uitwerking
van de eerste programmeeropgave) een klein beetje
probeert te begrijpen, oftewel een paar zaken doet die een compiler ook moet doen.
Het programma moet de invoerfile netjes ingesprongen naar een uitvoerfile
kopiëren, en daarbij alle //-commentaar weglaten.
En tellen hoe vaak een gegeven drietal letters direct achter elkaar voorkomt.
Verder moet het programma getallen opsporen, en kijken of deze een speciale eigenschap hebben.
Stel allereerst enkele eenvoudige vragen om gegevens van de gebruiker te
weten te komen.
Gevraagd wordt
hoe de originele invoerfile en de "doelfile" heten
(als de invoerfile niet bestaat stopt het programma direct),
en hoe groot de parameter tab (zie straks) moet worden.
Het programma leest dan eenmalig de opgegeven invoerfile,
en schrijft deze symbool voor symbool op
de juiste wijze aangepast weg naar de uitvoerfile;
na afloop wordt een rapportje op het scherm afgedrukt.
De volgende vier punten moeten worden geadresseerd:
- Commentaar moet verwijderd worden.
Elk commentaar dat begint met //
moet niet naar de uitvoerfile worden weggeschreven, maar weggelaten worden.
Alleen de regelovergang wordt weer naar de uitvoerfile gekopieerd.
Voor het gemak mag aangenomen worden dat er geen
/* ... */ commentaar voorkomt.
Als er binnen //-commentaar opnieuw
// voorkomt, wordt die volgende // ook gewoon verwijderd.
We vatten zelfs // binnen een string op als het begin van commentaar.
- Inspringen moet netjes geregeld worden.
De bedoeling is dat iedere regel op diepte d
even ver inspringt, en wel tab maal d spaties
(0 als d < 0).
Hierbij is tab een door de gebruiker te kiezen getal,
bijvoorbeeld 3. De diepte d van een regel
wordt als volgt bepaald.
De eerste regel van het programma is op diepte 0,
iedere openingsaccolade { verhoogt de diepte met 1 (één)
en iedere sluitaccolade } verlaagt de diepte met 1 (één).
Een veranderde diepte merk je pas op de volgende regel
(zie verderop hoe we accolades zelf afhandelen).
We nemen
aan dat er geen accolades binnen strings (of als karakter '{')
voorkomen. Accolades die binnen commentaar staan tellen niet mee voor
de berekening van de diepte.
De oude regelstructuur van het programma blijft behouden;
voor iedere regel geldt dat het eerste karakter ongelijk spatie en TAB
('\t') op positie tab maal d +1 moet komen.
Dit karakter kan een regelovergang zijn; zo wordt
een oorspronkelijk "lege" regel op diepte d nu een regel met
tab maal d spaties, en een regelovergang.
Wellicht ten overvloede, een regel met een stel spaties en TAB's, en
dan verder alleen //-commentaar, komt als tab maal d
spaties in de uitvoerfile.
En op welke positie staat een accolade, als dit het eerste symbool
is dat op een regel wordt afgedrukt?
We spreken af dat als dit een openings-accolade is hiervoor
nog de "oude" diepte wordt gebruikt,
en voor een sluit-accolade de "nieuwe". We krijgen dus
(waarbij een punt (.) een spatie voorstelt; tab = 3, d = 2):
......if ( x == y )
......{
.........z = 0;
......}
- Elk optreden van een drietal letters moet worden geteld.
Vraag aan het begin drie verschillende kleine letters aan de gebruiker (net zolang
tot dat gelukt is). Tel hoe vaak deze drie letters, in die volgorde, in de file voorkomen.
Hierbij matcht een hoofdletter in de tekst de bijbehorende kleine letter.
Optredens binnen strings en binnen commentaar tellen ook mee.
Er mogen hierbij geen strings worden gebruikt. Schrijf ook zelf een functie die een hoofdletter
naar de bijbehorende kleine letter converteert.
- Hebben we misschien met Lychrel-getallen te maken?
Voor elk geheel getal > 0 uit de invoerfile wordt gekeken of het een
Lychrel-getal is. Je telt herhaald het getal bij diens omgekeerde op,
bijvoorbeeld 196 plus 691 wordt 887, dan 887 plus 788 wordt 1775, enzovoorts. Je stopt als je een palindroom hebt (dat is een getal dat gelijk is aan diens omgekeerde, bijvoorbeeld 5372735, of 200002, of 7); dan is het oorsponkelijke getal geen Lychrel-getal. Je stopt ook als je boven INT_MAX uitkomt, en dan weet je het niet.
Op het scherm wordt het oorsponkelijke getal afgedrukt, en wat het aantal iteraties is om bij een palindroom uit te komen (bijvoorbeeld 0 voor 545, en 1 voor 113), of het nummer van de iteratie waarvan het resultaat
boven INT_MAX (gebruik include <climits>) uitkomt. Als dit laatste gebeurti (bijvoorbeeld bij 196 tijdens de 18de stap), wordt dit erbij vermeld.
Elke directe opeenvolging van cijfers in de invoerfile wordt als
een geheel getal opgevat. Neem aan dat ze alle kleiner dan of gelijk aan
INT_MAX zijn. Zo bevat 123abcd-"qqq 5"+++uvw-77.88ddd//vb5656
de gehele getallen 123, 5, 77 en 88.
Het maakt verder ook niet uit of een getal al dan niet binnen een string staat,
het telt gewoon mee.
Getallen binnen commentaar worden niet gedaan.
Neem aan dat de getallen in de invoerfile tussen 1 en INT_MAX, grenzen inbegrepen, zitten.
Na afloop moet worden meegedeeld of de accolades in de invoerfile goed "gepaard" waren.
Het kan om twee redenen mis zijn gegaan: te veel of te weinig sluitaccolades.
Ook wordt dan het aantal optredens van de drie letters genoemd.
Ter verdere inspiratie, zie het vijfde werkcollege.
Let op: files van websites kopiëren door met rechter muisknop
op de links te klikken, anders (met markeer-copy-paste) gaan spaties/tabs wellicht fout!
Twee voorbeeldfiles:
- File simpel2024.txt moet worden
simpel2024uit.txt, als tab gelijk aan 3 is. Accolades niet goed gepaard.
- File lastig2024.cc moet worden
lastig2024uit.cc, als tab gelijk aan 3 is. Het drieletterwoord the komt 6 keer voor, en het 3 keer.
Accolades goed gepaard.
Opmerkingen
-
We nemen aan dat de gebruiker zo vriendelijk is verder geen
fouten te maken bij het invoeren van gegevens.
Als een getal gevraagd wordt, geeft hij/zij een getal.
-
Gebruik de regelstructuur: elke regelovergang in een bestand bestaat
uit een LineFeed
(\n) (in UNIX) of een CarriageReturn gevolgd door een LineFeed
(\r\n) (in Windows).
Normaal gesproken gaat dit "vanzelf" goed.
We nemen aan dat er voor het EndOfFile-symbool (wat dat ook moge zijn)
een regelovergang staat.
-
Alleen voor de namen van de files
mag een array (of string) gebruikt worden;
voor het lezen
en verwerken van de tekst is slechts het huidige karakter en
enige kennis over de voorgaande karakters nodig — zie boven.
Alleen de headerfiles iostream en fstream
mogen gebruikt worden (en string
voor de filenamen; denk in dat geval aan het gebruik
van c_str; en climits voor INT_MAX).
Uit een file mag alleen met invoer.get (...) gelezen
worden, vergelijk Hoofdstuk 3.7 uit het dictaat,
gedeelte "aantekeningen bij de hoorcolleges".
Binnen de hoofdloop van het programma staat bij voorkeur maar
één keer een get-opdracht,
vergelijk het voorbeeldprogramma uit dit hoofdstuk
(daar staat twee keer get, één maal
vóór de loop, uiteraard).
Karakters mogen niet worden teruggezet in de
oorspronkelijke file.
Schrijf zelf functies die testen of een karakter een cijfer is, etcetera. Er mogen geen andere functies dan die
uit fstream gebruikt worden, en c_str.
-
Denk aan het infoblokje dat aan begin
op het scherm verschijnt. Gebruik enkele geschikte functies,
bijvoorbeeld voor infoblokje, inlezen gegevens van de gebruiker,
omkeren van een getal, Lychrel-test, en behandelen van een file
(zie de tips bij het vijfde werkcollege).
Globale variabelen zijn streng verboden.
Ruwe indicatie voor de lengte van het C++-programma: circa 250 regels.
Uiterste inleverdatum: maandag 14 oktober 2024, 18:00 uur.
De manier van inleveren (één exemplaar per koppel, dat —— ter herinnering — uit maximaal twee personen bestaat) is als volgt.
- Digitaal de C++-code inleveren via Brightspace > Course Tools > Assignments. Stuur geen executable's, LaTeX-files of PDF-files, lever alleen één C++-file digitaal in!
- Doe een print van het verslag in de doos bij kamer Gorlaeus BM.2.07.
De laatst voor de deadline ingeleverde versie wordt nagekeken.
Overal duidelijk datum en namen van de (maximaal twee) makers vermelden,
in het bijzonder als commentaar in de eerste regels van de C++-code.
Lees bij het
zesde werkcollege hoe het verslag
eruit moet zien en wat er in moet staan.
Te gebruiken compiler: als hij maar C++ vertaalt;
het programma moet in principe zowel op een Linux-machine
draaien.
Normering: verslag 1; layout 1; commentaar 1;
overzichtelijkheid/modulariteit 2;
werking 5.
Eventuele aanvullingen en verbeteringen: lees deze WWW-bladzijde:
www.liacs.leidenuniv.nl/~kosterswa/pm/op2pm.php.