11. előadás
A szoftver komponenseknek kiszámítható módon kell kommunikálnia az őt használó többi komponensel. A komponens ezen felületét interfésznek nevezzük.
A kliensek ezen a felületen keresztül érik el a szolgáltatásokat, melyeknek megvalósítása az implementáció.
Példa egy ilyen komponensre:
struct date
{
int year;
int month;
int day;
};
void f(void)
{
/* inicializálás, ellenőrzi az egyes mezők értékeit */
struct date exam = dateCreate(2019, 12, 17);
dateNext(&exam); /* egy nappal elhalasztva */
dateAdd(&exam,40); /* lekezeli a hónap végét */
}
Interfész definíció (header fájl):
/* date.h */
#ifndef DATE_H
#define DATE_H
#define EOK 0 /* ok */
#define ENOMEM 1 /* unable to allocate memory */
#define EINVALID 2 /* invalid date */
#define ENEGDAY 3 /* negative day for dateAdd */
struct DATE;
typedef struct DATE *date_t; /* forward deklaráció */
extern int dateError; /* error handling */
date_t dateCreate( int y, int m, int d);
void dateDestroy(date_t dp);
int dateSet( date_t dp, int y, int m, int d);
void dateNext( date_t dp);
int dateAdd( date_t dp, int n);
int dateGetYear(date_t dp);
int dateGetMonth(date_t dp);
int dateGetDay(date_t dp);
#endif /* DATE_H */
Pointer lett átadva, aminek a mérete majd később lesz deffiniálva.
A függvények megfelelőek így, hiszen a pointer mérete konzisztens, viszont nem alkalmazható rá a pointer arithmetika, mert a típus nem teljes(mérete nem ismert)
Implementáció egy külön fájlba kerül:
/* date.c */
#include <stdio.h>
#include <stdlib.h>
#include "date.h"
struct DATE
{
int year;
int month;
int day;
};
/* napok száma az adott hónapban, kiv. szökőév */
static const int dOfm[] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
/* y szökőév? */
static int leapYear( int y)
{
/* TODO implementálni!!! */
return 0;
}
/* napok tényleges száma az év/hónapban */
static int daysOfMonth( int y, int m)
{
int maxDay = dOfm[m-1]; /* tömb 0-tól indexelődik */
if ( 2 == m && leapYear(y) )
++maxDay; /* szökőév */
return maxDay;
}
/* helyes dátum-e az (y, m, d) hármas? */
static int checkDate(int y, int m, int d)
{
return 0 != y &&
1 <= m && m <= 12 &&
1 <= d && d <= daysOfMonth(y, m);
}
/* interfész: hibakezelés */
int dateError = EOK;
/* interfész függvények */
date_t dateCreate( int y, int m, int d)
{
date_t dp;
if ( ! checkDate( y, m, d) )
{
dateError = EINVALID;
return NULL;
}
if (NULL == (dp = (date_t) malloc(sizeof(struct DATE)) ))
{
dateError = ENOMEM;
return NULL;
}
dp->year = y;
dp->month = m;
dp->day = d;
dateError = EOK;
return dp;
}
void dateDestroy( date_t dp)
{
free(dp);
}
int dateSet( date_t dp, int y, int m, int d)
{
if ( ! checkDate( y, m, d) )
{
dateError = EINVALID;
return 0;
}
dp->year = y;
dp->month = m;
dp->day = d;
dateError = EOK;
return 1;
}
int dateGetYear( date_t dp)
{
dateError = EOK;
return dp->year;
}
int dateGetMonth( date_t dp)
{
dateError = EOK;
return dp->month;
}
int dateGetDay( date_t dp)
{
dateError = EOK;
return dp->day;
}
void dateNext( date_t dp)
{
++dp->day;
if ( dp->day > daysOfMonth( dp->year, dp->month) )
{
dp->day = 1;
++dp->month;
if ( 13 == dp->month )
{
dp->month = 1;
++dp->year;
if ( 0 == dp->year )
{
++dp->year;
}
}
}
dateError = EOK;
}
int dateAdd( date_t dp, int n)
{
int i;
if ( n < 0 )
{
dateError = ENEGDAY;
return 0;
}
for ( i = 0; i < n; ++i )
{
dateNext( dp);
}
dateError = EOK;
return 1;
}