C provides the means to group together variables under one name providing a convenient means of keeping related information together and providing a structured approach to data.
The general form for a structure definition is;
typedef struct
{
variable_type variable_name;
variable_type variable_name;
}
structure_name;
When accessing data files, with a fixed record structure, the
use of a structure variable becomes essential. The following example shows a
record structure for a very simple name and address file. It declares a data
structure called 'data', and comprised of six fields; 'name', 'address', 'town',
'county' , 'post' and 'telephone'.
typedef struct
{
char name[30];
char address[30];
char town[30];
char county[30];
char post[12];
char telephone[15];
}
data;
The structure 'data' may then be used in the program as a
variable data type for declaring variables;
data record;
Thus declares a variable called 'record' to be of type 'data'.
The individual fields of the structure variable are accessed
by the general form;
structure_variable.field_name;
Thus, the name field of the structure variable record is
accessed with;
record.name
There is no limit to the number of fields that may comprise a
structure, nor do the fields have to be of the same types, for example;
typedef struct
{
char name[30];
int age;
char *notes;
}
dp;
Declares a structure 'dp' that is comprised of a character
array field, an integer field and a character pointer field.
A structure variable may be passed as a parameter by passing
the address of the variable as the parameter with the & operator thus;
func(&my_struct)
The following is an example program that makes use of a
structure to provide the basic access to the data in a simple name and address
file;
/* A VERY simple address book written in ANSI C */
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <string.h>
#include <fcntl.h>
#include <sys\stat.h>
/* num_lines is the number of screen display lines */
#define num_lines 25
typedef struct
{
char name[30];
char address[30];
char town[30];
char county[30];
char post[12];
char telephone[15];
}
data;
data record;
int handle;
/* Function prototypes */
void ADD_REC(void);
void CLS(void);
void DISPDATA(void);
void FATAL(char *);
void GETDATA(void);
void MENU(void);
void OPENDATA(void);
int SEARCH(void);
void CLS()
{
int n;
for(n = 0; n < num_lines; n++)
puts("");
}
void FATAL(char *error)
{
printf ("\nFATAL ERROR: %s",error);
exit(0);
}
void OPENDATA()
{
/* Check for existence of data file and if not create it */
/* otherwise open it for reading/writing at end of file */
handle = open("address.dat",O_RDWR|O_APPEND,S_IWRITE);
if (handle == -1)
{
handle = open("address.dat",O_RDWR|O_CREAT,S_IWRITE);
if (handle == -1)
FATAL("Unable to create data file");
}
}
void GETDATA()
{
/* Get address data from operator */
CLS();
printf ("Name ");
gets(record.name);
printf ("\nAddress ");
gets(record.address);
printf ("\nTown ");
gets(record.town);
printf ("\nCounty ");
gets(record.county);
printf ("\nPost Code ");
gets(record.post);
printf ("\nTelephone ");
gets(record.telephone);
}
void DISPDATA()
{
/* Display address data */
char text[5];
CLS();
printf ("Name %s",record.name);
printf ("\nAddress %s",record.address);
printf ("\nTown %s",record.town);
printf ("\nCounty %s",record.county);
printf ("\nPost Code %s",record.post);
printf
("\nTelephone %s\n\n",record.telephone);
puts("Press RETURN to continue ");
gets(text);
}
void ADD_REC()
{
/* Insert or append a new record to the data file */
int result;
result = write(handle,&record,sizeof(data));
if (result == -1)
FATAL("Unable to write to data file");
}
int SEARCH()
{
char text[100];
int result;
printf ("Enter data to search for ");
gets(text);
if (*text == 0)
return(-1);
/* Locate start of file */
lseek(handle,0,SEEK_SET);
do
{
/* Read record into memory */
result = read(handle,&record,sizeof(data));
if (result > 0)
{
/* Scan record for matching data */
if (strstr(record.name,text) != NULL)
return(1);
if (strstr(record.address,text) != NULL)
return(1);
if (strstr(record.town,text) != NULL)
return(1);
if (strstr(record.county,text) != NULL)
return(1);
if (strstr(record.post,text) != NULL)
return(1);
if (strstr(record.telephone,text) != NULL)
return(1);
}
}
while(result > 0);
return(0);
}
void MENU()
{
int option;
char text[10];
do
{
CLS();
puts("\n\t\t\tSelect Option");
puts("\n\n\t\t\t1 Add new record");
puts("\n\n\t\t\t2 Search for data");
puts("\n\n\t\t\t3 Exit");
puts("\n\n\n\n\n");
gets(text);
option = atoi(text);
switch (option)
{
case 1 : GETDATA();
/* Go to end of file to append new record */
lseek(handle,0,SEEK_END);
ADD_REC();
break
;
case 2 : if (SEARCH())
DISPDATA();
else
{
puts("NOT FOUND!");
puts("Press RETURN to continue ");
gets(text);
}
break
;
case 3 : break ;
}
}
while(option != 3);
}
void main()
{
CLS();
OPENDATA();
MENU();
}
C allows the inclusion of variables with a size of less than eight bits to be included in structures. These variables are known as bit fields, and may be any declared size from one bit upwards.
The general form for declaring a bit field is;
type name : number_of_bits;
For example, to declare a set of status flags, each occupying
one bit;
typedef struct
{
unsigned carry : 1;
unsigned zero : 1;
unsigned over : 1;
unsigned parity : 1;
}
df;
df flags;
The variable 'flags' then occupies only four bits in memory,
and yet is comprised of four variables that may be accessed like any other
structure field.
Another facility provided by C for efficient use of available memory is the union structure. A union structure is a collection of variables that all share the same memory storage address. As such only one of the variables is ever accessible at a time.
The general form of a union definition is;
union name
{
type variable_name;
type variable_name;
.
.
.
type variable_name;
};
Thus, to declare a union structure for two integer variables;
union data
{
int vara;
int varb;
};
and to declare a variable of type 'data';
data my_var;
The variable 'my_var' is then comprised of the two variables 'vara'
and 'varb' that are accessed like with any form of structure, eg;
my_var.vara = 5;
Assigns a value of 5 to the variable 'vara' of union 'my_var'.
An enumeration assigns ascending integer values to a list of
symbols. An enumeration declaration takes the general form;
enum name { enumeration list } variable_list;
Thus to define a symbol list of colours, you can say;
enum COLOURS
{
BLACK,
BLUE,
GREEN,
CYAN,
RED,
MAGENTA,
BROWN,
LIGHTGRAY,
DARKGRAY,
LIGHTBLUE,
LIGHTGREEN,
LIGHTCYAN,
LIGHTRED,
LIGHTMAGENTA,
YELLOW,
WHITE
};
Then, the number zero may be referred to by the symbol BLACK,
the number one by the symbol BLUE, the number two by the symbol GREEN and so on.
The following program illustrates the use of an enumeration
list to symbolise integers;
#include <stdio.h>
enum COLOURS
{
BLACK,
BLUE,
GREEN,
CYAN,
RED,
MAGENTA,
BROWN,
LIGHTGRAY,
DARKGRAY,
LIGHTBLUE,
LIGHTGREEN,
LIGHTCYAN,
LIGHTRED,
LIGHTMAGENTA,
YELLOW,
WHITE
};
void main()
{
int x;
x = RED;
printf
("\nVariable 'x' holds %d",x);
}
File Input/Output through streaming.
Links: Home C Programming Guide C++ programming Guide