Wskaźniki do funkcji

{

void *temp;

/* Sortowanie numerycznie i leksykograficznie */

temp=v[i];

#include <stdio.h>

v[i]=v[j];

#include <string.h>

v[j]=temp;

}

#define MAXLINES 5000 /* maksymalna liczba wierszy do sortowania */

#define MAXLEN 1000 /* dlugosc wiersza wejsciowego */

char *lineptr[MAXLINES];

/* wskazniki do wierszy

int getline(char *, int);

tekstu */

/* readlines: wczytaj wiersze z wejscia */

int readlines(char *lineptr[], int nlines); int readlines(char *lineptr[], int maxlines) void writelines(char *lineptr[], int nlines);

{

int len, nlines=0;

void qqsort(void *lineptr[], int left, int right, char *p, line[MAXLEN];

int (*comp)(void *, void *));

int numcmp(const char *, const char *);

while ((len=getline(line, MAXLEN)) > 0) if (nlines >= maxlines || (p=(char *)

/* uporzadkuj wiersze z wejscia */

malloc(len))==NULL)

main(int argc, char *argv[])

return -1;

{

else {

int nlines; /* liczba wszystkich wierszy */

line[len-1]=’\0’; /* usun znak nowego wiersza */

int numeric=0; /* 1 - jesli sortowanie numeryczne */

strcpy(p,line);

lineptr[nlines++]=p;

if (argc > 1 && strcmp(argv[1], "-n") == 0)

}

numeric=1;

return nlines;

if ((nlines = readlines(lineptr, MAXLINES)) >= 0) {

}

qqsort((void **) lineptr, 0, nlines-1,

(int (*) (void *, void *))

/* writelines: wypisz wiersze na wyjscie */

(numeric ? numcmp : strcmp));

void writelines(char *lineptr[], int nlines) writelines(lineptr, nlines);

{

return 0;

int i;

} else {

for (i=0; i < nlines; i++)

printf("za duzo wierszy do sortowania\n"); printf("%s\n", lineptr[i]);

return 1;

}

}

}

/* getline: wczytaj wiersz do s, podaj jego dlugosc */

int getline(char s[], int lim)

/* qsort: uporzadkuj v[left] ... v[right] rosnaco */

{

void qqsort(void *v[], int left, int right, int c,i;

int (*comp)(void *, void *))

for (i=0; i<lim -1 && (c=getchar()) != EOF

{

&& c != ’\n’; ++i)

int i,last;

s[i]=c;

void swap(void *v[], int, int);

if (c==’\n’)

if (left >= right) /* nic nie rob, jesli tablica*/

s[i]=c;

return;

/* zawiera mniej niz dwa elementy */

else

swap(v, left, (left+right)/2);

++i;

last=left;

s[i]=’\0’;

for (i=left+1; i<=right; i++)

return i;

if ((*comp)(v[i],v[left]) < 0)

}

swap(v, ++last, i);

swap(v, left, last);

qqsort(v, left, last-1, comp);

Argumenty wskaźnikowe typu void *

qqsort(v, last+1, right, comp);

}

Funkcja qqsort ma argumenty typu void * dla argumentów wskaźnikowych. Za pomoc¸

a operacji rzutowania można dowolny

#include <stdlib.h>

wskaźnik przkeształcić do typu void * i z powrotem bez utraty informacji.

/* numcmp: porownaj numerycznie s1 i s2 */

int numcmp(const char *s1, const char *s2) Deklaracja

{

double v1,v2;

int (*comp) (void *, void *)

v1=atof(s1);

v2=atof(s2);

deklaruje wskaźnik do funkcji zwracaj¸

acej wartość całkowit¸

a.

if (v1 < v2)

Natomiast

return -1;

else if (v1 > v2)

return 1;

int *comp(void *, void *)

else

return 0;

}

mówi, że comp jest funkcj¸

a zwracaj¸

ac¸

a wskaźnik do obiektów

całkowitych.

Skomplikowane deklaracje

void swap(void *v[], int i, int j)

Przykłady:

char **argv

argv: wskaźnik do wskaźnik do char

return tokentype = BRACKETS;

int (*daytab)[13]

daytab: wskaźnik do tablica[13] o

} else if (isalpha(c)) {

elementach int

int *daytab[13]

daytab: tablica[13] o elementach

for (*p++ = c; isalnum(c=getch()); )

wskaźnik do int

*p++=c;

void *comp()

comp: funkcja zwracaj¸

aca wskaź-

*p=’\0’;

nik do void

ungetch(c);

void (*comp)()

comp: wskaźnik do funkcja zwra-

return tokentype = NAME;

caj¸

aca void

char (*(*x())[])()

x: funkcja zwracaj¸

aca wskaźnik do

} else

tablica[] o elementach wskaźnik do

return tokentype = c;

funkcja zwracaj¸

aca char

}

char (*(*x[3])())[5]

x: tablica[3] o elementach wskaź-

nik do funkcja zwracaj¸

aca wskaź-

#define BUFSIZE 100

/* maks. rozmiar bufora */

nik do tablica[5] o elementach char

char buf[BUFSIZE];

/* bufor na zwroty z ungetch */

Uproszczona postać reguł skaładniowych gramatyki wprowa-int bufp=0;

/* nastepne wolne miejsce w buforze */

dzaj¸

acej deklaratory:

int getch(void) /* wez znak, byc moze oddany na */

deklarator:

{

/*

wejscie */

opcjonalne * bezposredni-deklarator

return (bufp > 0) ? buf[--bufp]:getchar();

}

bezposredni-deklarator:

nazwa

void ungetch(int c) /* oddaj znak z powrotem na */

(deklarator)

{

/*

wejscie */

bezposredni-deklarator()

if (bufp >= BUFSIZE)

bezposredni-deklarator[opcjonalny rozmiar]

printf("ungetch: za wiele zwrotow\n"); else

buf[bufp++]=c;

}

Przykład (program rozszyfrowuj¸

acy proste deklaracje):

#include <stdio.h>

/* dcl: analiza skladniowa deklaratora */

#include <string.h>

void dcl(void)

#include <ctype.h>

{

#define MAXTOKEN 100

int ns;

for (ns=0; gettoken()==’*’;) /* zlicza *-i */

enum ( NAME, PARENS, BRACKETS };

ns++;

dirdcl();

void dcl(void);

while (ns-- > 0)

void dirdcl(void);

strcat(out, "wskaznik do");

int gettoken(void);

}

int tokentype;

/* typ ostatniego elementu

*/

char token[MAXTOKEN]; /* tekst ostatniego elementu */

/* dirdcl: analiza skladniowa bezposredniego char name[MAXTOKEN];

/* nazwa wystepujaca w dekl. */

deklaratora */

char datatype[MAXTOKEN]; /*typ danych: char,int,itp.*/

void dirdcl(void)

char out[1000];

/* wyjsciowy opis slowny */

{

int type;

main()

/* dcl: zamien deklaracje C na opis slowny */

if (tokentype == ’(’) {

/* (deklarator) */

{

dcl();

while (gettoken() != EOF) {/* pierwszy leksem w */

if (tokentype != ’)’)

strcpy(datatype, token)

/* wierszu jest typem*/

printf("blad: brak nawiasu )\n"); out[0]=’\0’;

/* danych */

} else if (tokentype == NAME) /* nazwa zmiennej */

dcl();

/* analiza skladniowa reszty wiersza */

strcpy(name, token);

if (tokentype != ’\n’)

else

printf("blad skladniowy\n");

printf("blad: spodziewana nazwa lub"

printf("%s: %s %s\n", name, out, datatype);

" (deklarator)\n");

}

while (type=gettoken())==PARENS || type==BRACKETS) return 0;

if (type == PARENS)

/* para nawiasow () */

}

strcat(out,"funkcja zwracajaca"); else {

/* para nawiasow [] */

int gettoken(void) /* podaj nastepny leksem */

strcat(out, " tablica");

{

strcat(out,token);

/* ew. rozmiar */

int c, getch(void);

strcat(out," o elementach");

void ungetch(int );

}

}

while ((c=getch()) == ’ ’ || c == ’\t’)

;

if (c == ’(’) {

if ((c=getch()) == ’)’) {

Zmienna długość list argumentów

strcpy(token, "()");

return tokentype = PARENS;

} else {

#include <stdio.h>

ungetch(c);

#include <stdarg.h>

return tokentype = ’(’;

/* minprintf: minimalna printf ze zmienna

}

liczba argumentow */

} else if (c == ’[’) {

void minprintf(char *fmt, ... )

for (*p++ = c; (*p++ = getch()) != ’)’;)

{

;

va_list ap; /* wskazuje po kolei kazdy nienazwany*/

*p=’\0’;

char *p, *sval;

/*

argument */

int ival;

double dval;

va_start(ap, fmt); /* ap wskazuje pierwszy nienazwany argument;

fmt - ostatni nazwany argument */

for (p=fmt; *p; p++) {

if (*p != ’%’) {

putchar(*p);

continue;

}

switch(*++p) {

case ’d’:

ival = va_arg(ap, int);

printf("%d",ival);

break;

case ’f’:

dval=va_arg(ap, double);

printf("%f",dval);

break;

case ’s’:

for (sval=va_arg(ap, char *); *sval; sval++) putchar(*sval);

break;

default:

putchar(*p);

break;

}

}

va_end(ap); /* po pracy wyczysc po sobie */

}

Trzy makra zdefiniowane w <stdarg.h>: va_start(va_list ap, lastfix);

type va_arg(va_list ap, type);

void va_end(va_list ap);

va_list

-

tablica, ktora przechowuje informacje

potrzebne dla va_arg i va_end

va_arg i va_start zapewniaj¸

a przenaszalny sposób dost¸

epu do

zmiennych list argumentów.

• va_start ustawia wskaźnik do pierwszego nienazwanego argumentu przekazanego do funkcji

• va_arg rozszerza si¸e do wyrażenia maj¸acego ten sam typ i wartość jak nast¸

epny przekazany argument

• va_end pomaga funkcji wykonać normalny powrót Przykład (sumowanie liczb):

#include <stdio.h>

#include <stdarg.h>

/* calculate sum of a 0 terminated list */

void sum(char *msg, ...)

{

int total = 0;

va_list ap;

int arg;

va_start(ap, msg);

while ((arg = va_arg(ap,int)) != 0) {

total += arg;

}

printf(msg, total);

va_end(ap);

}

int main(void) {

sum("The total of 1+2+3+4 is %d\n", 1,2,3,4,0); return 0;

}