Ukeoppgave 3: C programmering

Dette er det siste settet med ukeoppgaver som er hovedsaklig ment for de som ikke har f?lgt INF1060. Vi synes at de vil hjelpe med gjennomf?ringen av obliger og hjemmeeksamer. Dere som har f?lgt INF1060 vil ikke ha spesiell bruk for disse oppgavene.

Fra neste uke vil ukeoppgavene besto hovedsaklig av oppgaver som ligner oppgaver i den skriftlige slutteksamen. Mens dere holder p? med praktiske i obliger og hjemmeeksamer er det alts? nyttig ogs? ? f?lge med p? ukeoppgavene som forberedelse for slutteksamen.

M?let med disse oppgavene er ? g? gjennom en del konstruksjoner i spr?ket C som stiller programmerere som ikke er vant spr?ket foran en del problemer. Det er hovedsaklig pekere, arrays, strings, og bit-operasjoner. I disse konstruksjonene viser det seg tydelig at C ikke er et h?yniv?ssprak. Man m? tenke hardwaren?r for ? sj?nne hvorfor ting virker som de gj?r. For oss i INF3190/INF4190 er det viktig, fordi vi m? ha full kontroll over hver eneste bit og byte som vi ?nsker ? overf?re p? data link, network eller transportlag.

Programmeringsoppgaven skal l?ses p? en maskin av type unix; enten linux eller solaris.

1. Bitoperasjoner

Bitoperasjoner forekommer hyppig i alle protokoller nedenfor applikasjonslaget. I noen tilfeller er det bare gjort for ? sp?re b?ndbredde, men hovedsaklig er protokoller spesifisert p? bit-niv? fordi protokoller gj?r samtaler mulig mellom maskiner som er s? forskjellige at det eneste som de har i felles er sin forst?else om hva en bit er og hvilken rekkef?lge de har sendt og mottatt bittene i.

Derfor skal dere lese fra en fil og komprimere den etter metoden runlength encoding. Tanken med dette er at i steden for ? skrive mange etterf?lgende like tegn i en fil har man med en teller i tillegg som sier hvor mange like tegn som f?lger det tegnet vi akkurat har lest.

Filen skal inneholde bare tegnene a, b, c, d, e, f, g, h, i, j. Det gj?r det mulig ? komprimere bokstavene entydig med 4 bit per bokstav (a=0001, b=0010, c=0011, ..., j=1010). I tillegg til ? komprimere bokstavene skal dere telle hvor mange like bokstaver det er som f?lger etter hverandre. Er det bare en bokstav, s? skal dere bare skrive den komprimerte bokstaven. Er det flere like bostaver, skal dere bruke de to bitene 11 for ? vise at det er f?lger flere like bokstaver, fire bits for ? kodiere antallet gjentakelser bin?rt, f?lgt av den komprimerte bokstaven. Hvis den komprimerte strengen ikker slutter p? en byte-grense, skal den fylles opp med bitparer 00.

Det skal kunne b?de komprimere og dekomprimere strenger.

2. Arrays and pointers (a)

C er et spr?k med f? og korte ord og enkle symboler. En-bokstavs-symboler er hyppig brukt, og forkortelser er en del av syntaksen. Her er et eksempel for korrekt kode:

	  void function( char* buf )
	  {
	      ...
	  }

	  void otherfunction( )
	  {
	      char buffer[200];
	      ...
	      function( buffer ); /* <- abbreviation */
	      ...
	  }

Forklar hva det er som foreg?r.

3. Arrays and pointers (b)

Du har f?lgende kode:

	  void function( int a, int* b, char c, char* d, char e[] )
	  {
	      a  = 2;
	      *b = 3;
	      b  = &a;
	      c  = 'x';
	      *d = 'y';
	      d  = &c;
	      e[2] = 'z';
	  }
	  int main( )
	  {
	      int   k,l;
	      int*  m;
	      char  n,o;
	      char* p;
	      char  q[5];

	      k = 100;
	      l = 101;
	      m = &l;
	      n = 'n';
	      o = 'o';
	      p = &o;
	      q[0] = 'h';
	      q[1] = 'e';
	      q[2] = 'r';
	      q[3] = 'e';
	      q[4] = '\0';

	      function( k,m,n,p,q );

	      printf( "k=%d l=%d *m=%d\n", k, l, *m );
	      printf( "n=%c o=%c *p=%c\n", n, o, *p );
	      printf( "q=%s\n", q );
	  }

Hva skreves ut p? skjermen? Hvorfor skreves ut akkurat dette?

4. Strenger i C (a)

Strenger i C er ikke noe annet en bokstavarrayer. Det er blant annet ikke mulig ? utf?re veldig nyttige operasjoner p? C strenger som de allerfleste andre spr?k har. For eksempel kan man ikke bruke plus operatoren for ? konkatinere to C strenger. Mange misliker det.

Den store fordelen med C strenger er at man har full kontroll over det som skjer. Man hvet n?yaktig hvor i minne dataene til en C streng ligger, hvor mye plass den bruker, og hva man m? sende over nettet for at mottakersiden ogs? kan bruke den som en streng. Det klarer man ikke med strengene i de andre spr?kene. Og man kan f.eks. trekke ut eller erstatte enkelte bokstaver, regne med bokstaver som om de var tall eller p? en enkel m?te avbryte strenger. Men det krever litt trening.

Du har f?lgende kode:

	  void funA( char buf[10] )
	  {
	      int i;
	      for( i=0; i<10; i++ )
	      {
		  buf[i] = 'a' + i;
	      }
	  }
	  void funB( char* buf )
	  {
	      int i;
	      for( i=0; i<10; i++ )
	      {
		  buf[i] = 'b' + i;
	      }
	  }
	  void funC( char* buf )
	  {
	      int i;
	      for( i=0; i<10; i++ )
	      {
		  *buf = 'c' + i;
		  buf = buf + 1;
	      }
	  }
          int main( )
          {
                char buf[11];
                memset( buf, 0, 11 );
                funA( buf );
                printf( "%s\n", buf );
                funB( buf );
                printf( "%s\n", buf );
                funC( buf );
                printf( "%s\n", buf );
          }

Hva skreves ut p? skjermen? Hvorfor skreves ut akkurat dette?

5. Strenger i C (b)

Du har den f?lgende variablen:

        char* apple = "                     a\n"
                      "                    ppl\n"
                      "                  eappl\n"
                      "                 eapple\n"
                      "                 apple\n"
                      "                 appl\n"
                      "         eappleappleappleappl\n"
                      "     eappleappleappleappleapple\n"
                      "   appleappleappleappleappleapple\n"
                      "  appleappleappleappleappleappleappl\n"
                      " eappleappleappleappleappleappleapple\n"
                      "appleappleappleappleappleappleappleapp\n"
                      "leappleappleappleappleappleappleapplea\n"
                      "ppleappleappleappleappleappleappleappl\n"
                      "eappleappleappleappleappleappleappleap\n"
                      "pleappleappleappleappleappleappleapple\n"
                      "appleappleappleappleappleappleappleapp\n"
                      "leappleappleappleappwormpleappleapplea\n"
                      " ppleappleappleappleappleappleappleap\n"
                      "  pleappleappleappleappleappleapplea\n"
                      "   ppleappleappleappleappleappleapp\n"
                      "    leappleappleappleappleappleap\n"
                      "      pleappleappleappleappleapp\n"
                      "        leappleappleappleapple\n"
                      "          appleappleappleapp\n";

Dette er en lovlig C streng. Sp?rsm?lene er: Hvor langt er strengen? Hvor mange bytes m? du allokkere med malloc hvis du ?nsker ? lage en kopi?

5. Strenger i C (c)

Finn ormen i eplen. Fors?k f?lgende muligheter:

  • Bruk ikke noen C funksjoner i det hele tatt, bare enkle spr?koperasjoner som if/else, for, while, do osv.
  • Bruk s?kefunksjonen strchr(). Husk ? inkludere string.h.
  • Bruk erstatningsfunksjonen strstr().

Klipp ormen ut av eplen, med ? overskrive bokstavene med " ".

6. Strenger i C (d)

Hvor dypt i eplen var ormen (Hva er index verdien for den f?rste bokstaven 'w' av ordet worm). Brukt funksjonen strstr() for ? finne svaret.

7. Modifiser chatteprogram - structer over UDP socket

Modifiser sist ukes l?sningsforslag for chatteprogrammet slik at det bruker en UDP socket for kommunikasjon. Videre skal meldingene n? sendes og mottas som en struct som inneholder melding st?rrelse, en sjekksum og teksten. Ekstra: Alle meldinger sendt over udp forbindelsen skal ACK'es, bruk flytkontrollen "stop and wait" for ? f? til p?litelig overf?ring.

Publisert 25. jan. 2012 19:19