Programmering C: Lösningar till tentamen 2013-01-19

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

b) 8

c) -4

d) 1

Uppgift 2 (1 p)

a = 2, b = 2, c = 5

Uppgift 3 (4 p)

#include <stdio.h>

int main(void) {
    printf("Hur många flyttal? ");
    int antal_tal;
    scanf("%d", &antal_tal);

    printf("Skriv %d reella tal:\n", antal_tal);
    int antal_negativa_tal = 0;
    for (int i = 0; i < antal_tal; ++i) {
        double detta_flyttal;
        scanf("%lf", &detta_flyttal);
        if (detta_flyttal < 0)
            ++antal_negativa_tal;
    }

    printf("Antal negativa tal: %d\n", antal_negativa_tal);
    
    return 0;
}

Uppgift 4 (4 p)

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

int main(void) {
    printf("Skriv första raden: ");
    char rad1[100 + 1];
    gets(rad1);
    printf("Skriva andra raden: ");
    char rad2[100 + 1];
    gets(rad2);

    srand(time(NULL)); // Ger pseudoslumptalsgeneratorn ett startvärde
    int radval = rand() % 2; // Ger ett slumptal som är 0 eller 1

    printf("En slumpmässigt vald rad:\n");
    if (radval == 0)
        puts(rad1);
    else
        puts(rad2);
    return 0;
}

Uppgift 5 (2 p)

#define MAX_NAMNLANGD 40

struct Prisuppgift {
    char vara[MAX_NAMNLANGD + 1];
    char butik[MAX_NAMNLANGD + 1];
    int pris;
};

Uppgift 6 (1 p)

struct Prisuppgift p = { "Apple MacBook Air", "Dustin Home", 9590 };

Uppgift 7 (1 p)

int samma_vara(struct Prisuppgift u1, struct Prisuppgift u2) {
    return strcmp(u1.vara, u2.vara) == 0;
}

Uppgift 8 (2 p)

int billigare(struct Prisuppgift u1, struct Prisuppgift u2) {
    return samma_vara(u1, u2) && u1.pris < u2.pris;
}

Uppgift 9 (2 p)

void visa_prisuppgift(struct Prisuppgift u) {
    printf("Vara: %s\n", u.vara);
    printf("Butik: %s\n", u.butik);
    printf("Pris: %d\n", u.pris);
}

Uppgift 10 (3 p)

void las_prisuppgift(struct Prisuppgift *up) {
    printf("Ange varans namn: ");
    gets(up->vara); // Nej, vi borde egentligen inte använda gets
    printf("Ange butikens namn: ");
    gets(up->butik); // Nej, vi borde egentligen inte använda gets
    printf("Ange priset: ");
    scanf("%d", &up->pris);
    // Nu finns ett radslutstecken kvar i inmatningsbufferten.
    // Vi måste läsa förbi det, annars tolkar nästa gets det som en tom rad.
    while (getchar() != '\n')
        ;
}

Uppgift 11 (3 p)

int main(void) {
    struct Prisuppgift prisuppgift1, prisuppgift2;

    printf("Mata in två prisuppgiftar:\n");
    las_prisuppgift(&prisuppgift1);
    las_prisuppgift(&prisuppgift2);

    if (samma_vara(prisuppgift1, prisuppgift2) == 0) {
        printf("De handlar om olika varor.\n");
    }
    else {
        printf("De handlar om samma vara. Den billigaste:\n");
        if (billigare(prisuppgift1, prisuppgift2))
            visa_prisuppgift(prisuppgift1);
        else
            visa_prisuppgift(prisuppgift2);
    }

    return 0;
}

Uppgift 12 (8 p)

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

// Definitioner enligt ovan

void avradsluta(char *s) {
    int sista = strlen(s) - 1;
    if (s[sista] == '\n')
        s[sista] = '\0';
}

int las_prisuppgift_fran_fil(FILE *f, struct Prisuppgift *up) {
    char namn[MAX_NAMNLANGD + 1 + 1]; // +1 för \n och +1 för \0
    if (fgets(namn, sizeof namn, f) == NULL)
        return 0;
    avradsluta(namn);
    strcpy(up->vara, namn);
    fgets(namn, sizeof namn, f);
    avradsluta(namn);
    strcpy(up->butik, namn);
    fscanf(f, "%d", &up->pris);
    // Läs förbi radslutstecknet i inmatningsbufferten
    while (getc(f) != '\n')
        ;
    return 1;
}

int main(void) {
    char sokt_vara[MAX_NAMNLANGD + 1];
    printf("Ange vara: ");
    gets(sokt_vara); // Jaja. Vi vet.
    FILE* f = fopen("allapriser.txt", "r");
    if (f == NULL) {
        fprintf(stderr, "Filen 'allapriser.txt' gick inte att öppna.\n");
        exit(EXIT_FAILURE);
    }
    int varan_hittad = 0;
    struct Prisuppgift billigast_hittills;
    struct Prisuppgift u;
    while (las_prisuppgift_fran_fil(f, &u) != 0) {
        if (strcmp(sokt_vara, u.vara) == 0) {
            if (varan_hittad == 0 || billigare(u, billigast_hittills)) {
                billigast_hittills = u;
                varan_hittad = 1;
            }
        }
    }
    fclose(f);
    if (varan_hittad == 0) {
        printf("Det finns inga prisuppgifter för den varan.\n");
    }
    else {
        printf("Billigast på %s (%d kronor).\n",
               billigast_hittills.butik, billigast_hittills.pris);
    }
    return EXIT_SUCCESS;
}

Uppgift 13 (5 p)

#include <stdio.h>

int main(void) {
    FILE *bsin = fopen("tal.bin", "rb");
    FILE *tsin = fopen("tal.txt", "r");
    float bintal;
    float texttal;
    int hittat_skillnad = 0;
    while (fread(&bintal, sizeof bintal, 1, bsin) == 1 && !hittat_skillnad) {
        if (fscanf(tsin, "%f", &texttal) != 1)
            hittat_skillnad = 1;
        else if (bintal != texttal)
            hittat_skillnad = 1;
    }
    // Om det finns tal kvar på textfilen är filerna olika!
    if (fscanf(tsin, "%f", &texttal) != EOF)
        hittat_skillnad = 1;
    fclose(bsin);
    fclose(tsin);
    if (hittat_skillnad == 0)
        printf("Filerna innehåller samma tal.\n");
    else
        printf("Filerna innehåller inte samma tal.\n");
    return 0;
}


Thomas Padron-McCarthy (thomas.padron-mccarthy@oru.se), 21 januari 2013