Programmering C: Lösningar till tentamen 2008-05-31

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

b) 3

c) 2.25

Uppgift 2 (1 p)

i = 6, k = 4, n = 0.75

Uppgift 3 (1 p)

struct Igelkott temp;
temp = x;
x = y;
y = temp;

Uppgift 4 (1 p)

Så här kan man göra:
float plus(float tal1, float tal2) {
    return tal1 + tal2;
}
Så här kan man också göra:
double plus(double tal1, double tal2) {
    double summan = tal1 + tal2;
    return summan;
}

Uppgift 5 (4 p)

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

int main(void) {
    double x, y, R;

    printf("Ange x: ");
    scanf("%lf", &x);
    printf("Ange y: ");
    scanf("%lf", &y);
    printf("Ange R: ");
    scanf("%lf", &R);

    double namnaren = R * (x*x - y*y*y);

    if (namnaren == 0) {
        printf("Tyvärr går uttrycket inte att beräkna,\n");
        printf("eftersom nämnaren i divisionen är noll.\n");
        printf("Vi beklagar att det blev så här.\n");
        exit(EXIT_FAILURE);
    }

    double under_roten = 1 - 1 / namnaren;

    if (under_roten < 0) {
        printf("Tyvärr går uttrycket inte att beräkna,\n");
        printf("eftersom deluttrycket under rottecknet är mindre än noll.\n");
        printf("Vi beklagar SÅ att det blev så här.\n");
        exit(EXIT_FAILURE);
    }

    double uttrycket = sqrt(under_roten);
    printf("Värde: %f\n", uttrycket);
        
    return EXIT_SUCCESS;
}

Uppgift 6 (1 p)

struct Igelkott {
    char namn[10+1];
    double vikt;
    int antal_taggar;
};

Uppgift 7 (1 p)

struct Igelkott pilt = { "Pilt", 1.3, 7000 };

Uppgift 8 (2 p)

void visa_igelkott(struct Igelkott k) {
    printf("Igelkott: %s\n", k.namn);
    printf("Vikt: %f\n", k.vikt);
    printf("Taggar: %d\n", k.antal_taggar);
}

Uppgift 9 (2 p)

En lösning:
void las_igelkott(struct Igelkott *p) {
    printf("Skriv in data om en igelkott!\n");
    printf("Ange namnet: ");
    gets(p->namn); // Använd inte gets i riktiga program!
    printf("Ange vikten: ");
    scanf("%lf", &p->vikt);
    printf("Ange antal taggar: ");
    scanf("%d", &p->antal_taggar);
    while (getchar() != '\n')
        ;
Ett annat alternativ, som undviker den farliga funktionen gets:
void las_igelkott(struct Igelkott *p) {
    printf("Skriv in data om en igelkott!\n");
    printf("Ange namnet: ");
    fgets(p->namn, sizeof(p->namn), stdin);
    p->namn[strlen(p->namn) - 1] = '\0';
    printf("Ange vikten: ");
    scanf("%lf", &p->vikt);
    printf("Ange antal taggar: ");
    scanf("%d", &p->antal_taggar);
    while (getchar() != '\n')
        ;
}
Ett tredje alternativ, som returnerar igelkott-posten som funktionsvärde:
struct Igelkott las_igelkott(void) {
    struct Igelkott k;
    printf("Skriv in data om en igelkott!\n");
    printf("Ange namnet: ");
    fgets(k.namn, sizeof(k.namn), stdin);
    k.namn[strlen(k.namn) - 1] = '\0';
    printf("Ange vikten: ");
    scanf("%lf", &k.vikt);
    printf("Ange antal taggar: ");
    scanf("%d", &k.antal_taggar);
    while (getchar() != '\n')
        ;
    return k;
}

Uppgift 10 (2 p)

Om man använder pekar-versionen av las_igelkott:
int main(void) {
    struct Igelkott k1, k2;

    las_igelkott(&k1);
    las_igelkott(&k2);
    visa_igelkott(k1);
    visa_igelkott(k2);

    return 0;
}
Om man använder den versionen av las_igelkott som returnerar igelkott-posten som ett funktionsvärde:
int main(void) {
    struct Igelkott k1, k2;

    k1 = las_igelkott();
    k2 = las_igelkott();
    visa_igelkott(k1);
    visa_igelkott(k2);

    return 0;
}

Uppgift 11 (4 p)

Alternativ 1, som skriver till en textfil:
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

// Här ska det finnas definitioner av posttypen, mm

int main(void) {
    struct Igelkott k;
    FILE *f;
    f = fopen("igelkottar.txt", "w");
    if (f == NULL) {
        fprintf(stderr, "Kunde inte öppna filen 'igelkottar.txt'.\n");
        fprintf(stderr, "Möjlig orsak: %s (felkod %d)\n",
                strerror(errno), errno);
        exit(EXIT_FAILURE);
    }
    printf("Skriv in igelkottar.\n");
    printf("Avsluta med en igelkott med vikten 0.\n");
    las_igelkott(&k);
    while (k.vikt != 0) {
        fprintf(f, "%s\n%f\n%d\n", k.namn, k.vikt, k.antal_taggar);
        las_igelkott(&k);
    }
    fclose(f);
    return 0;
}
Alternativ 2, som skriver till en binärfil:
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

// Här ska det finnas definitioner av posttypen, mm

int main(void) {
    struct Igelkott k;
    FILE *f;
    f = fopen("igelkottar.bin", "wb");
    if (f == NULL) {
        fprintf(stderr, "Kunde inte öppna filen 'igelkottar.bin'.\n");
        fprintf(stderr, "Möjlig orsak: %s (felkod %d)\n", strerror(errno), errno);
        exit(EXIT_FAILURE);
    }
    printf("Skriv in igelkottar.\n");
    printf("Avsluta med en igelkott med vikten 0.\n");
    las_igelkott(&k);
    while (k.vikt != 0) {
        fwrite(&k, sizeof k, 1, f);
        las_igelkott(&k);
    }
    fclose(f);
    return 0;
}

Uppgift 12 (4 p)

Alternativ 1, som läser från en textfil:
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

// Här ska det finnas definitioner av posttypen, mm

int main(void) {
    char namn[10 + 1];
    printf("Ange att namn att söka efter: ");
    gets(namn); // Använd inte gets i riktiga program!

    FILE *f;
    f = fopen("igelkottar.txt", "r");
    if (f == NULL) {
        fprintf(stderr, "Kunde inte öppna filen 'igelkottar.txt'.\n");
        fprintf(stderr, "Möjlig orsak: %s (felkod %d)\n",
                strerror(errno), errno);
        exit(EXIT_FAILURE);
    }
    struct Igelkott k;
    while (fgets(k.namn, sizeof(k.namn), f) != NULL) {
        k.namn[strlen(k.namn) - 1] = '\0';
        fscanf(f, "%lf", &k.vikt);
        fscanf(f, "%d", &k.antal_taggar);
        while (getc(f) != '\n')
            ;
        if (strcmp(namn, k.namn) == 0)
            visa_igelkott(k);
    }
    fclose(f);

    return 0;
}
Alternativ 2, som läser från en binärfil:
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

// Här ska det finnas definitioner av posttypen, mm

int main(void) {
    char namn[10 + 1];
    printf("Ange att namn att söka efter: ");
    gets(namn); // Använd inte gets i riktiga program!

    FILE *f;
    f = fopen("igelkottar.bin", "rb");
    if (f == NULL) {
        fprintf(stderr, "Kunde inte öppna filen 'igelkottar.bin'.\n");
        fprintf(stderr, "Möjlig orsak: %s (felkod %d)\n",
                strerror(errno), errno);
        exit(EXIT_FAILURE);
    }
    struct Igelkott k;
    while (fread(&k, sizeof k, 1, f) == 1) {
        if (strcmp(namn, k.namn) == 0)
            visa_igelkott(k);
    }
    fclose(f);

    return 0;
}

Uppgift 13 (4 p)

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

#define MAX_RAD 107

int main(void) {
    char s1[MAX_RAD + 1 + 1];
    char s2[MAX_RAD + 1 + 1];
    char s3[MAX_RAD + 1 + 1];

    fgets(s1, sizeof s1, stdin);
    fgets(s2, sizeof s2, stdin);
    fgets(s3, sizeof s3, stdin);

    int l1 = strlen(s1);
    int l2 = strlen(s2);
    int l3 = strlen(s3);

    if (l1 >= l2 && l1 >= l3) {
        fputs(s2, stdout);
        fputs(s3, stdout);
    }
    else if (l2 >= l1 && l2 >= l3) {
        fputs(s1, stdout);
        fputs(s3, stdout);
    }
    else {
        fputs(s1, stdout);
        fputs(s2, stdout);
    }

    return 0;
}

Uppgift 14 (4 p)

Ett alternativ:
#include <stdio.h>

int main(void) {
    double langd, vikt, bmi;

    while (1) {
        printf("Längd (i meter): ");
        scanf("%lf", &langd);
        printf("Vikt (i kg): ");
        scanf("%lf", &vikt);
        if (langd == 0 || vikt == 0)
            break;
        bmi = vikt / (langd * langd);
        printf("BMI = %f\n", bmi);
    }
    return 0;
}
Ett annat alternativ, som upprepar en del kod (dåligt) men som kanske är lättare att förstå (bra):
#include <stdio.h>

int main(void) {
    double langd, vikt, bmi;

    printf("Längd (i meter): ");
    scanf("%lf", &langd);
    printf("Vikt (i kg): ");
    scanf("%lf", &vikt);

    while (langd != 0 && vikt != 0) {
        bmi = vikt / (langd * langd);
        printf("BMI = %f\n", bmi);

        printf("Längd (i meter): ");
        scanf("%lf", &langd);
        printf("Vikt (i kg): ");
        scanf("%lf", &vikt);
    }

    return 0;
}


Thomas Padron-McCarthy (Thomas.Padron-McCarthy@tech.oru.se), 4 juni 2008