
ifstream in(DATAFILE);
if (!in)
{
cerr << "Can't open " << DATAFILE <<" for reading\n";
return(-1);
}
in >> numstudents; // Using the >> operator - again, just
// like standard i/o
if (numstudents > MAXSTUDENTS)
{
cerr << "Too many database entries\n";
return(-1);
}
for(int i = 0; i < numstudents; i++)
{
in >> pstudent[i].name;
in >> pstudent[i].id;
in >> pstudent[i].mark;
}
in.close();
pstudent[numstudents].id = 0; // Sentinel
return(0);
}
Note that main will have to be modified to take account of the return
value from load_data and abort the program if that value is less than 0.
We often don’t know how much memory will be required until run-
time. It might depend on the size of a database, the number of iterations
of an algorithm, the volume of incoming data. We need a mechanism
to ask for memory from the operating system as and when needed. In
C, the program requests memory using the new operator which
‘returns’ a pointer to the start of allocated memory. For example, to
allocate a new student structure:
student *pstudent;
pstudent = new student;
pstudent
points to a newly allocated student structure, which can be
used as required. When no longer needed, the memory would be
returned to free store with:
delete pstudent;
Allocating arrays of objects is easy.
student *pstudent;
pstudent = new student[numstudents];
Beginning programming in C 105
Review the second exercise on page 95. The above function has
a similar bug to the one lurking there. You need to think about
this with the aid of the struct student definition on page 103.
See what the bug is? More clues on page 129.
4.20 Memory allocation

And now pstudent is the start address of a block of memory that can
be used as if it were a numstudents long array of student structures.
The memory would be released with
delete [] pstudent;
The use of the array brackets in the delete statement ensures that the
whole array of items is deleted and not just the first.
Every pointer value used in a delete statement must have been
returned by an earlier use of new. When a program terminates, all
allocated memory is returned to the operating system anyway, but it is
standard practice explicitly to delete everything allocated with new.
Here is a complete program to read in a student database and cal-
culate the average mark. Some of the functions have been changed
from those given above.
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
#define MAXSTUDENTS 80
#define MAXNAMELENGTH 30
struct student
{
char name[MAXNAMELENGTH];
long id;
float mark;
};
float average_mark(int num_students, student *p);
int load_data(char *fname, student **pp);
int main(int argc, char **argv)
{
student *syde321; // Will point to the base of the array of
// structures
106 Software Design for Engineers and Scientists
What if new fails?
If new cannot get the memory you asked for, it throws an exception. We haven’t discussed exceptions yet (see
page 160), but, in the meantime, there are alternatives. First, you can rely on the default exception handling
mechanism – if an exception isn’t caught, the program terminates.This could well be the right thing for a failure
with
new:exhausting the memory is very unusual, and making your program work around it could be impossible.
Alternatively you could use the
nothrow version of new like this:
pstudent = new(nothrow) student[numstudents];
if (pstudent == 0) {
cerr << "Allocation failed! Panic!" << endl;
return -1;
}
When the nothrow version of new cannot allocate the required memory it returns value 0.This can be tested as
above, and be handled in the calling code.

int num_students;
if (argc != 2)
{
cerr << "Usage: average filename\n";
return(-1);
}
if ((num_students = load_data(*(argv+1),&syde321)) < 0)
return(-1);
cout << "Average was " << average_mark(num_students,
syde321) << '\n';
return(0);
}
float average_mark(int num_students, student *p)
{
int i;
float sum_marks;
sum_marks = 0.0;
for (i = 0; i < num_students; i++)
sum_marks += p[i].mark;
// Remember, a pointer passed to a function can
// be treated like the start address of an array.
return(sum_marks/num_students);
}
int load_data(char *fname, student **pp)
{
char c;
student *memory;
unsigned int numstudents;
ifstream in(fname);
if (!in)
{
cerr << "Can't open " << fname << " for reading\n";
return(-1);
}
in >> numstudents;
if (numstudents > MAXSTUDENTS)
{
cerr << "Too many database entries\n";
return(-1);
}
memory = new student[numstudents];
// Memory is allocated here
// Don't catch bad_alloc exception from new: Just exit if
// memory exhausted.Write into student pointer
*pp = memory;
for(int i = 0; i < numstudents; i++)
{
in >> memory[i].name;
in >> memory[i].id;
Beginning programming in C 107
Get Software Design for Engineers and Scientists now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.