Azine
Om tidningen Azine
Köpa Azine
Kontakta Azine
Hjälpa till
Annonsera i Azine
About Azine English

Senaste numret
Nästa nummer
Arkiv

Kurser/Skolor
Intervjuer
Forum

ACG
SUA
ACG Göteborg
AmigaGuiden

Annonsörer:
GGS-Data

Sponsorer:
AmigaRulez (Forum)
GGS-Data
WestSide Praetorian
M.Andersson

Försäljningsställen
GGS-Data
Guru Meditation


Senaste Nummer 8 Nummer 7 Nummer 7 bilaga Nummer 6 Nummer 5++ Nummer 4 Nummer 3 Nummer 2 Nummer 1









Vill du ha din banner här?
Skriv till [email protected]!
Välkommen till hela Sveriges Amigatidning.


ACGs maskot

Grunderna i C, del 5.

I den här delen kommer vi att fortsätta med strukturer och pekare. Men nu kommer vi att använda dem ihop och bygga dynamiska listor med data. Sedan ska vi lära oss lite om hur vi kan göra operationer på variabler på bit-nivå.

Länkade listor!

När man vill ha listor med information i, som till exempel i en telefonbok där man vill ha namn och telefonnummer, så kan man använda sig utav “structobjekt”, från och nu kallar vi dem poster, som man länkar ihop till en lista med hjälp av pekare. Då får man så kallade länkade listor.
Vad det hela går ut på är att man i en post pekar ut nästa post och på så vis länkar ihop posterna. Man kan naturligtvis även ha en pekare i varje post som pekar ut föregående post också, se Figur 1.

Figur 1.


En struct för att hantera detta kan se ut som i Figur 2.

Figur 2.

struct person
{
  struct person *next;
  struct person *prev;
  char firstname[20];
  char lastname[20];
  int  age;
};
Här har vi pekare som pekar ut en efterföljande och föregående post, som även de är en ´struct person´, och kallar dem för next och prev.
När man håller på med pekare och länkade listor är det viktigt att man inte tappar bort poster och då får minnesläckor.
Vi tar ett litet exempel på hur ett program som använder länkade listor kan se ut. Se figur 3.

Figur 3.

#include 
#include 
#include struct person
{
  struct person *next,*prev;
  char firstname[20], lastname[20];
  int  age;
};struct person *NewPerson(char
  *firstname,char *lastname,int age);
struct person *DelPerson(struct person 
  *delperson);int main(int argv, char *argc[])
{
  struct person first;
  struct person *more = NULL;
  struct person *temp = NULL;  first.next = NULL; first.prev = NULL;
  strcpy(first.firstname,”Anders”); 
  strcpy(first.lastname,”Andersson”);
  first.age = 11;  more=NewPerson(”Bengt”,”Bengtsson”,22);
  more->prev = &first; first.next = more;  more=NewPerson(”David”,”Davidsson”,33);
  temp = first.next;
  more->prev = temp; temp->next = more;  temp = &first;
  while(temp != NULL)
  {
    printf(”Förnamn: %s\nEfternamn: 
               %s\nÅlder: %d\n\n”,
             temp->firstname,temp->lastname, 
             temp->age);
    temp = temp->next;
  }
  while(first.next != NULL)
  {
    DelPerson(first.next);
  }
  return 0;
}struct person *NewPerson(char *firstname,char *lastname,int age)
{
  struct person *newperson;
  newperson = (struct person *) 
    malloc(sizeof(struct person));  if(newperson != NULL)
  {
    newperson->next = NULL; 
    newperson->prev = NULL;
    strcpy(newperson->firstname,firstname);
    strcpy(newperson->lastname,lastname);
    newperson->age = age;
    printf(”Lägger till %s %s\n”,
      newperson->firstname,
      newperson->lastname);
  }
  return newperson;
}struct person *DelPerson(struct person *delperson)
{
  if(delperson != NULL)
  {
    struct person *next=delperson->next;
    struct person *prev=delperson->prev;    printf(”Tar bort %s %s\n”,
      delperson->firstname,
      delperson->lastname);    if(prev != NULL)
    {
      prev->next = next;
    }    if(next != NULL)
    {
      next->prev = prev;
    }    free(delperson);    if(prev != NULL)
    {
      return prev;
    }    return next;
  }  return NULL;
}

Vad har vi gjort?

struct person first;
Här skapar vi en variabel av typen ´struct person´. Första posten i en länkad lista kan även vara en pekare som man sedan allokerar upp minne till, men vi har en fast struktur i exemplet.
struct person *more = NULL;
Här skapar vi en pekare till en `struct person` och sätter den till att peka på NULL. Här har vi alltså ingen plats för själva strukturen, bara en pekare som kan peka ut en struktur.
first.next = NULL
Här sätter vi pekarna till nästa post (och sedan till föregående) till NULL i variabeln first. Det är bra att sätta alla nya pekare vi har till NULL så att vi vet att de inte pekar på någonting. Observera att när vi har en struktur (first är en struct/struktur, inte en pekare till en struct) och vill komma åt de variabler som finns i strukturen så använder vi oss utav ´.´.
more->prev = &first;
Här sätter vi pekaren för föregående post i den post som NewPerson-funktionen skapat. Vi pekar ut adressen till posten first (& före en variabel, här en variabel av typ ´struct person´, ger adressen till minnet där variabeln ligger). När man inte har ett objekt, som för first, utan en pekare till ett objekt så använder man ´->´ för att komma åt variablerna i strukturen.

Att tänka på

Länkade listor är egentligen ganska simpelt, men det gäller att hela tiden hålla koll på det man gör. För skulle man till exempel ha pekare som pekar fel eller inte ha tillräckligt med kontroller på NULL-värden så kommer programmet att krasha eller läcka minne som en sil. Inte bra! Så det gäller att vara noga med det man gör.

Bitar hit och bitar dit!

Som vi tagit upp i första delen av skolan så består data av bitar. Åtta bitar blir en byte och så vidare. Nu ska vi ta och lära oss lite hur vi kan påverka dessa bitar och göra jämförelser med dessa.
Det finns 6 stycken operationer som man kan göra på bit-nivå:
~	komplement
&	AND
^	exklusiv OR
|	inklusiv OR
<<	skifta vänster
>>	skifta höger
Vi tar och går igenom vad dessa betyder:
~
betyder att man inverterar alla bitar. Det vill säga att alla 1:or blir 0:or och 0:or blir 1:or.
a	00110001
~a	11001110
&
betyder att vi tar två värden och kollar om bitarna på samma positioner är 1:or och sätter då en etta på den positionen i resultatet.
^
betyder att vi tar två värden och kollar om en, och endast en, av bitarna på samma position är en 1:a och sätter då en etta på den positionen i resultatet.
|
betyder att vi tar två värden och kollar om en eller två bitar på samma position är 1:or och sätter då en etta på den positionen i resultatet.
A   B  A&B A^B A|B
0   0   0   0   0
1   0   0   1   1
0   1   0   1   1
1   1   1   0   1A   00110010
B   10010111
A&B 00010010
A^B 10100101
A|B 10110111
<<
och
>>
betyder att vi tar 2 värden och flyttar bitarna åt sidan. Första värdet skiftas så många steg som det andra värdets tal. Resultatet av en skift är 4 bytes (32 bitar).
A                                  10010001
A << 2  00000000 00000000 00000010 01000100B       10000000 00000000 00000000 00000000
B >> 2	00100000 00000000 00000000 00000000*
B >> 2	11100000 00000000 00000000 00000000*
* Beroende på vad det är för maskin och vilken typ B är (signed eller unsigned) kan högerskiftningar skifta in olika. Unsigned kommer alltid att skifta in 0:or, men på vissa maskiner så kommer till exempel en integer (som är signed) att skifta in 1:or istället om sign-biten (biten längst till vänster) är en 1:a.
Figur 4 skriver ut bit-represent-ationen av en integer med hjälp av bit-operationerna vi lärt oss nu.

Figur 4.

#include 
void main() {
	int i;
	int value = 7070;
	int n = sizeof(int) * 8;
	unsigned int mask = 1 << (n-1);	for(i = 0; i < n; i++) {
		if((i % 8) == 0) printf(” “);
		if(mask & value) printf(”1");
		else printf(”0");
		mask = mask >> 1;
	}
	printf(”\n”);
	return;
}

Slutet gott, allting fortsätter!

Det har äntligen blivit dax att säga farväl till Grunderna i C, och nu hoppas vi att några personer har lyckats lära sig lite om C, för nu så ska vi börja koda lite mer avancerat och lite mer Amiga-specifikt i kommande delar av C-skolan.


Hemsidorna underhålls av Magnus Andersson