Lösningsförslag till datorövning 8, Programmering C. (Senaste ändring av denna fil: 29 februari 2016) /* ovning-8a.c */ #include #include #include #define MAX_ANTAL_TAL 1000 int main(void) { char filnamn[100]; printf("Ange namnet på en textfil med tal:\n"); fgets(filnamn, sizeof filnamn, stdin); if (filnamn[strlen(filnamn) - 1] == '\n') filnamn[strlen(filnamn) - 1] = '\0'; FILE *tsin = fopen(filnamn, "r"); if (tsin == NULL) { fprintf(stderr, "Kunde inte öppna filen '%s'.\n", filnamn); exit(EXIT_FAILURE); } printf("Läser filen '%s'...\n", filnamn); double talen[MAX_ANTAL_TAL]; int antal_tal = 0; double detta_tal; int fscanf_status; while ((fscanf_status = fscanf(tsin, "%lf", &detta_tal)) == 1) { if (++antal_tal > MAX_ANTAL_TAL) { fprintf(stderr, "För många tal på filen. Max är %d.\n", MAX_ANTAL_TAL); exit(EXIT_FAILURE); } talen[antal_tal - 1] = detta_tal; } if (fscanf_status != EOF) { fprintf(stderr, "Felaktiga data på filen efter %d tal.\n", antal_tal); exit(EXIT_FAILURE); } fclose(tsin); double summan = 0; for (int i = 0; i < antal_tal; ++i) summan += talen[i]; double medel = summan / antal_tal; int antal_over_medel = 0; for (int i = 0; i < antal_tal; ++i) { if (talen[i] > medel) ++antal_over_medel; } printf("Medel: %f\n", medel); printf("Antal över medel: %d av totalt %d\n", antal_over_medel, antal_tal); return EXIT_SUCCESS; } /* ovning-8b.c */ #include #include #include int main(void) { char filnamn[100]; printf("Ange namnet på en textfil med tal:\n"); fgets(filnamn, sizeof filnamn, stdin); if (filnamn[strlen(filnamn) - 1] == '\n') filnamn[strlen(filnamn) - 1] = '\0'; FILE *tsin = fopen(filnamn, "r"); if (tsin == NULL) { fprintf(stderr, "Kunde inte öppna filen '%s'.\n", filnamn); exit(EXIT_FAILURE); } printf("Läser filen '%s'...\n", filnamn); double *talen = NULL; int antal_tal = 0; double detta_tal; int fscanf_status; while ((fscanf_status = fscanf(tsin, "%lf", &detta_tal)) == 1) { ++antal_tal; talen = realloc(talen, antal_tal * sizeof(double)); if (talen == NULL) { fprintf(stderr, "Kunde inte allokera plats för %d tal.\n", antal_tal); exit(EXIT_FAILURE); } talen[antal_tal - 1] = detta_tal; } if (fscanf_status != EOF) { fprintf(stderr, "Felaktiga data på filen efter %d tal.\n", antal_tal); exit(EXIT_FAILURE); } fclose(tsin); double summan = 0; for (int i = 0; i < antal_tal; ++i) summan += talen[i]; double medel = summan / antal_tal; int antal_over_medel = 0; for (int i = 0; i < antal_tal; ++i) { if (talen[i] > medel) ++antal_over_medel; } printf("Medel: %f\n", medel); printf("Antal över medel: %d av totalt %d\n", antal_over_medel, antal_tal); return EXIT_SUCCESS; } /* ovning-8c.c */ #include #include #include struct Tal { double talet; struct Tal *nasta_tal; }; int main(void) { char filnamn[100]; printf("Ange namnet på en textfil med tal:\n"); fgets(filnamn, sizeof filnamn, stdin); if (filnamn[strlen(filnamn) - 1] == '\n') filnamn[strlen(filnamn) - 1] = '\0'; FILE *tsin = fopen(filnamn, "r"); if (tsin == NULL) { fprintf(stderr, "Kunde inte öppna filen '%s'.\n", filnamn); exit(EXIT_FAILURE); } printf("Läser filen '%s'...\n", filnamn); struct Tal *forsta_talet = NULL; int antal_tal = 0; double detta_tal; int fscanf_status; while ((fscanf_status = fscanf(tsin, "%lf", &detta_tal)) == 1) { ++antal_tal; struct Tal *nytt = malloc(sizeof(struct Tal)); if (nytt == NULL) { fprintf(stderr, "Kunde inte allokera plats för %d tal.\n", antal_tal); exit(EXIT_FAILURE); } nytt->talet = detta_tal; nytt->nasta_tal = forsta_talet; forsta_talet = nytt; } if (fscanf_status != EOF) { fprintf(stderr, "Felaktiga data på filen efter %d tal.\n", antal_tal); exit(EXIT_FAILURE); } fclose(tsin); double summan = 0; struct Tal *p = forsta_talet; while (p != NULL) { summan += p->talet; p = p->nasta_tal; } double medel = summan / antal_tal; int antal_over_medel = 0; p = forsta_talet; while (p != NULL) { if (p->talet > medel) ++antal_over_medel; p = p->nasta_tal; } printf("Medel: %f\n", medel); printf("Antal över medel: %d av totalt %d\n", antal_over_medel, antal_tal); return EXIT_SUCCESS; } Övning 8 D ---------- På min dator, en hyfsat snabb skrivbordsdator från 2014, ger varken program B eller C någon märkbar fördröjning för att läsa och behandla 1000 tal, från det man trycker på ENTER efter filnamnet tills resultatet skrivs ut. Med en miljon tal tar programmen knappt två tiondelar av en sekund. Ungefär samma tider för båda programmen. Med en miljard tal tar programmen ungefär tre minuter. (Och det är ju ganska rimligt, för en miljard är tusen gånger mer än en miljon, och tusen gånger 0.2 sekunder är 200 sekunder, vilket är ungefär 3 minuter.)