I originally started out with just a self taught lesson on manipulating bit fields, but
instead most of my work was getting weaned off of the scanf() when reading strings.
When I moved the print_records and enter_records to their own function, now there's
hardly anything left in main()!
I got an unexpected bonus: I'm going to extract the fgets() reads and create a function
to read in strings in all of my future programs.
I've tried to break this code for overflow, etc. Special thanks to Kermit also, I did a
search on the scanf() problem and he posted a link on another thread. So I used that
and bookmarked.
Here's my updated code. Any comments always welcomed.
Code:
// 9/15/10
//
// practice using bit fields inside structures
// while at the same time using Cprogramming.com approved I/O functions.
//
// As it turned out, 95% of my effort was in dealing with stdin & replacement functions
// for scanf() and gets().
// http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?answer=1044652485&id=1043284385
//
#include <stdio.h>
#include <string.h>
#define YES 1;
#define NO 0;
#define MAX 5 // <--- set upper limit for # records here.
#define MAX_NAME 20
#define MAX_SSNMBR 12
struct emp_data
{
unsigned char
health : 2, // width for 4 possible types of health coverage
dental : 1,
college : 1;
char fname[MAX_NAME];
char lname[MAX_NAME];
char ssnumber[MAX_SSNMBR];
};
struct emp_data workers[MAX];
int enter_records( struct emp_data *, int ); // enters data into employee records
void print_records( struct emp_data *, int ); // prints out all employee records
int main( void )
{
struct emp_data *pemp = workers; // create a pointer to type emp_data & initialize
int return_code;
return_code = enter_records( pemp, MAX );
if (return_code != 0)
return 1; // Error msg already printed out
print_records( pemp, MAX );
return 0;
}
int enter_records( struct emp_data *qptr, int max)
{
void *ptr; // declaring a generic pointer
unsigned bit;
char *p;
int count;
char buf[BUFSIZ];
size_t name_max = MAX_NAME;
size_t ssnumbr_max = MAX_SSNMBR;
for( count=0; count<max; count++ )
{
qptr->dental = NO; // initialize all bit fields
qptr->college = NO;
qptr->health = NO;
{
printf("\nEnter first name: ");
ptr = fgets(buf, BUFSIZ, stdin); // enters string from stdin
if ( ptr == NULL ) // check for error
{
printf("Error entering fname\n\n"); // Funtionality tested OK when entered cntrl^z
return 1;
}
if ((p = strchr(buf, '\n')) != NULL) // get rid of that '\n' from the FAQ
*p = '\0';
strncpy( qptr->fname, buf, name_max - 1 ); // only copys name_max-1 chars to destination from buf.
}
{
printf("Enter last name: ");
ptr = fgets(buf, BUFSIZ, stdin);
if ( ptr == NULL )
{
printf("Error entering lname\n\n"); // Abort if error
return 1;
}
if ((p = strchr(buf, '\n')) != NULL)
*p = '\0';
strncpy( qptr->lname, buf, name_max - 1 );
}
do
{
printf("\nEnter Dental 1 or 0\n"); // toggle the 1-bit fields
scanf("%u", &bit );
if( bit == 1 )
qptr->dental = YES;
} while ( bit > 1 );
do
{
printf("\nEnter College 1 or 0\n");
scanf("%u", &bit );
if( bit == 1 )
{
qptr->college = YES;
}
} while ( bit > 1 );
do
{
printf("\nEnter Health 0 - 3\n"); // 2-bit field
scanf("%u", &bit );
switch ( bit) // determine which health bits to set
{
case 0:
{
qptr->health |= bit;
break;
}
case 1:
{
qptr->health |= bit;
break;
}
case 2:
{
qptr->health |= bit;
break;
}
case 3:
{
qptr->health |= bit;
break;
}
default:
{
printf("Invalid entry for health\n");
}
}
} while ( bit > 3 );
{
while (getchar() != '\n'); // clear stdin newline
printf("\nEnter SS Number:\n");
ptr = fgets(buf, BUFSIZ, stdin);
if ( ptr == NULL )
{
printf("Error entering ssnumber\n\n"); // Abort if error
return 1;
}
if ((p = strchr(buf, '\n')) != NULL)
*p = '\0';
strncpy( qptr->ssnumber, buf, ssnumbr_max - 1 );
}
qptr++; // point to the next empty data record
}
return 0;
}
void print_records( struct emp_data *sptr, int size )
{
int count;
for( count=0; count<size; count++ ) // print out the records entered
{
printf("\n\n%s %s\n", sptr->fname, sptr->lname);
printf("dental= %d\tCollege= %d\tHealth= %d\tSS Number= %s\n",
sptr->dental, sptr->college, sptr->health, sptr->ssnumber);
sptr++; // point to the next data record
}
printf("\n");
}