Programmering C: Lösningar till tentamen 2013-03-02

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. En del av lösningarna kanske använder en modernare C-dialekt än vad Visual Studio klarar av.

Uppgift 1 (3 p)

a = 14
*b = 0
*****c = 0.000000

Uppgift 2 (5 p)

#include <stdio.h>

int main(void) {
    double maxvikt;
    double vaskvikt;
    double totalvikt;
    double sakvikt;

    printf("Ange högsta tillåtna totalvikt: ");
    scanf("%lf", &maxvikt);

    printf("Ange själva väskans vikt: ");
    scanf("%lf", &vaskvikt);

    totalvikt = vaskvikt;

    printf("Ange sakernas vikter. Avsluta med 0.\n");
    printf("Vad väger nästa sak? ");
    scanf("%lf", &sakvikt);
    while (sakvikt != 0) {
        if (totalvikt + sakvikt <= maxvikt) {
            printf("Ok, lägg i den.\n");
            totalvikt += sakvikt;
        }
        else {
            printf("Nej, det blir för tungt!\n");
        }
        printf("Vad väger nästa sak? ");
        scanf("%lf", &sakvikt);
    }

    printf("Totalvikt: %.2f\n", totalvikt);

    return 0;
}

Uppgift 3 (1 p)

struct Rektangel {
    double x1, y1; // Ena hörnet
    double x2, y2; // Andra hörnet
};

Uppgift 4 (1 p)

struct Rektangel r = { -1.5, 2, 5, 4.9 };

Uppgift 5 (2 p)

double area(struct Rektangel r) {
    return fabs( (r.x1 - r.x2) * (r.y1 - r.y2) );
}

Uppgift 6 (2 p)

int mindre(struct Rektangel r1, struct Rektangel r2) {
    return area(r1) < area(r2);
}

Uppgift 7 (3 p)

double total_area(struct Rektangel rektanglar[], int antal_rektanglar) {
    double summa = 0;
    for (int i = 0; i < antal_rektanglar; ++i)
        summa += area(rektanglar[i]);
    return summa;
}

Uppgift 8 (5 p)

int main(void) {
    struct Rektangel liten_rektangel = { -1.0, -1.1, 99, 1000 }; // Area: 100110
    struct Rektangel stor_rektangel  = { -1.0, -1.1, 99, 1000 + 0.01 }; // Area: 100111
    struct Rektangel flera_rektanglar[] = {
        { -1, -1, 1, 1 }, // Area: 4
        { -10, -10, 10, 10 }, // Area: 400
        { -0.1, -0.1, 0.1, 0.1 }, // Area: 0.04
    };

    printf("%f\n", area(liten_rektangel));
    printf("%f\n", area(stor_rektangel));
    printf("%f\n", total_area(flera_rektanglar, 3));

    double litet_resultat = area(liten_rektangel);
    if (litet_resultat != 100110)
        printf("Fel! area(liten_rektangel) blev %f och inte 100110\n", litet_resultat);

    int mindre_resultat = mindre(liten_rektangel, stor_rektangel);
    if (mindre_resultat != 1)
        printf("Fel! mindre(liten_rektangel, stor_rektangel) blev %d och inte 1\n", mindre_resultat);

    double totalt_resultat = total_area(flera_rektanglar, 3);
    if (totalt_resultat != 404.04)
        printf("Fel! total_area(flera_rektanglar, 3) blev %f och inte 404.04\n", totalt_resultat);

    return 0;
}
Kommentarer:
Vi ignorerar problemen med flyttal och likhetsjämförelser. På riktigt kan man mycket väl få fel resultat eftersom en del reella tal, till exempel 0.1, inte kan representeras exakt med flyttal.

Uppgift 9 (4 p)

#include <stdio.h>

int main()
{
    double talen[10];

    // En loop för att läsa in tio tal
    for (int i = 0; i < 10; i++) {
	printf("Ange talen[%d]: ", i);
	scanf("%lf", &talen[i]);
    }

    double min, max, summa;

    // Sätt första talet som startvärde för alla variablerna
    min = talen[0];
    max = talen[0];
    summa = talen[0];

    // En loop för att gå ignom resten av talen
    for (int i = 1; i < 10; i++) {
	if (talen[i] < min)
	    min = talen[i];
	if (talen[i] > max)
	    max = talen[i];
	summa += talen[i];
    }

    printf("Största = %.2f\n", max);
    printf("Minsta = %.2f\n", min);
    printf("Summa = %.2f\n", summa); 

    return 0;
}

Uppgift 10 (4 p)

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

int main(void) {
    FILE* f = fopen("tal.txt", "w");
    if (f == NULL) {
        fprintf(stderr, "Filen 'tal.txt' gick inte att öppna.\n");
        exit(EXIT_FAILURE);
    }
    printf("Skriv reella tal. Avsluta med talet 0.\n");
    double talet;
    scanf("%lf", &talet);
    while (talet != 0) {
        fprintf(f, "%g\n", talet); // %g skriver inte ut onödiga nollor på slutet
        scanf("%lf", &talet);
    }
    fclose(f);
    return EXIT_SUCCESS;
}

Uppgift 11 (4 p)

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

int main(void) {
    FILE* f = fopen("tal.txt", "r");
    if (f == NULL) {
        fprintf(stderr, "Filen 'tal.txt' gick inte att öppna.\n");
        exit(EXIT_FAILURE);
    }
    int antal_tal = 0;
    double talet;
    while (fscanf(f, "%lf", &talet) != EOF)
        ++antal_tal;
    fclose(f);
    printf("Antal tal: %d\n", antal_tal);
    return EXIT_SUCCESS;
}

Uppgift 12 (4 p)

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

int main(void) {
    srand(time(NULL)); // Ger pseudoslumptalsgeneratorn ett startvärde
    int antal_tal = rand() % 1000 + 1; // Mellan 1 och 1000 tal
    FILE* f = fopen("tal.txt", "w");
    if (f == NULL) {
        fprintf(stderr, "Filen 'tal.txt' gick inte att öppna.\n");
        exit(EXIT_FAILURE);
    }
    for (int i = 0; i < antal_tal; ++i) {
        double talet = rand() % 10000 / 1000.0; // Ett tal mellan 0.0 och 9.999
        fprintf(f, "%g\n", talet); // %g skriver inte ut onödiga nollor på slutet
    }
    fclose(f);
    return EXIT_SUCCESS;
}


Thomas Padron-McCarthy (thomas.padron-mccarthy@oru.se), 22 augusti 2013