Uppgifterna som är markerade med en och två stjärnor görs i mån av tid. Men försök hinna med dem!
Snabblänkar: Datorövning 1 2 3 4 5 6
Man kan göra datorövning 1 på det första övningstillfället, men räkna med att det kan krävas både förberedelsetid och ytterligare hemarbete om man ska hinna göra uppgifterna.
[Lösningsförslag till datorövning 1]
Ja, det skulle kunna heta Strängtest, men erfarenheten lär oss att även om det ska funka med ÅÄÖ i olika namn på datorer, så är det tyvärr inte alltid det verkligen gör det. Plötsligt får man något konstigt fel som efter flera timmars letande visar sig bero på att man hade ett svenskt tecken i ett filnamn. Så det kan vara en god idé att undvika svenska tecken, åtminstone i namn som slutanvändarna inte ser. (Och allra helst borde det kanske vara på engelska?) Samma sak gäller mellanslag. |
På kursens hemsida (eller direkt här) finns en instruktion om hur man startar Visual Studio 2010. och sen skapar och provkör ett enkelt C-program. Om man arbetar på en egen dator är det inte förbjudet att använda till exempel GCC under Linux. Här förutsätter vi dock Visual Studio 2010. |
När du skapar projektet, bläddra då och skapa en ny katalog M:\PCSA\Metod. Ditt projekt hamnar nu i katalogen M:\PCSA\Metod\Strangtest\. Ta fram Solution Explorer med View och addera den nya filen Strang.c till projektets Source Files. I denna fil ska du skriva funktionen strlangd, som tar en sträng som parameter och returnerar strängens aktuella längd. Använd inte den färdiga funktionen strlen! Spara filen och kompilera filen separat genom att i Solution Explorer markera filen Strang.c och med höger musknapp välja Compile. Addera sedan en ny fil Strangtest.c till Source Files och skriv där ett huvudprogram, som läser in en sträng på max 30 tecken och skriver ut strängens längd genom att anropa funktionen strlangd. Kompilera separat och tänk på att deklarationen (huvudet) för funktionen strlangd måste skrivas in före main. Länka ihop projektet med Project | Build och kör det med Debug | Start.
Koden i las_medlem bör kontrollera att medlemmens namn och telefonnummer verkligen får plats i fälten i posten. (Vad kan hända annars?)#define MAX_NAMN 30 #define MAX_TELEFON 20 struct Medlem { int medlemsnummer; char namn[MAX_NAMN + 1]; char telefon[MAX_TELEFON + 1]; }; typedef struct Medlem Medlem; void las_medlem(Medlem *mp); void skriv_medlem(Medlem *mp);
las_medlem returnerar ett heltal för att man ska se om läsningen nått slutet på filen. Returvärdet 1 betyder att det gick bra att läsa en medlem från filen, och returvärdet 0 betyder att det inte gick.int las_medlem_fil(FILE *tsin, Medlem *mp); void skriv_medlem_fil(FILE *tsut, Medlem *mp);
Koden i las_medlem_fil ska kontrollera att medlemmens namn och telefonnummer verkligen får plats i fälten i posten.
En medlem ska lagras som tre rader i filen, med medlemsnummer, namn och telefonnummer:
Filen 10-medlemmar.txt innehåller data om 10 medlemmar. Ändra huvudprogrammet Medlemstest.cpp så att det läser från den filen, mellanlagrar alla medlemmarna i en array, och till sist skriver en ny fil med alla medlemmar utom de som bor i riktnummerområde 0158.3 Viola-Christina Henriksson 0159-135914
(Tips: Man kan använda funktionen strncmp för att jämföra med början av en sträng.)
Programmet skapa-medlemsfil.cpp kan användas för att skapa filer med olika antal medlemmar.
[Lösningsförslag till datorövning 1]
Man kan göra datorövning 2 på det andra övningstillfället (tredje kursveckan), men räkna med att det kan krävas både förberedelsetid och ytterligare hemarbete om man ska hinna göra uppgifterna.
Under den tredje veckan av kursen bör man också försöka hinna med inlämningsuppgift 1.
[Lösningsförslag till datorövning 2]
#include <stdio.h> int main() { double medel; double spridning; double talarray[] = {2.3, 1.2, 3.4, 5.6, 4.5}; medel_och_spridning(talarray, 5, &medel, &spridning); printf("Medel = %.2f\n", medel); printf("Spridning = %.2f\n", spridning); return 0; }
och som läser in mätvärdesnummer (nr) och mätvärde (x) till dessa, samt länkar ihop dessa till en länkad lista med hjälp av next-pekarna. Inläsningen ska upprepas så länge det inlästa nr-värdet inte är 0. Då inläsningen avslutats, ska alla x-värdena skrivas ut, följt av deras medelvärde.struct Measure { int nr; double x; struct Measure *next; };
Städa upp den länkade listan innan programmet avslutas, genom att gå igenom listan och avallokera (med free) varje malloc-allokerad post.
Hur bör man provköra för att se om det blir någon skillnad i hastighet?
Blir det någon skillnad i hastighet? Om det inte blev det - vad skulle det kunna bero på?
[Lösningsförslag till datorövning 2]
Man kan göra datorövning 3 på det tredje övningstillfället (fjärde kursveckan), men räkna med att det kan krävas både förberedelsetid och ytterligare hemarbete om man ska hinna göra uppgifterna.
Under den fjärde veckan av kursen bör man också försöka hinna med inlämningsuppgift 2. Det är en teoriuppgift som inte behöver lösas vid datorn.
[Lösningsförslag till datorövning 3]
Det ska fortfarande finnas en deklarationsfil Medlem.h och en definitionsfil Medlem.cpp, men nu ska det vara en class i stället för en struct, med medlemsnummer, namn och telefon som privata medlemsvariabler, och funktionerna las_medlem och skriv_medlem som publika medlemsfunktioner.
(En riktig C++-programmerare skulle fnysa åt våra char-arrayer, vår användning av stdio-paketet, med mera, och föreslå att vi ändrade till mer C++-mässiga lösningar, som klassen std::string. Men i den här övningen behöver vi bara ändra så mycket som behövs för att göra en klass.)
Ändra huvudprogrammet Medlemstest.cpp så att det fungerar som förut, men med den nya medlemstypen.
(Om du gjort övning 1 E eller övning 1 F, där programmet läser från en fil, kan du utgå från det programmet i stället.)
(Tips: För att stoppa in heltal och flyttal i listorna kan man skicka med värden direkt till push_front och push_back, som i push_front(17.7). Med medlemmar behöver du först göra en variabel av typen Medlem och läsa in data till den med las-funktionen, och därefter kan du stoppa in den i listan.)
Skriv sen ut längden på listorna (fås med funktionen size). Använd lämpliga kombinationer av funktionerna pop_front, pop_back och clear för att tömma de tre listorna på element. Skriv sen ut längden på listorna igen, för att kontrollera att de verkligen är tomma.
Prova också vad som händer om man försöker ta bort för många element ur en lista!
Det finns en del inbyggd hjälp i Visual Studio, till exempel med IntelliSense, men man kan också använda den här referenssidan: http://www.cplusplus.com/reference/stl/list/. |
Gör ett C++-program som lagrar vanliga C-structar i en std::list.
Skapa en lista av typen std::list, lägg in lite data, och skriv ut dem genom att gå igenom listan med en iterator. Använd std::list:s egen iteratortyp.
Sen ska programmet fråga efter ett ytterligare ett tal, och tala om hur många gånger det förekommer i listan. Använd en iterator när du går igenom listan och letar efter förekomster.
Exempel: Om allihop är 1, 7, 9, 3, 9, 3, 2, 8 och förbjudna är 3, 1, 1, 1, så ska resultatet bli 2, 7, 8, 9, 9.
Tips: Det finns flera färdiga funktioner i std::list som kan underlätta!
Kom ihåg att det finns en del inbyggd hjälp i Visual Studio, till exempel med IntelliSense, men man kan också använda den här referenssidan: http://www.cplusplus.com/reference/stl/list/. |
Det finns några olika att välja på i föreläsningsanteckningarna, och här är en till av void*-varianten, generic_list, och en av typedef-varianten, twolist.
Du kan också göra en egen (se uppgiften nedan).
[Lösningsförslag till datorövning 3]
Använd modulen StackOfDoubles från föreläsning 7 (filer: StackOfDoubles.h, StackOfDoubles.cpp) för att hantera stacken.
Använd std::queue för att hantera kön.
Det finns en del inbyggd hjälp i Visual Studio, till exempel med IntelliSense, men man kan också använda den här referenssidan: http://www.cplusplus.com/reference/stl/queue/. |
Det anländer i genomsnitt en person var 25:e sekund, och det tar i genomsnitt 100 sekunder att betjäna en kund.
Kunderna numreras efter den ordning de anländer, och varje kund representeras av detta heltal. Simulera köerna med fyra stycken std::queue. Varje sekund händer följande:
[Lösningsförslag: mcdonalds.cpp]
Restaurangen har öppet 07-23 (16 timmar). Hur blir det om man simulerar hela dagen? Varierar det mellan olika körningar av programmet?
Miniräknaren använder en stack. Principen är att om man matar in ett tal, så placeras det på stacken, och om det kommer en operation (som +) så hämtas två tal från stacken, operationen utförs på dessa, och resultatet läggs tillbaka på stacken. Läs mer här.
Skriv en postfix-kalkylator, med hjälp av en stack som lagras i en std::stack. Användaren matar in rader, som antingen kan innehålla ett reellt tal eller en operator (+, -, * eller /). Efter varje utförd operation ska programmet skriva ut det värde som nu ligger överst på stacken. Om man försöker utföra en operation när det inte finns minst två tal på stacken, ska man få ett varningsmeddelande, och operationen ska inte utföras.
Det finns en del inbyggd hjälp i Visual Studio, till exempel med IntelliSense, men man kan också använda den här referenssidan: http://www.cplusplus.com/reference/stl/stack/. |
Ta till exempel följande program:
void h() { } void g() { h(); } void f() { g(); h(); } int main(void) { f(); g(); return 0; }
main startas, anropar f, som sen i sin tur anropar g, som anropar h, och så vidare. Om vi har ett spårbibliotek trace, kan vi inkludera filen trace.h, och lägga in anrop till enter och leave i alla funktioner:
#include "trace.h" void h() { enter("h"); leave(); } void g() { enter("g"); h(); leave(); } void f() { enter("f"); g(); h(); leave(); } int main(void) { enter("main"); f(); g(); leave(); return 0; } // main
Spårutskrifterna från en körning av programmet skulle kunna se ut så här:
Entering main Entering f Entering g Entering h Leaving h Leaving g Entering h Leaving h Leaving f Entering g Entering h Leaving h Leaving g Leaving main
Implementera spårbiblioteket trace genom att skriva filerna trace.h och trace.h. Ledtråd: Det behövs en stack, så att leave vet vad det är för funktion som lämnas. Glöm inte att indentera spårutskrifterna, så man ser hur djupt anropen har nästlats.
[Lösningsförslag: trace.h, trace.cpp]
VALTYP;LAN;NAMN_LAN;KOM;NAMN_KOM;KRETS;NAMN_KRETS;DISTRIKT;NAMN_DISTRIKT;PARTIBETECKNING;ANTAL K;03;Uppsala län;05;Håbo;00;Håbo kommun;0101;Håbo 1;Toppzi;1 K;03;Uppsala län;05;Håbo;00;Håbo kommun;0102;Håbo 2;HARRY POTTER;1 K;03;Uppsala län;05;Håbo;00;Håbo kommun;0102;Håbo 2;Piratpartiet;2 R;03;Uppsala län;05;Håbo;00;Håbo kommun;0102;Håbo 2;HARRY POTTER;1(och så vidare)
På filen handskrivna.txt finns de handskrivna rösterna till riksdagsvalet, men lite enklare formaterat och utan informationen om vilken valkrets rösterna kommer från. (Följande är inte den riktiga filen, utan ett exempel för att visa dataformatet.)
Talet i början av raden anger hur många röster med den partibeteckningen som avgavs i den valkretsen.
1 HARRY POTTER 2 Stoppa E4 väst 1 Harry Potter 1 Harry Potter 1 All makt åt kungen 1 Fartguppsförbjudarpartiet 2 All makt åt kungen 1 ETT GOTT PARTI
Vi antar att för rösterna ska räknas till samma parti så måste namnen vara exakt likadana (dvs strcmp ska tycka att de är lika), så till exempel räknas HARRY POTTER och Harry Potter som två olika partier. Med dessa exempeldata har partiet All makt åt kungen fått 3 röster, och vinner alltså valet bland de handskrivna rösterna.
Använd en länkad lista för att lagra partierna. Använd inte någon färdig listtyp som std::list eller liknande, utan bygg själv upp den länkade listan med hjälp av poster ("structar") och pekare. Men dela gärna upp programmet så att listan hanteras som en abstrakt datatyp, eller i alla fall med särskilda funktioner.
Tips: Läs filen rad för rad. För varje rad, sök i den länkade listan efter det partiet. Om partiet redan fanns i listan, lägg till det antal röster som stod på raden. Om det inte redan fanns i listan, stoppa in en ny post i listan, med den partibeteckningen och det antal röster som stod på raden. När filen är slut, gå igenom hela listan för att hitta det parti som har flest röster. Skriv ut det partiet.
[Lösningsförslag: val-lista.cpp]
Kör programmet i Debuggern och studera hur n varierar.1 2 ..... n
Använd inte någon färdig trädtyp, utan bygg själv upp trädet med hjälp av poster ("structar") och pekare.
Använd inte någon färdig hashtabelltyp, utan bygg själv upp hashtabellen med hjälp av poster ("structar"), pekare och en array.
[Lösningsförslag: val-hashtabell.cpp]
[Lösningsförslag till datorövning 6]
[Lösningsförslag till datorövning 6]