Programmering C: Lösningar till tentamen 2014-03-01

Observera att detta är förslag på lösningar. Det kan finnas andra lösningar som också är korrekta, och det kan hända att en del av lösningarna är mer omfattande än vad som krävs för full poäng på uppgiften. En del av lösningarna är kanske inte fullständiga, utan hänvisar bara till var man kan läsa svaret. Dessutom har det inträffat i världshistorien att lärare skrivit fel i lösningsförslagen.

Uppgift 1 (1 p)

Vilka värden har följande C-uttryck?

a) 0

b) 1

c) 2

d) 3

Uppgift 2 (2 p)

a = 3, b = 2, c = 8, d = 3

Uppgift 3 (2 p)

int slumptal(int max) {
    return rand() % max;
}

Anmärkning: Uppgiften innehåller en motsägelse. Det står att funktionen ska returnera ett slumptal mellan 0 och max, inklusive gränserna, men sen står det att anropet slumptal(4) ska returnera något av talen 0, 1, 2 och 3. Den här lösningen returnerar ett slumptal mellan 0 och max, inklusive 0 men inte inklusive max.

Uppgift 4 (3 p)

Ett alternativ:
int main(void) {
    int tal1, tal2, tal3;
    int slump_012;

    srand(time(NULL));

    printf("Skriv tre heltal: ");
    scanf("%d", &tal1);
    scanf("%d", &tal2);
    scanf("%d", &tal3);

    slump_012 = slumptal(3);
    if (slump_012 == 0)
        printf("%d\n", tal1);
    else if (slump_012 == 1)
        printf("%d\n", tal2);
    else
        printf("%d\n", tal3);
    
    return 0;
}
Ett annat alternativ:
int main(void) {
    int tal[3];
    int i;

    srand(time(NULL));

    printf("Skriv tre heltal: ");
    for (i = 0; i < 3; ++i)
        scanf("%d", &tal[i]);

    printf("%d\n", tal[slumptal(3)]);
    
    return 0;
}

Uppgift 5 (5 p)

a) 5
b) 5
c) 4
d) 5
e) 12
f) 6
g) 427
h) 6
i) 1
j) 4

Uppgift 6 (5 p)

a)
void namnbyte(struct President *pp) {
    char temp[MAXNAMN + 1];
    strcpy(temp, pp->fornamn);
    strcpy(pp->fornamn, pp->efternamn);
    strcpy(pp->efternamn, temp);
}
b)
int main(void) {
    struct President president = { "John", "F", "Kennedy" };
    namnbyte(&president);
    printf("Efternamn: %s\n", president.efternamn);

    return 0;
}

Uppgift 7 (3 p)

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int talen[5];
    int i;

    printf("Mata in 5 heltal:\n");

    for (i = 0; i < 5; ++i)
        scanf("%d", &talen[i]);

    printf("Heltalen:\n");

    for (i = 4; i >= 0; --i)
        printf("%d\n", talen[i]);

    return 0;
}

Uppgift 8 (3 p)

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    double x, expected, result;
    int i, n;

    printf("Talet x: ");
    scanf("%lf", &x);

    printf("Antalet n: ");
    scanf("%d", &n);

    printf("Förväntat resultat: ");
    scanf("%lf", &expected);

    result = 0;
    for (i = 0; i < n; ++i)
        result += x;

    printf("Beräknat resultat: %f\n", result);
    printf("Skillnad: %f\n", result - expected);

    return 0;
}

Uppgift 9 (5 p)

#include <stdio.h>
#include <string.h>

int main(void) {
    char rad[100];
    int antal_ord = 0;
    int antal_a_ord = 0;

    printf("Skriv ett ord per rad. Avsluta med \"klar\", \"sluta\" eller \"avbryt\".\n");
    gets(rad); // Jaja, vi vet.
    while (strcmp(rad, "klar") != 0 && strcmp(rad, "sluta") != 0 && strcmp(rad, "avbryt") != 0) {
        ++antal_ord;
        if (rad[0] == 'a' || rad[0] == 'A')
            ++antal_a_ord;
        gets(rad); // Jaja, vi vet.
    }
    ++antal_ord; // För avslutningsordet

    printf("Totalt antal ord: %d\n", antal_ord);
    printf("Antal ord som börjar med A: %d\n", antal_a_ord);
    
    return 0;
}

Uppgift 10 (5 p)

#include <stdlib.h>
#include <stdio.h>

int main(void) {
    double tal;
    double summa = 0;
    double medel;
    int totalt_antal = 0;
    int antal_over = 0;
    FILE *tsin;

    tsin = fopen("tal.txt", "r");
    if (tsin == NULL) {
        fprintf(stderr, "Kunde inte läsa filen 'tal.txt'.\n");
        exit(EXIT_FAILURE);
    }

    while (fscanf(tsin, "%lf", &tal) == 1) {
        summa += tal;
        ++totalt_antal;
    }

    medel = summa / totalt_antal;

    rewind(tsin); // Eller stäng och öppna igen

    while (fscanf(tsin, "%lf", &tal) == 1) {
        if (tal > medel)
            ++antal_over;
    }

    fclose(tsin);

    printf("Totalt antal tal: %d\n", totalt_antal);
    printf("Antal över medel: %d\n", antal_over);

    return EXIT_SUCCESS;
}

Uppgift 11 (5 p)

#include <stdlib.h>
#include <stdio.h>

struct Triangel {
    double sida1;
    double sida2;
    double sida3;
};

int main(void) {
    int antal_liksidiga = 0;
    int antal_likbenta = 0;
    int antal_alla_sidor_olika = 0;
    FILE *bsin;
    struct Triangel triangel;

    bsin = fopen("trianglar.bin", "rb");
    if (bsin == NULL) {
        fprintf(stderr, "Kunde inte läsa filen 'trianglar.bin'.\n");
        exit(EXIT_FAILURE);
    }

    while (fread(&triangel, sizeof triangel, 1, bsin) == 1) {
        if (triangel.sida1 == triangel.sida2 && triangel.sida2 == triangel.sida3)
            ++antal_liksidiga;
        else if (triangel.sida1 == triangel.sida2 ||
                 triangel.sida2 == triangel.sida3 ||
                 triangel.sida1 == triangel.sida3)
            ++antal_likbenta;
        else
            ++antal_alla_sidor_olika;
    }

    fclose(bsin);

    printf("Antal liksidiga: %d\n", antal_liksidiga);
    printf("Antal likbenta: %d\n", antal_likbenta);
    printf("Antal med alla sidor olika: %d\n", antal_alla_sidor_olika);

    return EXIT_SUCCESS;
}

Anmärkning: Matematiker brukar räkna en triangel som liksidig om den har minst två sidor som är lika långa, vilket betyder att alla liksidiga trianglar också är likbenta. I den här lösningen ingår de liksidiga trianglarna dock inte i antalet likbenta.


Thomas Padron-McCarthy (thomas.padron-mccarthy@oru.se), 5 mars 2014