Programmering C: Lösningar till tentamen 2006-03-15

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)

Alternativ 1:
z = x / sqrt(pow(x, 2) - pow(y, 2)) + sqrt(pow(x, 2) - pow(y, 2)) / k;
Alternativ 2:
z = x / sqrt(x*x - y*y) + sqrt(x*x - y*y) / k;

Uppgift 2 (1 p)

a) 11

b) 5

Uppgift 3 (1 p)

11

Uppgift 4 (1 p)

struct Land landet = { "Sverige", 9001774, 410934 };

Uppgift 5 (1 p)

int temp;
temp = x;
x = y;
y = temp;

Uppgift 6 (2 p)

int datum_ok(int datumet) {
  int m = datumet % 10000 / 100;
  int d = datumet % 100;
  return (m >= 1) && (m <= 12) && (d >= 1) && (d <= 31);
}

Uppgift 7 (2 p)

void visa_datum(int datumet) {
  if (datum_ok(datumet)) {
    int y = datumet / 10000;
    int m = datumet % 10000 / 100;
    int d = datumet % 100;
    printf("%d/%d %d\n", d, m, y);
  }
  else {
    printf("Felaktigt datum\n");
  }
}

Uppgift 8 (2 p)

int las_datum() {
  int y, m, d, datumet;
  do {
    printf("Ange en dag (1-31): ");
    scanf("%d", &d);
    printf("Ange en månad (1-12): ");
    scanf("%d", &m);
    printf("Ange ett år (med fyra siffror): ");
    scanf("%d", &y);
    datumet = 10000 * y + 100 * m + d;
  } while (!datum_ok(datumet));
  return datumet;
}

Uppgift 9 (2 p)

void visa_land(struct Land landet) {
  printf("Landets namn: %s\n", landet.namn);
  printf("Landets folkmängd: %d\n", landet.befolkning);
  printf("Landets landyta: %f\n", landet.landyta);
}

Uppgift 10 (2 p)

Alternativ 1:
struct Land las_land() {
  struct Land landet;
  printf("Ange landets namn: \n");
  scanf("%s", landet.namn); /* Vi antar att landsnamn bara består av ett ord. */
  printf("Ange landets folkmängd: \n");
  scanf("%d", &landet.befolkning);
  printf("Ange landets landyta: \n");
  scanf("%f", &landet.landyta);
  return landet;
}
Alternativ 2:
void las_land(struct Land* p) {
  printf("Ange landets namn: \n");
  scanf("%s", p->namn); /* Vi antar att landsnamn bara består av ett ord. */
  printf("Ange landets folkmängd: \n");
  scanf("%d", &p->befolkning);
  printf("Ange landets landyta: \n");
  scanf("%f", &p->landyta);
}

Uppgift 11 (5 p)

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

extern int datum_ok(int datumet);
extern void visa_datum(int datumet);
extern int las_datum();

#define MAX_ANTAL_DAGAR 10

int main(void) {
  int idag, dagar[MAX_ANTAL_DAGAR], antal_dagar;

  printf("Ange dagens datum!\n");
  idag = las_datum();
  
  printf("Ange antal datum att hantera: ");
  scanf("%d", &antal_dagar);

  if (antal_dagar > MAX_ANTAL_DAGAR) {
    printf("Programmet kan bara hantera %d datum.\n", MAX_ANTAL_DAGAR);
    return EXIT_FAILURE;
  }

  for (int i = 0; i < antal_dagar; ++i)
    dagar[i] = las_datum();

  printf("Datum i framtiden:\n");
  for (int i = 0; i < antal_dagar; ++i)
    if (dagar[i] > idag)
      visa_datum(dagar[i]);

  return EXIT_SUCCESS;
}
Kommentarer:
  1. Kursmaterialet använder void main, trots att C-standarden (i de flesta sammanhang) egentligen kräver int main. Jag använder int main i mina lösningar, men ger inga poängavdrag för void main.
  2. Man behöver inte upprepa definitionerna av funktionerna datum_ok, visa_datum och las_datum. I programmet ovan har jag extern-deklarerat dem, men det ger inga poängavdrag om man inte har med dem alls.

Uppgift 12 (5 p)

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

int main(void) {
  int maxgransen, slumptalet, gissningen, antalet_gissningar;

  printf("Gissningsspel!\n");
  printf("Ange det största tillåtna talet: ");
  scanf("%d", &maxgransen);

  srand(time(NULL));
  slumptalet = rand() % maxgransen + 1;

  antalet_gissningar = 0;

  do {
    printf("Gissa: ");
    scanf("%d", &gissningen);
    ++antalet_gissningar;
    if (gissningen < slumptalet)
      printf("Gissningen var för liten!\n");
    else if (gissningen > slumptalet)
      printf("Gissningen var för stor!\n");
    else
      printf("Rätt!\n");
  } while (gissningen != slumptalet);

  printf("Du gissade %d gånger.\n", antalet_gissningar);

  return EXIT_SUCCESS;
}

Uppgift 13 (5 p)

#include <stdio.h>

struct Land {
   char namn[30];   // Landets namn
   int befolkning;  // Landets invånarantal
   float landyta;   // Landets landyta (i kvadratkilometer)
};

extern struct Land las_land();

int main(void) {
  struct Land landet;
  FILE* f = fopen("lander.dat", "wb");
  landet = las_land();
  while (landet.befolkning != 0 || landet.landyta != 0) {
    fwrite(&landet, sizeof(landet), 1, f);
    landet = las_land();
  }
  fclose(f);

  return 0;
}
Kommentarer:
Man behöver inte upprepa definitionen av funktionen las_land. I programmet ovan har jag extern-deklarerat den, men det ger inga poängavdrag om man inte har med den alls.

Uppgift 14 (5 p)

#include <stdio.h>
#include <limits.h>

struct Land {
   char namn[30];   // Landets namn
   int befolkning;  // Landets invånarantal
   float landyta;   // Landets landyta (i kvadratkilometer)
};

extern void visa_land(struct Land landet);
extern struct Land las_land();

int main(void) {
  struct Land landet, minfolk, maxfolk, minyta, maxyta;
  FILE* f = fopen("lander.dat", "rb");
  minfolk.befolkning = INT_MAX;
  maxfolk.befolkning = INT_MAX;
  minyta.landyta = INT_MAX;
  maxyta.landyta = INT_MIN;
  while (fread(&landet, sizeof(landet), 1, f) == 1) {
    if (landet.befolkning > maxfolk.befolkning)
      maxfolk = landet;
    if (landet.befolkning < minfolk.befolkning)
      minfolk = landet;
    if (landet.landyta > maxyta.landyta)
      maxyta = landet;
    if (landet.landyta < minyta.landyta)
      minyta = landet;
  }
  fclose(f);

  printf("*** Landet med minsta folkmängden:\n");
  visa_land(minfolk);
  printf("*** Landet med största folkmängden:\n");
  visa_land(maxfolk);
  printf("*** Landet med minsta ytan:\n");
  visa_land(minyta);
  printf("*** Landet med största ytan:\n");
  visa_land(maxyta);

  return 0;
}

Uppgift 15 (5 p)

#include <stdio.h>

struct TempData {
  float summa;
  int antal;
};

int main(void) {
  struct TempData tempdata[101]; /* 101? Ja, de är ju numrerade 1-100, inte 0-99! */

  for (int i = 1; i <= 100; ++i) {
    tempdata[i].summa = 0;
    tempdata[i].antal = 0;
  }

  FILE* f = fopen("temperaturer.txt", "r");
  int tid, givarnummer;
  float temperatur;
  while (fscanf(f, "%d %d %f", &tid, &givarnummer, &temperatur) == 3) {
    tempdata[givarnummer].summa += temperatur;
    tempdata[givarnummer].antal++;
  }
  fclose(f);

  for (int i = 1; i <= 100; ++i) {
    printf("Mätställe %d: Medeltemperatur = %f\n",
           i, tempdata[i].summa / tempdata[i].antal);
  }

  return 0;
}


Thomas Padron-McCarthy (Thomas.Padron-McCarthy@tech.oru.se) 24 mars 2006