Umeå Universitet
Institutionen för datavetenskap
Programmeringsteknik för tekniska fysiker
Niklas Frykholm, 24 februari 1999
#include <stdio.h>
int upphoj(int x, int y);
int main(void)
{
printf("3 ^ 5 = %d\n", upphoj(3,5));
printf("5 ^ 3 = %d\n", upphoj(5,3));
return 0;
}
/* Beräknar värdet av x upphöjt till y. */
int upphoj(int x, int y)
{
int res=1, i;
for (i=1; i<=y; i++)
res *= x;
return res;
}
#include <stdio.h>
#include <math.h>
double gamma(double a);
int main(void)
{
int i;
/* Formateringskoder för att få snyggare utskrift. Se
kap 11. */
printf("%6s %6s\n", "a", "gamma");
for (i=0; i<=19; i++)
printf("%6.2lf %6.2lf\n", i*0.05, gamma(i*0.05));
return 0;
}
double gamma(double a)
{
return 1/sqrt(1-a*a);
}
#include <stdio.h>
int main(void)
{
double p_ja = 0, p_nej = 0;
int ja=0, nej=0;
int val;
while(1) {
printf("\n\nÄr det rätt att ta pengar från försvaret och lägga "
"på vården?\n\n"
" 1. Ja (%.1lf %%)\n"
" 2. Nej (%.1lf %%)\n\n"
" 3. Avsluta programmet\n\n"
"Välj ett alternativ: ", p_ja, p_nej);
scanf("%d", &val);
switch (val) {
case 1: ja++; break;
case 2: nej++; break;
case 3: exit(0);
}
if (ja || nej) {
p_ja = (double)ja/(ja+nej)*100.0;
p_nej = 100 - p_ja;
}
}
}
Några viktiga fall att fundera över är:
Exakt hur vi hanterar dessa olika fall spelar inte så stor roll, så länge som vi ser till att dokumentera vårt val i kommentaren till funktionen, så att den som skall använda funktionen förstår hur den skall användas.
#include <stdio.h>
#include <math.h>
int storsta_primtal(int a, int b);
int primtal(int x);
int main(void)
{
int a, b, res;
printf("Skriv in a och b (a <= b): ");
scanf("%d %d", &a, &b);
res = storsta_primtal(a,b);
if (res!=-1)
printf("Det största primtalet mellan %d och %d är %d.\n",
a, b, res);
else
printf("Det finns inget primtal mellan %d och %d.\n",a,b);
return 0;
}
/* Ger det största primtalet mellan a och b.
Funktionen skall anropas med a <= b.
Om det inte finns något primtal mellan talen returneras -1. */
int storsta_primtal(int a, int b)
{
int i;
for(i=b; i>=a; i--)
if (primtal(i))
return i;
return -1;
}
/* Ger värdet sant om x är ett primtal. */
int primtal(int x)
{
int y;
for (y=2; y<=sqrt(x); y++)
if (x%y==0)
return 0;
return 1;
}
Utskriften blir E D C B A A B C D E.
Det enklaste sättet att se det är att först kolla vad som händer när funktionen anropas med rek1('A'), därefter med rek1('B') osv.
Svårt att ge ett facit på denna uppgift. Allt är rätt, bara det är väl genomtänkt.
Det enklaste sättet att lösa detta problem är att först titta på det enklaste fallet n=0 och se vad returvärdet blir då, sedan på det näst enklaste n=1, osv, och därefter försöka skriva en iterativ funktion som ger samma resultat.
#include <stdio.h>
double rek1(double x, int n);
double iter1(double x, int n);
int main(void)
{
double x;
int n;
for (x=0.2; x<0.7; x+=0.2)
for (n=-1; n<=5; n+=2)
printf("rek1(%.1lf,%2d) = %6.2lf iter1(%.1lf,%2d) = %6.2lf\n",
x,n,rek1(x,n),x,n,iter1(x,n));
return 0;
}
double rek1(double x, int n)
{
if (n <= 0)
return 1.0;
else
return 1.0 + x * rek1(x, n-1);
}
double iter1(double x, int n)
{
double res=1;
int i;
for (i=1; i<=n; i++)
res = 1.0 + x * res;
return res;
}
Här är ett program som skriver ut största talet, minsta talet och medelvärdet. Vi gör det genom att låta en variabel hålla reda på det största tal vi har sätt hittills.
Notera specialfallet för n==0. Det första talet vi läser in är alltid det största och det minsta hittills. (Utan specialfallet skulle programmet inte fungera eftersom storsta och minsta har slumpmässiga värden.)
#include <stdio.h>
int main(void)
{
double tal, storst, minst, sum;
int n=0;
while(1) {
scanf("%lf", &tal);
if (tal < 0)
break;
if (n==0) {
storst = tal;
minst = tal;
}
else {
if (tal > storst)
storst = tal;
if (tal < minst)
minst = tal;
}
sum += tal;
n++;
}
if (n==0)
printf("Du har inte skrivit in några tal.\n");
else
printf("Största: %.2lf, Minsta: %.2lf, Medel: %.2lf\n", storst, minst,
sum/n);
return 0;
}
Här är ett program som skriver ut det näst största talet. Notera att vi måste hålla reda på både det största och det näst största talet, eftersom det största kan bli det näst största.
#include <stdio.h>
int main(void)
{
double tal, storst, nast_storst;
int n=0;
while (1) {
scanf("%lf", &tal);
if (tal <0)
break;
if (tal > storst || n==0) {
nast_storst = storst;
storst = tal;
}
else if (tal > nast_storst || n==1)
nast_storst = tal;
n++;
}
if (n<2)
printf("Du har skrivit in färre än två tal.\n");
else
printf("Det näst största talet är %lf.\n", nast_storst);
return 0;
}
Eftersom varje anrop av funktionen har sin egen variabel summa så kommer programmet inte att fungera. Anropet summera(7) kommer att ge värdet 7.
Nu är summa global och delas av alla funktionsanrop. Varje funktionsanrop kommer alltså att lägga sitt tal till summan och vi får rätt resultat.
Men det är inte någon speciellt bra lösning - för att resultatet skall bli rätt krävs att den globala variabeln har värdet 0 när funktionen anropas. Om vi anropar summera(7) och summera(3) så kommer det gamla värdet på summa att ligga kvar och förstöra för det andra funktionsanropet. För att få rätt resultat måste vi nollställa summa mellan varje funktionsanrop.
s7 = summera(7); summa = 0; s3 = summera(3);
Det är besvärligt och lätt att glömma bort -- en dålig lösning.
#include <stdio.h>
int summera(int n);
int main(void)
{
int n;
scanf("%d", &n);
printf("summera(%d) = %d\n", n, summera(n));
return 0;
}
int summera(int n)
{
if (n<=0)
return 0;
else
return n + summera(n-1);
}
© Niklas Frykholm, februari 1999