2.7. Flere små programmer og øvelsesforslag.

For at demonstrere styrken af små 10-24 linjers programmer ("Hallo-programmer") kommer her en serie sådanne små særlinge.

2.7.1. Tal formatering ved udskrift med printf.

Her kommer kildeteksten til et program, som kan skrive en listing af tallene fra 0 til 7, inverteret og som 2's complement. (Som lovet i Eksempel 1-2).

Eksempel 2-26. Tallene fra 0 til 7 i hexadecimal notation.


/* bitinvert.c viser hexadeximalt tallene fra 0 - 8  */
/* og desuden invertering, og såkaldt 2-s complement */

#include <stdio.h>


char    *thisprg;

int main(int argc, char *argv[])
{
   int jj;

   thisprg = argv[0];

   for (jj=0;jj<8;++jj) {
     printf("Word: %08x, Inverted: %08x, Complement: %08x\n",jj,~jj,~jj+1);
   }
   return 0;
}

/* end bitinvert.c */

2.7.2. Word count - med tak til Kernighan & Ritchie

Her er en simpel variant af Kernighan & Ritchie's word count program. Det er en ultra simpel tilstandsmaskine. Den har kun to tilstande, enten er den i HVID tilstand, eller i SORT.

Hvis den er i HVID tilstand, har den læst et bogstav, som var whitespace, d.v.s. typisk space eller newline eller tab. Hvis den er i SORT tilstand, har den læst et tegn, som kræver tryksværte - eller rettere, et, som ikke er et whitespace tegn.

Programmet skelner altså ikke mellem ord og tal eller tegnsætning. Det anser bogstaver mellem to spaces for at være et ord! Så simpel en ord-tællingsmekanisme kan såmænd da være meget anvendelig i mange sammenhæng, f.eks. echo * | ordtael vil vise, hvor mange filer, der er i det aktuelle katalog. Det er grundlaget for det lidt mere avancerede program Eksempel 2-25 som kan skelne mellem ord og tal og skilletegn.

Eksempel 2-27. Simpel ordtælling


/*file wc.c */

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

int nc, nw, nl;  /* static vars garanteret 0 */

enum status_t { HVID, SORT };

enum status_t status;

int main()
{
    int c;
    while ( (c=getchar()) != EOF) {
        ++nc;
        if (c == '\n')
            ++nl;
        if (isspace(c))
            status = HVID;
        else                           /* <--- SE kommentar!!!*/
            if (status == HVID) {
                status = SORT;
                ++nw;
            }
    }
    printf("%d %d %d\n", nc, nw, nl);
    /* lav en version, der KUN taeller ord! */
    return 0;
}

/* end of file wc.c */

Læg mærke til, at programmet altid tæller characters, når der er læst en. Hvis det er en newline, så tæller vi linjer. Klart nok. Hvis det nu er en slags space (eller newline, tab, backspace, vertical tab, formfeed ...) så lader vi den gå i HVID-tilstand.

Den efterfølgende ELSE er kernepunktet for forståelse. Hvad ved vi, hvis vi havner i ELSE-sætningen? Jo, vi ved, at vores nys indlæste character IKKE var hvid.

Hvad ved vi så, hvis STATUS er lig med HVID, og vores nys indlæste bogstav var sort?

Joda, ... giv dig tid!

Så ved vi, at det foregående bogstav var hvidt (altså space) og at det nuværende er sort, altså, det første bogstav i et ord. Så derfor skifter vi tilstand til sort og tæller det nye ord med.

Så vores tilstandsvariabel status er meget praktisk, fordi den kan huske for os, hvad det foregående bogstav var, eller i bredere forstand, hvilken slags bogstav det var, og dermed hvilken tilstand vores tællemaskine var i.

Det er et program, som er sindssygt svært at forstå for en begynder, som heller ikke har erfaring med andre sprog. Sådan er det forresten altid når if-sætninger gror oven i hinanden. Hvis du har arbejdet dig igennem læsning af programmet og - bedre - har fået det til at køre, evt. med dine egne tilføjelser, så du kan se, hvad der sker undervejs, så har du taget et stort skridt fremad indenfor programmering (og logisk tænkning).