Wiki

Clone wiki

CPL01 / extra_oefeningen_2

Extra oefeningen 2

Deze pagina bevat extra oefenopgaven met uitwerkingen. Deze oefeningen zijn een vervolg op extra oefeningen 1. In deze opgaven wordt niet alleen gebruik gemaakt van onthouden, rekenen, beslissen, herhalen, in- en output, maar ook van functies en array's.

Bij elke opdracht staat vermeld welke C-features in de uitwerking worden gebruikt. Bedenk wel dat er altijd vele oplossingen mogelijk zijn.

Alle onderstaande programma's zijn geschreven in C99 en bij het compileren moeten de volgende opties worden gebruikt: -std=c99 -pedantic -Wall.

Perfecte getallen

Een perfect getal is een getal dat gelijk is aan de som van al zijn eigen delers (behalve zichzelf). Bijvoorbeeld: 28 is (slechts) deelbaar door 14, 7, 4, 2 en 1 en 14 + 7 + 4 + 2 + 1 = 28, dus 28 is een perfect getal. Zie eventueel voor verdere uitleg https://nl.wikipedia.org/wiki/Perfect_getal. Het is nog niet bekend hoeveel perfecte getallen er zijn. Er zijn slechts 5 perfecte getallen die in een variabele van het type int passen, namelijk 6, 28, 496, 8128 en 33550336. Er zijn veel meer perfecte getallen bekend maar die zijn allemaal groter van 2^31 (twee tot de macht eenendertig) en die passen dus niet in een variabele van het type int.

Schrijf een functie isPerfect die bepaalt of een getal van het type int perfect is. Als dit zo is moet de functie de waarde 1 teruggeven en als dit niet zo is moet de functie de waarde 0 teruggeven. Het is niet nodig om rekenkundig te bepalen of het getal perfect is. Je kunt het als argument meegegeven getal simpel vergelijken met de 5 perfecte getallen die in een variabele van het type int passen.

Gebruik het onderstaande programma om de functie isPerfect te testen.

#!C
int main(void)
{
    // testprogramma voor isPerfect
    if (
        isPerfect(0) == 0 &&
        isPerfect(1) == 0 &&
        isPerfect(5) == 0 &&
        isPerfect(6) == 1 &&
        isPerfect(7) == 0 &&
        isPerfect(28) == 1 &&
        isPerfect(101) == 0 &&
        isPerfect(496) == 1 &&
        isPerfect(8128) == 1 &&
        isPerfect(33550336) == 1 &&
        isPerfect(-33550336) == 0
    )
    {
        printf("Test geslaagd.\n");
    }
    else
    {
        printf("Test NIET geslaagd!\n");
    }
}
In de uitwerking worden de volgende C-features gebruikt: int, vergelijken, booleaanse algebra en functie.

Uitwerking: isPerfect.c.

Hoewel dit een eenvoudige functie is zijn er toch heel veel mogelijke oplossingen, zie 21 goede antwoorden op een eenvoudige programmeervraag.

Minimum

Het bepalen van een minimum uit een reeks getallen wordt vaak gebruikt. Denk hierbij bijvoorbeeld aan het bepalen van de minimale temperatuur van de dag.

Schrijf en implementeer een functie genaamd min2, die het minimum teruggeeft van twee gehele getallen.

Schrijf en implementeer een functie genaamd min5, die het minimum teruggeeft van vijf gehele getallen. Natuurlijk kan er een functie worden geschreven die via meerdere vergelijkingen het minimum van vijf getallen bepaalt maar dat is niet nodig. Je kunt het minimum van meerdere getallen namelijk óók bepalen met behulp van de min2-functie. Zo kun je bijvoorbeeld het minimum van drie getallen bepalen door aan één van de parameters van min2 het minimum van twee getallen door te geven! De min2-functie wordt dus gebruikt als argument in een (andere) min2-functie. Implementeer een min5-functie die alleen maar min2-functies gebruikt.

Gebruik het onderstaande programma om de functie min5 te testen.

#!C
int main(void)
{
    // testprogramma voor min5
    if (
        min5(10, 11, 12, 13, 14) == 10 &&
        min5(11, 10, 12, 13, 14) == 10 &&
        min5(11, 12, 10, 13, 14) == 10 &&
        min5(11, 12, 13, 10, 14) == 10 &&
        min5(11, 12, 13, 14, 10) == 10 &&
        min5(10, 10, 10, 10, 10) == 10 &&
        min5(10, 10, -10, 10, 10) == -10
    )
    {
        printf("Test geslaagd.\n");
    }
    else
    {
        printf("Test NIET geslaagd!\n");
        printf("min5(10, 11, 12, 13, 14) => %d\n", min5(10, 11, 12, 13, 14));
        printf("min5(11, 10, 12, 13, 14) => %d\n", min5(11, 10, 12, 13, 14));
        printf("min5(11, 12, 10, 13, 14) => %d\n", min5(11, 12, 10, 13, 14));
        printf("min5(11, 12, 13, 10, 14) => %d\n", min5(11, 12, 13, 10, 14));
        printf("min5(11, 12, 13, 14, 10) => %d\n", min5(11, 12, 13, 14, 10));
        printf("min5(10, 10, 10, 10, 10) => %d\n", min5(10, 10, 10, 10, 10));
        printf("min5(10, 10, -10, 10, 10) => %d\n", min5(10, 10, -10, 10, 10));
    }
}

In de uitwerking worden de volgende C-features gebruikt: int, if, else, return en functies.

Uitwerking: min5.c.

Binair afdrukken van een integer

In standaard C kunnen we een integer in het decimale talstelsel afdrukken door %d te gebruiken in een printf-functieaanroep. Het is ook mogelijk om met behulp van de standaard printf-functie een integer in het hexadecimale talstelsel af te drukken. Zoek zelf uit hoe je dit moet doen op http://en.cppreference.com/w/c/io/fprintf. Schrijf een C-programma waarmee de waarden 0 t/m 255 in het hexadecimale stelsel worden afgedrukt (16 getallen per regel).

De gewenste uitvoer is:

#!None
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF

In de uitwerking worden de volgende C-features gebruikt: int, for en printf.

Uitwerking: hextabel.c.

Er is echter geen standaard manier om een integer in het binaire talstelsel af te drukken. Bij sommige implementaties van printf is dit mogelijk door %b te gebruiken maar in standaard C99 is dit niet toegestaan.

Test of het in Code::Blocks mogelijk is om een integer in het binaire talstelsel af te drukken met printf("%d (decimaal) = %b (binair)", 189, 189);.

Uitwerking: printf_bin.c.

De uitvoer van dit programma is:

#!None
189 (decimaal) = %b (binair)

We zullen dus zelf een functie moeten maken om een integer in het binaire talstelsel af te drukken.

Schrijf een functie print_binary waarmee de als argument meegegeven integer tussen 0 en 255 (inclusief) in het binaire talstelsel wordt afgedrukt.

Hint: om te kijken of het hoogste bit (bit 7; we nummeren van 7 t/m 0) een 0 of 1 is, kun je het getal vergelijken met 128, de hoogste macht in een 8-bit binair getal. Is het getal 128 of groter, dan is het meest significante bit 1, anders is het 0. Als bit 7 de waarde 1 heeft, moet je 128 van het getal aftrekken. Vervolgens kun je op vergelijkbare wijze de overige bits, van 6 tot 0, een voor een afgaan. Door gebruik van een for-lus kun je de oplossing efficiënt programmeren.

Gebruik deze functie vervolgens om de waarden 0 t/m 255 in het binaire talstelsel af te drukken (8 getallen per regel).

De gewenste uitvoer is:

#!None
00000000 00000001 00000010 00000011 00000100 00000101 00000110 00000111
00001000 00001001 00001010 00001011 00001100 00001101 00001110 00001111
00010000 00010001 00010010 00010011 00010100 00010101 00010110 00010111
00011000 00011001 00011010 00011011 00011100 00011101 00011110 00011111
00100000 00100001 00100010 00100011 00100100 00100101 00100110 00100111
00101000 00101001 00101010 00101011 00101100 00101101 00101110 00101111
00110000 00110001 00110010 00110011 00110100 00110101 00110110 00110111
00111000 00111001 00111010 00111011 00111100 00111101 00111110 00111111
01000000 01000001 01000010 01000011 01000100 01000101 01000110 01000111
01001000 01001001 01001010 01001011 01001100 01001101 01001110 01001111
01010000 01010001 01010010 01010011 01010100 01010101 01010110 01010111
01011000 01011001 01011010 01011011 01011100 01011101 01011110 01011111
01100000 01100001 01100010 01100011 01100100 01100101 01100110 01100111
01101000 01101001 01101010 01101011 01101100 01101101 01101110 01101111
01110000 01110001 01110010 01110011 01110100 01110101 01110110 01110111
01111000 01111001 01111010 01111011 01111100 01111101 01111110 01111111
10000000 10000001 10000010 10000011 10000100 10000101 10000110 10000111
10001000 10001001 10001010 10001011 10001100 10001101 10001110 10001111
10010000 10010001 10010010 10010011 10010100 10010101 10010110 10010111
10011000 10011001 10011010 10011011 10011100 10011101 10011110 10011111
10100000 10100001 10100010 10100011 10100100 10100101 10100110 10100111
10101000 10101001 10101010 10101011 10101100 10101101 10101110 10101111
10110000 10110001 10110010 10110011 10110100 10110101 10110110 10110111
10111000 10111001 10111010 10111011 10111100 10111101 10111110 10111111
11000000 11000001 11000010 11000011 11000100 11000101 11000110 11000111
11001000 11001001 11001010 11001011 11001100 11001101 11001110 11001111
11010000 11010001 11010010 11010011 11010100 11010101 11010110 11010111
11011000 11011001 11011010 11011011 11011100 11011101 11011110 11011111
11100000 11100001 11100010 11100011 11100100 11100101 11100110 11100111
11101000 11101001 11101010 11101011 11101100 11101101 11101110 11101111
11110000 11110001 11110010 11110011 11110100 11110101 11110110 11110111
11111000 11111001 11111010 11111011 11111100 11111101 11111110 11111111

In de uitwerking worden de volgende C-features gebruikt: int, if, else, for, printf en functie.

Uitwerking: print_binary.c.

##Getallen uitschrijven Het Genootschap Onze Taal geeft als richtlijn om getallen tot twintig in lopende tekst als woord te schrijven en niet als getal, zie https://onzetaal.nl/taaladvies/advies/getallen-in-letters-of-cijfers. Met behulp van de onderstaande functies kun je getallen automatisch omzetten in woorden.

Getallen van 1 tot 10 uitschrijven

Schrijf een functie schrijfTot10 waarmee een als argument meegegeven getal vanaf 0 tot en met 9 als woord wordt uitgeschreven. Test deze functie met alle geldige en enkele ongeldig argumenten.

De aanroep schrijfTot10(8) moet dus als gevolg hebben dat het woord acht op het scherm wordt afgedrukt.

In de uitwerking worden de volgende C-features gebruikt: int, switch, for, printf en functie.

Uitwerking: schrijfTot10.c.

Getallen van 1 tot 100 uitschrijven

Schrijf een functie schrijfTot100 waarmee een als argument meegegeven getal vanaf 0 tot en met 99 als woord wordt uitgeschreven. Test deze functie met alle geldige en enkele ongeldig argumenten.

De aanroep schrijfTot100(99) moet dus als gevolg hebben dat het woord negenennegentig op het scherm wordt afgedrukt.

Tip: Je kunt slim (2x) gebruik maken van de functie schrijfTot10 die je eerder hebt gemaakt. Bedenk dat je de eenheden van een getal kunt vinden met de formule getal % 10. De tientallen voor een getal kleiner dan 100 kun je vinden met de formule getal / 10.

In de uitwerking worden de volgende C-features gebruikt: int, switch, for, printf en functies.

Uitwerking: schrijfTot100.c.

Getallen van 1 tot 1000 uitschrijven

Schrijf een functie schrijfTot1000 waarmee een als argument meegegeven getal vanaf 0 tot en met 999 als woord wordt uitgeschreven. Test deze functie met alle geldige en enkele ongeldig argumenten.

De aanroep schrijfTot1000(713) moet dus als gevolg hebben dat het woord zevenhonderddertien op het scherm wordt afgedrukt.

Tip: Je kunt slim gebruik maken van de functies schrijfTot10 en schrijfTot10 die je eerder hebt gemaakt.

In de uitwerking worden de volgende C-features gebruikt: int, switch, for, printf en functies.

Uitwerking: schrijfTot1000.c.

abc-formule

De abc-formule wordt, zoals je weet, gebruikt voor het oplossen van kwadratische vergelijkingen. Schrijf een C-functie genaamd abc die de reële wortels van de vergelijking ax^2+bx+c=0 bepaald. De functie moet het aantal wortels (0, 1 of 2) als returnwaarde teruggeven. De waarden van a, b en c moeten via call by value aan de functie worden doorgegeven en de waarden van de wortels moeten, als ze er zijn, via call by reference worden teruggegeven.

Gebruik het onderstaande programma om de functie abc te testen.

#!C
int main(void)
{
    double w1, w2;
    if (
        abc(2, 5, -7, &w1, &w2) != 2 && w1 - -3.5 > 10e-9 && w2 - 1 > 10e-9 ||
        abc(9, 30, 25, &w1, &w2) != 1 && w1 - -5/3 > 10e-9 ||
        abc(9, -15, 25, &w1, &w2) != 0
    )
    {
        printf("Test NIET geslaagd!\n");
    }
    else
    {
        printf("Test geslaagd\n");
    }
    return 0;
}

In de uitwerking worden de volgende C-features gebruikt: int, double, if, else, return, call by value en call by reference.

Uitwerking: abc.c.

Omdraaien

Schrijf een functie reverse waarmee de inhoud van een rij gehele getallen omgedraaid kan worden. Als de rij de getallen 0, 1, 2 en 3 bevat dan moet de rij na afloop van de functie de getallen 3, 2, 1 en 0 bevatten.

Gebruik het onderstaande programma om de functie reverse te testen.

#!C
int main(void)
{
    int a[] = {1, 2, 3, 4};
    reverse(a, sizeof a / sizeof a[0]);
    if (a[0] != 4 || a[1] != 3 || a[2] != 2 || a[3] != 1)
    {
        printf("Test1 NIET geslaagd!\n");
    }
    else
    {
        reverse(a, 1);
        if (a[0] != 4 || a[1] != 3 || a[2] != 2 || a[3] != 1)
        {
            printf("Test2 NIET geslaagd!\n");
        }
        else
        {
            reverse(a, 3);
            if (a[0] != 2 || a[1] != 3 || a[2] != 4 || a[3] != 1)
            {
                printf("Test3 NIET geslaagd!\n");
            }
            else
            {
                printf("Alle testen geslaagd.\n");
            }
        }
    }
    return 0;
}

In de uitwerking worden de volgende C-features gebruikt: int, array, while, return, call by value en call by reference.

Uitwerking: reverse1.c.

Door gebruik te maken van de incremenet en de decrement operatoren kan de bovenstaande oplossing worden verkort: reverse2.c.

Door gebruik te maken van de parameter n is nog slecht 1 variabele nodig: reverse3.c.

Het is zelf mogelijk om een oplossing te bedenken die helemaal geen lokale variabelen gebruikt: reverse4.c. In deze oplossing wordt gebruik gemaakt van het feit dat de naam van een array (in dit geval de parameter a) hetzelfde is als een pointer naar het eerste element van de array (&a[0]). Bovendien wordt gebruik gemaakt van pointer arithmetic: a + n is hetzelfde als &a[n].

Let op! De laatste twee oplossingen zijn erg getruct. Je schrijft een programma niet alleen om de computer te vertellen wat hij moet doen, maar ook om de programmeurs die het programma later moeten aanpassen, uitbreiden of hergebruiken te vertellen hoe je programma werkt. De eerste twee oplossingen zijn dus veel beter dan de laatste twee!

Onvoldoendes

Schrijf een functie aantal_onvoldoendes waarmee het aantal onvoldoendes in een array met toetsresultaten kan worden berekend. Een toetsresultaat is een floatingpoint getal (double) met 1 cijfer achter de decimale punt. Het maximale toetsresultaat is 10.0 en het minimale toetsresultaat is 1.0. Een toetsresultaat lager dan 5.5 telt als een onvoldoende. Een toetsresultaat hoger dan of gelijk aan 5.5 telt als voldoende. De array en het aantal toetsresultaten in de array moeten via parameters aan de functie worden doorgeven. Het aantal onvoldoendes moet via een return statement worden teruggeven.

Gebruik het onderstaande programma om de functie aantal_onvoldoendes te testen.

#!C
int main(void)
{
    double test_resultaten[] = {1.4, 6.4, 5.5, 9.4, 5.4, 7.8};

    if (
        aantal_onvoldoendes(test_resultaten, 6) == 2 &&
        aantal_onvoldoendes(test_resultaten, 2) == 1 &&
        aantal_onvoldoendes(test_resultaten, 1) == 1 &&
        aantal_onvoldoendes(test_resultaten, 0) == 0
    )
    {
        printf("Test geslaagd.\n");
    }
    else
    {
        printf("Test NIET geslaagd!\n");
    }
    return 0;
}

In de uitwerking worden de volgende C-features gebruikt: int, double, array, for, if, return en functie.

Uitwerking: aantal_onvoldoendes.c.

Uniek

Schrijf een functie int uniek(int a[], int aantal_a) die alle getallen die meer dan één keer in de array a voorkomen verwijderd uit deze array. De parameter aantal_a bevat het aantal elementen in de array a. De functie moet het aantal unieke getallen in array a teruggeven als return waarde.

Gebruik het onderstaande programma om de functie uniek te testen.

#!C
int main(void)
{
    int rij1[] = { 23, 3, 56, 3, 23, 5, 12, 6, 3, 18, 7, 10, 56, 11 };
    int rij2[] = { 3, 3, 3, 3 };
    int aantal_uniek = uniek(rij1, sizeof rij1 / sizeof rij1[0]);
    for (int i = 0; i < aantal_uniek; i++)
    {
        printf("%d ", rij1[i]);
    }
    printf("\n");
    aantal_uniek = uniek(rij2, sizeof rij2 / sizeof rij2[0]);
    for (int i = 0; i < aantal_uniek; i++)
    {
        printf("%d ", rij2[i]);
    }
    printf("\n");

    // flauw maar moet wel werken
    aantal_uniek = uniek(rij2, 0);
    for (int i = 0; i < aantal_uniek; i++)
    {
        printf("%d ", rij2[i]);
    }
    printf("\n");

    return 0;
}

De gewenste uitvoer van het bovenstaande programma is:

#!None
23 3 56 5 12 6 18 7 10 11
3

In de uitwerking worden de volgende C-features gebruikt: int, array, for, break, if, return en functie.

Uitwerking: uniek.c.

8 bits binair naar integer

Schrijf een functie bin2dec waarmee een 8 bits unsigned getal in binaire notatie omgezet kan worden naar een getal in decimale notatie. Het getal in binaire notatie is opgeslagen in een array van 8 integers. Elk element in de array is gevuld met een het getal 0 of met het getal 1. Het most significant bit (MSB) is opgeslagen in het element met de index 0.

Gebruik het onderstaande programma om de functie bin2dec te testen.

#!C
int main(void)
{
    int b1[8] = {0, 0, 0, 0, 1, 0, 1, 1};
    int b2[8] = {1, 0, 1, 1, 1, 1, 0, 1};
    if (bin2dec(b1) == 11)
    {
        printf("Test 1 is geslaagd.\n");
    }
    else
    {
        printf("Test 1 is NIET geslaagd!\n");
    }
    if (bin2dec(b2) == 189)
    {
        printf("Test 2 is geslaagd.\n");
    }
    else
    {
        printf("Test 2 is NIET geslaagd!\n");
    }
    return 0;
}

In de uitwerking worden de volgende C-features gebruikt: int, array, for, return en functie.

Uitwerking: bin2dec.c.

Magisch vierkant

Een magisch vierkant van de orde 8 is een vierkant raster van 8 bij 8 hokjes waarin de getallen 1 t/m 64 zodanig zijn ingevuld dat de som van elke kolom, de som van elke rij en de som van elk van de 2 diagonalen 260 is. Zie eventueel https://nl.wikipedia.org/wiki/Magisch_vierkant.

Een programmeur heeft vijf functiedeclaraties geschreven die moeten helpen om te bepalen of een vierkant van 8 x 8 magisch is.

#!C
int checkGetallen(int vierkant[8][8]);
int checkSomRijen(int vierkant[8][8]);
int checkSomKolommen(int vierkant[8][8]);
int checkSomDiagonalen(int vierkant[8][8]);
int isMagisch(int vierkant[8][8]);

De functie checkGetallen geeft 1 terug als de getallen 1 t/m 64 allemaal exact 1x voorkomen in de parameter vierkant. Als dit niet zo is, dan geeft de functie checkGetallen 0 terug. De functie checkSomRijen geeft 1 terug als de som van elke rij van de parameter vierkant 260 is. Als dit niet zo is, dan geeft de functie checkSomRijen 0 terug. De functie checkSomKolommen geeft 1 terug als de som van elke kolom van de parameter vierkant 260 is. Als dit niet zo is, dan geeft de functie checkSomKolommen 0 terug. De functie checkSomDiagonalen geeft 1 terug als de som van elk van de twee diagonalen van de parameter vierkant 260 is. Als dit niet zo is, dan geeft de functie checkSomDiagonalen 0 terug.

De functie isMagisch geeft 1 terug als de parameter vierkant een magisch vierkant is. Als dit niet zo is, dan geeft de functie isMagisch 0 terug. Deze functie maakt gebruik van de functies: checkGetallen, checkSomRijen, checkSomKolommen en checkSomDiagonalen.

Schrijf de implementatie (de definitie) van de vijf functies met de bovenstaande functiedeclaratie en werking.

Gebruik het onderstaande programma om de functie isMagisch te testen.

#!C
int main(void)
{
    int test1[8][8] =
    {
        { 8, 58, 59,  5,  4, 62, 63,  1},
        {49, 15, 14, 52, 53, 11, 10, 56},
        {41, 23, 22, 44, 45, 19, 18, 48},
        {32, 34, 35, 29, 28, 38, 39, 25},
        {40, 26, 27, 37, 36, 30, 31, 33},
        {17, 47, 46, 20, 21, 43, 42, 24},
        { 9, 55, 54, 12, 13, 51, 50, 16},
        {64,  2,  3, 61, 60,  6,  7, 57}
    };

    int test2[8][8] =
    {
        { 8, 58, 59,  5,  4, 62, 63,  1},
        {49, 15, 14, 52, 53, 11, 10, 56},
        {41, 23, 22, 44, 45, 19, 18, 48},
        {32, 34, 35, 29, 28, 38, 39, 25},
        {40, 26, 27, 37, 36, 30, 31, 33},
        {17, 47, 46, 20, 21, 43, 42, 24},
        { 9, 55, 54, 12, 13, 51, 50, 16},
        {63,  2,  3, 61, 60,  6,  7, 57}
    };

    if (isMagisch(test1) == 1 && isMagisch(test2) == 0)
    {
        printf("Test geslaagd.");
    }
    else
    {
        printf("Test NIET geslaagd!");
    }

    return 0;
}

In de uitwerking worden de volgende C-features gebruikt: int, 2-dimensionale array, for, if, return en functies.

Uitwerking: magisch_vierkant.c.

Vervang spaties door underscores

Schrijf een functie genaamd underscore die in als argument meegegeven C-string alle spaties () vervangen door een laag streepje (_).

Gebruik het onderstaande programma om de functie underscore te testen.

#!C
int main(void)
{
    char string[] = "Wat is hier aan de hand?";
    underscore(string);
    printf("%s\n", string);
    return 0;
}

De uitvoer van het bovenstaande programma moet dus zijn:

#!None
Wat_is_hier_aan_de_hand?

Tip: een C-string wordt altijd afgesloten met een NUL karakter (\0).

In de uitwerking worden de volgende C-features gebruikt: int, C-string, for, if, return en functie.

Uitwerking: underscore.c.

Spiegelwoord

Schrijf een functie genaamd is_spiegelwoord die bepaalt of een C-string een spiegelwoord is. Wij definiëren een spiegelwoord als een woord dat alleen uit kleine letters bestaat en dat van links naar rechts gelezen hetzelfde is als van rechts naar links gelezen. Voorbeelden van spiegelwoorden in de Nederlandse taal zijn lepel, droomoord, negen, lol, soos en meetsysteem. Voorbeelden van woorden die geen spiegelwoorden zijn: Lol (omdat er een hoofletter in voorkomt) en 73neen37 (omdat er cijfers in voorkomen). Het prototype van de functie is als volgt:

#!C
int is_spiegelwoord(char woord[]);

De functie moet de waarde 1 teruggeven als de meegegeven C-string een spiegelwoord is en moet de waarde 0 teruggeven als de meegegeven C-string geen spiegelwoord is.

Tip 1: Je kunt de functie strlen die gedeclareerd is in string.h gebruiken om het aantal karakters van het als argument meegegeven woord te vinden.

Tip 2: Je kunt de functie islower die gedeclareerd is in ctype.h gebruiken om te controleren of een karakter een kleine letter is.

Tip 3: Je hoeft niet te controleren of het woord voorkomt in de Nederlandse taal. Het woord acjsheehsjca is dus een spiegelwoord.

Gebruik het onderstaande programma om de functie is_spiegelwoord te testen.

#!C
int main(void)
{
    if (
        is_spiegelwoord("meetsysteem")
        && is_spiegelwoord("soos")
        && !is_spiegelwoord("Lol")
        && !is_spiegelwoord("73neen37")
    )
    {
        printf("Test geslaagd.\n");
    }
    else
    {
        printf("Test NIET geslaagd!\n");
    }
    return 0;
}

In de uitwerking worden de volgende C-features gebruikt: int, C-string, while, if, else, return, strlen, islower en functie.

Uitwerking: is_spiegelwoord.c.

CamelCase

Sommige C programmeurs schrijven een variabelenaam die bestaat uit meerdere woorden als volgt: dit_is_een_voorbeeld. De verschillende woorden waaruit de variabelenaam bestaat worden gescheiden door een laag streepje (het _-teken). Ander programmeurs schrijven een variabelenaam die bestaat uit meerdere woorden als volgt: ditIsEenVoorbeeld. De scheiding tussen de verschillende woorden wordt in dit geval met hoofdletters aangegeven. Deze laatste methode wordt 'CamelCase' genoemd.

Schrijf een functie genaamd toCamelCase die een variabelenaam is opgeslagen waarin de verschillende woorden met lage steepjes zijn gescheiden omzet naar de overeenkomstige variabelenaam in CamelCase. De variabelenaam is opgeslagen in een C-string.

Tip: Je kunt de functie toupper die gedeclareerd is in ctype.h gebruiken om een kleine letter om te zetten naar een hoofdletter.

Gebruik het onderstaande programma om de functie toCamelCase te testen.

#!C
int main(void)
{
    char voorbeeld1[] = "dit_is_een_voorbeeld";
    char voorbeeld2[] = "en_dit_ook";
    char voorbeeld3[] = "all_4_one";
    char voorbeeld4[] = "laatste_";
    char voorbeeld5[] = "_eerste";
    toCamelCase(voorbeeld1);
    toCamelCase(voorbeeld2);
    toCamelCase(voorbeeld3);
    toCamelCase(voorbeeld4);
    toCamelCase(voorbeeld5);
    printf("%s %s %s %s %s\n", voorbeeld1, voorbeeld2, voorbeeld3, voorbeeld4, voorbeeld5);
    return 0;
}

De verwachte uitvoer van bovenstaand programma is:

#!None
ditIsEenVoorbeeld enDitOok all4One laatste Eerste

In de uitwerking worden de volgende C-features gebruikt: int, C-string, while, if, else, return, toupper en functie.

Uitwerking: camel_case.c.

Efficiëntere uniek

De bovenstaande funtie uniek is niet erg efficiënt omdat voor elk getal in de array, de hele array van voren af aan doorlopen moet worden (tot aan het betreffende getal) om te bepalen of dit getal uniek is. Het is efficiënter om de array eerst te sorteren en daarna de dubbele getallen (die dan allemaal achter elkaar staan) te verwijderen.

Geen een implementatie van de functie uniek die werkt volgens het hierboven beschreven principe. Maak gebruik van de standaard functie qsort. Zie http://en.cppreference.com/w/c/algorithm/qsort. De functie qsort is enigszins gecompliceerd zodat deze functie met verschillende datatypen gebruikt kan worden. Er wordt gebruik gemaakt van zogenoemde void-pointers. Zo'n pointer kan naar elk gewenst type wijzen, maar voordat de waarde waar de pointer naar wijst gelezen kan worden, moet de pointer eerst naar het juiste type gecast worden.

De vierde parameter van qsort is een pointer naar een functie met als prototype: int comp(const void *a, const void *b). Deze functie bepaald hoe de gegevens gesorteerd worden. Het keyword const betekent dat de pointer alleen gebruikt mag worden om een waarde uit het geheugen te lezen (en niet om te schrijven).

Maak gebruik van het voorbeeld dat is gegeven op http://en.cppreference.com/w/c/algorithm/qsort!

Gebruik het onderstaande programma om de functie uniek te testen.

#!C
int main(void)
{
    int rij1[] = { 23, 3, 56, 3, 23, 5, 12, 6, 3, 18, 7, 10, 56, 11 };
    int rij2[] = { 3, 3, 3, 3 };
    int aantal_uniek = uniek(rij1, sizeof rij1 / sizeof rij1[0]);
    for (int i = 0; i < aantal_uniek; i++)
    {
        printf("%d ", rij1[i]);
    }
    printf("\n");
    aantal_uniek = uniek(rij2, sizeof rij2 / sizeof rij2[0]);
    for (int i = 0; i < aantal_uniek; i++)
    {
        printf("%d ", rij2[i]);
    }
    printf("\n");

    // flauw maar moet wel werken
    aantal_uniek = uniek(rij2, 0);
    for (int i = 0; i < aantal_uniek; i++)
    {
        printf("%d ", rij2[i]);
    }
    printf("\n");

    return 0;
}

De gewenste uitvoer van het bovenstaande programma is:

#!None
3 5 6 7 10 11 12 18 23 56
3

In de uitwerking worden de volgende C-features gebruikt: int, array, for, if, qsort, sizeof, return en functie.

Uitwerking: uniek_met_sort.c.

Updated