Programmering C: Lösningar till tentamen 2015-08-20

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 (3 p)

a = 110
b = 0, x = 5.000000
b = 1, x = 5.000000
b = 2, x = 5.000000
x = 5.000000
summan = 7.000000
uttrycket = 7.000000
a = 110
t = odefinierat värde
Där det står odefinierat värde har variabeln t inte fått något värde, så utskriften ger vad C-standarden kallar "odefinierat beteende". Standarden tillåter att vad som helst händer, till exempel att datorn exploderar, men det som brukar hända är att variabeln innehåller vad det nu var för skräp som tidigare råkade finnas på den platsen i minnet där variabeln hamnade, och det skräpet skrivs ut. Det kan till exempel bli 0.000000 eller -147.250000.

Uppgift 2 (4 p)

#include <stdio.h>
#include <math.h>

int main(void) {
    double x, y, R, under_inre_roten, namnaren, under_yttre_roten, resultat;

    printf("Ange värdet på x: ");
    scanf("%lf", &x);
    printf("Ange värdet på y: ");
    scanf("%lf", &y);
    printf("Ange värdet på R: ");
    scanf("%lf", &R);

    under_inre_roten = x*x - y*y*y;
    if (under_inre_roten < 0) {
        printf("Uttrycket har inte ett reellt värde.\n");
    }
    else {
        namnaren = R * sqrt(under_inre_roten);
        if (namnaren == 0) {
            printf("Uttrycket har inte ett reellt värde.\n");
        }
        else {
            under_yttre_roten = x - 1 / namnaren;
            if (under_yttre_roten < 0) {
                printf("Uttrycket har inte ett reellt värde.\n");
            }
            else {
                resultat = sqrt(under_yttre_roten);
                printf("Resultat: %f\n", resultat);
            }
        }
    }

    return 0;
}

Uppgift 3 (5 p)

void visa_array(int a[], int antal, FILE *f) {
    printf("[ ");
    for (int i = 0; i < antal; ++i) {
        printf("%d", a[i]);
        if (i != antal - 1)
            printf(", ");
    }
    printf(" ]\n");
}

Uppgift 4 (4 p)

int main(void) {
    int a[100];
    int antal;
    char filnamn[100 + 1];
    FILE *f;

    printf("Ange antalet heltal:\n");
    scanf("%d", &antal);

    printf("Skriv de %d talen:\n", antal);
    for (int i = 0; i < antal; ++i)
        scanf("%d", &a[i]);

    /* Här ligger ett radslutstecken kvar efter sista scanf:en! */
    while (getchar() != '\n')
        ;

    printf("Ange filnamnet:\n");
    gets(filnamn);

    f = fopen(filnamn, "w");
    if (f == NULL) {
        fprintf(stderr, "Filen '%s' gick inte att öppna.\n", filnamn);
        exit(EXIT_FAILURE);
    }

    visa_array(a, antal, f);
    
    return EXIT_SUCCESS;
}

Uppgift 5 (5 p)

int max_antal_siffra(char *s) {
    int antal[10];
                
    for (int i = 0; i < 10; ++i)
        antal[i] = 0;
    int length = strlen(s);
    for (int i = 0; i < length; ++i) {
        if (isdigit(s[i]))
            ++antal[s[i] - '0'];
    }
    int max = 0;
    for (int i = 0; i < 10; ++i) {
        if (antal[i] > max)
            max = antal[i];
    }
    return max;
}

Uppgift 6 (3 p)

int main(void) {
    if (max_antal_siffra("kalle") != 0 ||
        max_antal_siffra("kalle7") != 1 ||
        max_antal_siffra("xx447xxx4") != 3)
        printf("Något av testfallen gav fel svar.\n");
    else
        printf("Testfallen gav rätt svar.\n");
        
    return 0;
}

Uppgift 7 (16 p)

a)
#define NAME_LENGTH 3
#define MAX_HIGH_SCORE_ENTRIES 10

struct Entry {
    char name[NAME_LENGTH + 1];
    long int points; // The max of a plain "int" CAN be as small as 32767
};

struct Entry high_scores[MAX_HIGH_SCORE_ENTRIES];
int nr_high_scores = 0;
b)
void skriv_listan(void) {
    printf("Placering   Namn    Poäng\n");
    printf("---------   ----    -----\n");
    printf("\n");
    for (int i = 0; i < nr_high_scores; ++i)
        printf("%4d %10s %9ld\n", i + 1, high_scores[i].name, high_scores[i].points);
}
c)
int ska_lagras(int points) {
    return nr_high_scores < MAX_HIGH_SCORE_ENTRIES ||
        points > high_scores[nr_high_scores - 1].points;
}
En alternativ lösning:
int ska_lagras(int points) {
    if (nr_high_scores < MAX_HIGH_SCORE_ENTRIES)
        return 1;
    else if (points > high_scores[nr_high_scores - 1].points)
        return 1;
    else
        return 0;
}
d)
void registrera_resultat(char *name, int points) {
    if (ska_lagras(points)) {
        // Find the right place, expressed as an array index
        int place = 0;
        while (place < MAX_HIGH_SCORE_ENTRIES && high_scores[place].points > points)
            ++place;
        printf("[place = %d]\n", place);
        // Move the entries after one step towards the end of the list
        for (int i = MAX_HIGH_SCORE_ENTRIES - 2; i >= place; --i)
            high_scores[i + 1] = high_scores[i];
        // Insert the new one
        strcpy(high_scores[place].name, name);
        high_scores[place].points = points;
        if (nr_high_scores < MAX_HIGH_SCORE_ENTRIES)
            ++nr_high_scores;
    }
}
e)
void spara_resultat(void) {
    FILE *f = fopen("high_scores.txt", "w");
    if (f != NULL) {
        for (int i = 0; i < nr_high_scores; ++i)
            fprintf(f, "%s %ld\n", high_scores[i].name, high_scores[i].points);
        fclose(f);
    }
}
f)
void hemta_resultat(void) {
    FILE *f = fopen("high_scores.txt", "r");
    if (f != NULL) {
        nr_high_scores = 0;
        while (fscanf(f, "%s %ld", high_scores[nr_high_scores].name, &high_scores[nr_high_scores].points) == 2)
            ++nr_high_scores;
        fclose(f);
    }
}
g)

Minustecken kan inte ingå i identifierare (som till exempel namn på funktioner) i C, utan hemta-resultat skulle tolkas som hemta - resultat, dvs subtrahera resultat från hemta.


Thomas Padron-McCarthy (thomas.padron-mccarthy@oru.se), 24 augusti 2015