W12.PDF

(42 KB) Pobierz
w12.dvi
Wska¹niki do funkcji
{
void *temp;
/* Sortowanie numerycznie i leksykograficznie */
#include <stdio.h>
#include <string.h>
temp=v[i];
v[i]=v[j];
v[j]=temp;
}
#define MAXLINES 5000 /* maksymalna liczba wierszy
do sortowania */
char *lineptr[MAXLINES]; /* wskazniki do wierszy
tekstu */
#define MAXLEN 1000 /* dlugosc wiersza wejsciowego */
int getline(char *, int);
int readlines(char *lineptr[], int nlines);
void writelines(char *lineptr[], int nlines);
/* readlines: wczytaj wiersze z wejscia */
int readlines(char *lineptr[], int maxlines)
{
int len, nlines=0;
char *p, line[MAXLEN];
void qqsort(void *lineptr[], int left, int right,
int (*comp)(void *, void *));
int numcmp(const char *, const char *);
while ((len=getline(line, MAXLEN)) > 0)
if (nlines >= maxlines || (p=(char *)
malloc(len))==NULL)
/* uporzadkuj wiersze z wejscia */
main(int argc, char *argv[])
{
return -1;
else {
line[len-1]='\0'; /* usun znak nowego wiersza */
strcpy(p,line);
lineptr[nlines++]=p;
int nlines; /* liczba wszystkich wierszy */
int numeric=0; /* 1 - jesli sortowanie numeryczne */
if (argc > 1 && strcmp(argv[1], "-n") == 0)
numeric=1;
if ((nlines = readlines(lineptr, MAXLINES)) >= 0) {
qqsort((void **) lineptr, 0, nlines-1,
(int (*) (void *, void *))
(numeric ? numcmp : strcmp));
writelines(lineptr, nlines);
return 0;
} else {
printf("za duzo wierszy do sortowania\n");
return 1;
}
return nlines;
}
/* writelines: wypisz wiersze na wyjscie */
void writelines(char *lineptr[], int nlines)
{
int i;
for (i=0; i < nlines; i++)
printf("%s\n", lineptr[i]);
}
}
}
/* 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 (*comp)(void *, void *))
int c,i;
for (i=0; i<lim -1 && (c=getchar()) != EOF
&& c != '\n'; ++i)
{
int i,last;
void swap(void *v[], int, int);
if (left >= right) /* nic nie rob, jesli tablica*/
return; /* zawiera mniej niz dwa elementy */
swap(v, left, (left+right)/2);
last=left;
for (i=left+1; i<=right; i++)
if ((*comp)(v[i],v[left]) < 0)
swap(v, ++last, i);
swap(v, left, last);
qqsort(v, left, last-1, comp);
qqsort(v, last+1, right, comp);
s[i]=c;
if (c=='\n')
s[i]=c;
else
++i;
s[i]='\0';
return i;
}
Argumenty wska¹nikowe typu void *
Funkcja qqsort ma argumenty typu void * dla argumentów
wska¹nikowych. Za pomoca operacji rzutowania mo»na dowolny
wska¹nik przkesztaªci¢ do typu void * i z powrotem bez utraty
informacji.
}
#include <stdlib.h>
/* 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);
if (v1 < v2)
return -1;
else if (v1 > v2)
return 1;
else
return 0;
deklaruje wska¹nik do funkcji zwracajacej warto±¢ caªkowita.
Natomiast
int *comp(void *, void *)
}
mówi, »e comp jest funkcjazwracajaca 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
int (*daytab)[13] daytab: wska¹nik do tablica[13] o
elementach int
int *daytab[13] daytab: tablica[13] o elementach
wska¹nik do int
void *comp() comp: funkcja zwracajaca wska¹-
nik do void
void (*comp)() comp: wska¹nik do funkcja zwra-
cajaca void
char (*(*x())[])() x: funkcja zwracajaca wska¹nik do
tablica[] o elementach wska¹nik do
funkcja zwracajaca char
char (*(*x[3])())[5] x: tablica[3] o elementach wska¹-
nik do funkcja zwracajaca wska¹-
nik do tablica[5] o elementach char
Uproszczona posta¢ reguª skaªadniowych gramatyki wprowa-
dzajacej deklaratory:
return tokentype = BRACKETS;
} else if (isalpha(c)) {
for (*p++ = c; isalnum(c=getch()); )
*p++=c;
*p='\0';
ungetch(c);
return tokentype = NAME;
} else
return tokentype = c;
}
#define BUFSIZE 100 /* maks. rozmiar bufora */
char buf[BUFSIZE]; /* bufor na zwroty z ungetch */
int bufp=0; /* nastepne wolne miejsce w buforze */
deklarator:
opcjonalne * bezposredni-deklarator
int getch(void) /* wez znak, byc moze oddany na */
{
/* wejscie */
return (bufp > 0) ? buf[--bufp]:getchar();
}
bezposredni-deklarator:
nazwa
(deklarator)
bezposredni-deklarator()
bezposredni-deklarator[opcjonalny rozmiar]
void ungetch(int c) /* oddaj znak z powrotem na */
{
/* wejscie */
if (bufp >= BUFSIZE)
printf("ungetch: za wiele zwrotow\n");
else
buf[bufp++]=c;
}
Przykªad (program rozszyfrowujacy proste deklaracje):
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAXTOKEN 100
/* dcl: analiza skladniowa deklaratora */
void dcl(void)
{
int ns;
for (ns=0; gettoken()=='*';) /* zlicza *-i */
ns++;
dirdcl();
while (ns-- > 0)
strcat(out, "wskaznik do");
enum ( NAME, PARENS, BRACKETS };
void dcl(void);
void dirdcl(void);
int gettoken(void);
int tokentype; /* typ ostatniego elementu */
char token[MAXTOKEN]; /* tekst ostatniego elementu */
char name[MAXTOKEN]; /* nazwa wystepujaca w dekl. */
char datatype[MAXTOKEN]; /*typ danych: char,int,itp.*/
char out[1000];
}
/* dirdcl: analiza skladniowa bezposredniego
deklaratora */
/* wyjsciowy opis slowny */
void dirdcl(void)
{
main() /* dcl: zamien deklaracje C na opis slowny */
{
int type;
if (tokentype == '(') { /* (deklarator) */
dcl();
if (tokentype != ')')
printf("blad: brak nawiasu )\n");
} else if (tokentype == NAME) /* nazwa zmiennej */
strcpy(name, token);
while (gettoken() != EOF) {/* pierwszy leksem w */
strcpy(datatype, token) /* wierszu jest typem*/
out[0]='\0'; /* danych */
dcl(); /* analiza skladniowa reszty wiersza */
if (tokentype != '\n')
printf("blad skladniowy\n");
printf("%s: %s %s\n", name, out, datatype);
else
printf("blad: spodziewana nazwa lub"
" (deklarator)\n");
while (type=gettoken())==PARENS || type==BRACKETS)
if (type == PARENS) /* para nawiasow () */
strcat(out,"funkcja zwracajaca");
else { /* para nawiasow [] */
strcat(out, " tablica");
strcat(out,token); /* ew. rozmiar */
strcat(out," o elementach");
}
return 0;
}
int gettoken(void) /* podaj nastepny leksem */
{
int c, getch(void);
void ungetch(int );
}
while ((c=getch()) == ' ' || c == '\t')
;
if (c == '(') {
if ((c=getch()) == ')') {
strcpy(token, "()");
return tokentype = PARENS;
} else {
ungetch(c);
return tokentype = '(';
}
Zmienna dªugo±¢ list argumentów
#include <stdio.h>
#include <stdarg.h>
/* minprintf: minimalna printf ze zmienna
liczba argumentow */
void minprintf(char *fmt, ... )
{
}
} else if (c == '[') {
for (*p++ = c; (*p++ = getch()) != ')';)
;
*p='\0';
va_list ap; /* wskazuje po kolei kazdy nienazwany*/
char *p, *sval;
/* argument */
int ival;
double dval;
va_start(ap, fmt); /* ap wskazuje pierwszy nienaz-
wany 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 zdeniowane 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 zapewniaja przenaszalny sposób dostepu do
zmiennych list argumentów.
va_start ustawia wska¹nik do pierwszego nienazwanego
argumentu przekazanego do funkcji
va_arg rozszerza sie do wyra»enia majacego ten sam typ
i warto±¢ jak nastepny 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;
}
Zgłoś jeśli naruszono regulamin