Programmering C: Lösningar till tentamen 2009-01-14

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.

Uppgift 1 (1 p)

a) 6

b) 2

c) 0

Uppgift 2 (1 p)

a = 3, b = 2, c = 7

Uppgift 3 (1 p)

x = 3.14, y = 4.14

Uppgift 4 (1 p)

double medel(double x, double y, double z) {
    return (x + y + z) / 3;
}

Uppgift 5 (2 p)

double arraymedel(double talen[], int antalet) {
    double summan = 0;
    for (int i = 0; i < antalet; ++i)
        summan += talen[i];
    return summan / antalet;
}

Uppgift 6 (1 p)

struct Temperatur {
    double temperatur;
    int timme, minut;
    char plats[10 + 1];
};

Uppgift 7 (1 p)

struct Temperatur orebro_vid_middagstid = { -14.0, 12, 1, "Örebro" };

Uppgift 8 (2 p)

void visa_temperatur(struct Temperatur t) {
    printf("%s kl %02d:%02d: %.1f\n",
           t.plats, t.timme, t.minut, t.temperatur);
}

Uppgift 9 (2 p)

struct Temperatur las_temperatur(void) {
    struct Temperatur t;

    printf("Ange plats: ");
    fgets(t.plats, sizeof t.plats, stdin);
    t.plats[strlen(t.plats) - 1] = '\0';
    printf("Ange timme: ");
    scanf("%d", &t.timme);
    printf("Ange minut: ");
    scanf("%d", &t.minut);
    printf("Ange uppmätt temperatur: ");
    scanf("%lf", &t.temperatur);
    while (getchar() != '\n')
        ;

    return t;
}

Uppgift 10 (3 p)

int main(void) {
    struct Temperatur t1, t2;

    t1 = las_temperatur();
    t2 = las_temperatur();

    printf("Högsta temperaturen:\n");
    if (t1.temperatur > t2.temperatur)
        visa_temperatur(t1);
    else
        visa_temperatur(t2);

    return 0;
}

Uppgift 11 (1 p)

struct Temperatur temp;
temp = t1;
t1 = t2;
t2 = temp;

Uppgift 12 (4 p)

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

/* Definitioner här */

int main(void) {
    double summa = 0;
    int antal = 0;
    struct Temperatur t;

    do {
        t = las_temperatur();
        if (t.temperatur >= 0) {
            summa += t.temperatur;
            ++antal;
        }
    } while (t.temperatur >= 0);

    printf("Medeltemperatur: %f\n", summa / antal);

    return 0;
}

Uppgift 13 (7 p)

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

#define MAX_ANTAL_TEMPERATURER 1000

/* Definitioner här */

int main(void) {
    int antal = 0;
    struct Temperatur t;
    struct Temperatur temperaturer[MAX_ANTAL_TEMPERATURER];

    printf("Mata in temperaturer. Avsluta med temperaturen -100.\n");

    t = las_temperatur();
    while (t.temperatur != -100) {
        if (antal == MAX_ANTAL_TEMPERATURER) {
            fprintf(stderr, "För många temperaturer. Adjö.\n");
            exit(EXIT_FAILURE);
        }
        temperaturer[antal++] = t;
        t = las_temperatur();
    }

    FILE* f = fopen("temperaturer.bin", "wb");
    if (f == NULL) {
        fprintf(stderr, "Kunde inte skriva filen.\n");
        exit(EXIT_FAILURE);
    }
    for (int i = 0; i < antal; ++i)
        fwrite(&temperaturer[i], sizeof(struct Temperatur), 1, f);
    fclose(f);

    return EXIT_SUCCESS;
}

Uppgift 14 (5 p)

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

#define MAX_ANTAL_TEMPERATURER 1000

/* Definitioner här */

int main(void) {
    char plats[10 + 1];

    printf("Ange plats: ");
    fgets(plats, sizeof plats, stdin);
    plats[strlen(plats) - 1] = '\0';

    struct Temperatur t, max, min;
    FILE* f = fopen("temperaturer.bin", "rb");
    if (f == NULL) {
        fprintf(stderr, "Kunde inte läsa filen.\n");
        exit(EXIT_FAILURE);
    }
    max.temperatur = -1000;
    min.temperatur = 1000;
    while (fread(&t, sizeof(struct Temperatur), 1, f) == 1) {
        if (strcmp(t.plats, plats) == 0) {
            if (t.temperatur < min.temperatur)
                min = t;
            if (t.temperatur >max.temperatur)
                max = t;
        }
    }
    fclose(f);

    printf("Lägsta uppmätta temperatur i %s:\n", plats);
    visa_temperatur(min);
    printf("Högsta uppmätta temperatur i %s:\n", plats);
    visa_temperatur(max);

    return EXIT_SUCCESS;
}

Uppgift 15 (8 p)

a) (4p)

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

int main(void) {
    char s[80 + 1];

    printf("Ange en sträng: ");
    gets(s);

    int n = strlen(s);
    int antal_ord = 0;
    int inuti_ord = 0;

    for (int i = 0; i < n; ++i) {
        if (s[i] == ' ') {
            inuti_ord = 0;
        }
        else if (!inuti_ord) {
            /* Det var inte ett blanktecken, och vi var inte inuti ett ord (än) */
            ++antal_ord;
            inuti_ord = 1;
        }
    }
    
    printf("Antal ord: %d\n", antal_ord);

    return 0;
}

b) (1p)

Funktionen gets kontrollerar inte att den inlästa raden får plats i det angivna minnesutrymmet. Därför kan man få så kallad buffer overflow, vilket betyder att man försöker skriva på andra platser i minnet än den avsedda, och då kan skriva sönder andra saker som finns där. Det kan ge konstiga effekter, till exempel:

c) (1p)

Ett sätt är att använda fgets. Då måste man också ta bort radslutstecknet, för fgets lagrar det.

    printf("Ange en sträng: ");
    fgets(s, sizeof s, stdin);
    s[strlen(s) - 1] = '\0';

d) (2p)

int number_of_occurences(char* s, char c) {
    int occurences = 0;
    int length = strlen(s);
    for (int i = 0; i < length; ++i)
        if (s[i] == c)
            ++occurences;
    return occurences;
}


Thomas Padron-McCarthy (thomas.padron-mccarthy@oru.se), 6 januari 2009