cannot compile the following example code (person-pointer)

  • Thread starter =?ISO-8859-1?Q?Martin_J=F8rgensen?=
  • Start date
D

Daniel T.

Martin Jørgensen said:
int main()
{
void bsort(person**, int); //prototype
PersonArray persons; //persons-array...
char choice; //input char
bool success;

while( success = persons.addperson() )
{
cout << "Enter another (y/n)? ";
cin >> choice;
if(choice == 'n')
break;
}

/* is the array full ? */
if(success == false)
cout << endl << "No room for more persons." << endl;

cout << "\n\nUnsorted list:";

persons.print_persons();

persons.bsort();
cout << "\n\n\nSorted list:";

persons.print_persons();

persons.delete_them();

cout << endl;
return 0;
}

I suggest you find ways to get rid of your 'choice' and 'success'
variables in the above function. Some things to think about:

a) You are using 'success' to determine if the PersonArray is full. Why
not have an "isFull" member-function in PersonArray that returns true if
it's full and false if not?

b) I've mentioned the 'choice' variable before. Encapsulate it, and the
lines dealing with it in a function that you call. It should return a
bool. Either "should_continue" or "should_stop" would be a good name for
it.

With suggestion (a) above, you can check to see if addperson will
succeed before actually calling it, that should clean things up a bit
and may make it easer to write a clean loop with no break in it.

Also, an interface question. When the person array is full, should the
program go ahead and ask the user if he wants to continue, or should it
just say that it can't take more names and go on? I mean if he enters 4
names and then says no, then he need never know that the program can't
take anymore names. On the other hand if he says yes and then doesn't
get to add a name... Something to think about when you start writing
real programs.

Personally, if you implement (a) and (b) above, I'd say you are done
with this program and should go on to the next assignment.
 
?

=?ISO-8859-1?Q?Martin_J=F8rgensen?=

Daniel said:
I suggest you find ways to get rid of your 'choice' and 'success'
variables in the above function. Some things to think about:

a) You are using 'success' to determine if the PersonArray is full. Why
not have an "isFull" member-function in PersonArray that returns true if
it's full and false if not?
Done.

b) I've mentioned the 'choice' variable before. Encapsulate it, and the
lines dealing with it in a function that you call. It should return a
bool. Either "should_continue" or "should_stop" would be a good name for
it.

Done. "should_continue" member function made.
With suggestion (a) above, you can check to see if addperson will
succeed before actually calling it, that should clean things up a bit
and may make it easer to write a clean loop with no break in it.

I couldn't figure out how to do that without break... Because there are
two requirements that both needs to be fullfilled at the same time: 1)
there should be room enough in the array and 2) the user should start by
entering at least one person and then be asked if he wants to enter
additional...

I thought of using the &&-operator, but couldn't figure out how because
one solution require a while-loop but the other requires a do-while-loop
(see code below).
Also, an interface question. When the person array is full, should the
program go ahead and ask the user if he wants to continue, or should it
just say that it can't take more names and go on? I mean if he enters 4
names and then says no, then he need never know that the program can't
take anymore names. On the other hand if he says yes and then doesn't
get to add a name... Something to think about when you start writing
real programs.

Done. Seem to work.
Personally, if you implement (a) and (b) above, I'd say you are done
with this program and should go on to the next assignment.

Thanks... I can't solve the one small problem described above... I don't
have enough "imagination"... :)

But else it works...

- - - - - - - - - - - - - - - - - - - - - - - -
#include <iostream>
#include <string> //for string class

//const int max_names =4;

using namespace std;
////////////////////////////////////////////////////////////////
class person //class of persons
{
protected:
string name; //person's name

public:
void setName() //set the name
{ cout << "Enter name: "; cin >> name; }
void printName() //display the name
{ cout << endl << name; }
string getName() //return the name
{ return name; }
~person() { cout << endl << endl << "Person class object
destroyed!" << endl; }
};


////////////////////////////////////////////////////////////////

class PersonArray
{
private:
static const int max_names = 4;
int n;
person* persPtr[max_names]; //pointer to each person

void order(person** pp1, person** pp2) //orders two pointers
{ //if 1st larger than 2nd,
if( (*pp1)->getName() > (*pp2)->getName() )
{
person* tempptr = *pp1; //swap the pointers
*pp1 = *pp2;
*pp2 = tempptr;
}
}
public:
PersonArray() : n(0) { } /* constructor */
~PersonArray() { cout << endl << endl << "PersonArray object
destroyed" << endl; }
int get_n() const { return n; }

void print_persons();
bool addperson();
void bsort(); //sort pointers to persons
void delete_them(); // delete them all & reset n
bool isFull(); // is personArray full?
bool should_continue(); // ask for user input
};


void PersonArray::print_persons()
{
if ( n <= max_names)
for ( int j = 0; j < n; ++j )
persPtr[j]->printName();
}

bool PersonArray::addperson()
{
/* last name ? */
if( n == max_names ) /* or >= perhaps = */
{
return(false);
}

/* add person */
persPtr[n] = new person;
persPtr[n] -> setName();
n++;

/* else finish and return normally */
return(true);
}

void PersonArray::bsort() //sort pointers to persons
{
int j, k; //indexes to array

for(j=0; j<n-1; j++) //outer loop
for(k=j+1; k<n; k++) //inner loop starts at outer
order(persPtr+j, persPtr+k); //order the pointer contents
}

void PersonArray::delete_them()
{
for ( int j = 0; j < n; ++j )
delete persPtr[j];
n = 0;
}


bool PersonArray::isFull()
{
return n == max_names ? true : false;
}

bool PersonArray::should_continue()
{
char tmp;
cin >> tmp;
return tmp == 'n' ? false : true;
}


////////////////////////////////////////////////////////////////
int main()
{
void bsort(person**, int); //prototype
PersonArray persons; //persons-array...


// while( !persons.isFull() )
// {
// persons.addperson();
// cout << "Enter another (y/n)? ";
// if( !persons.should_continue() )
// break;
// }

do{
if( !persons.isFull() )
{
persons.addperson();
cout << "Enter another (y/n)? ";
}
else
break;
} while( persons.should_continue() );

/* is the array full ? */
if( persons.isFull() )
cout << endl << "No room for more persons." << endl;

cout << "\n\nUnsorted list:";

persons.print_persons();

persons.bsort();
cout << "\n\n\nSorted list:";

persons.print_persons();

persons.delete_them();

cout << endl;
return 0;
}

- - - - - - - - - - - - - - - - - - - - - - - -

Best regards / Med venlig hilsen
Martin Jørgensen
 
D

Daniel T.

Martin Jørgensen said:
Done. "should_continue" member function made.

It shouldn't be a member function because it doesn't have anything to do
with the values contained in the class... make it a global function and
add the "Enter another" bit into it:

bool should_continue() {
cout << "Enter another (y/n)? ";
char choice;
cin >> choice;
return choice == 'y';
}
I couldn't figure out how to do that without break... Because there are
two requirements that both needs to be fullfilled at the same time: 1)
there should be room enough in the array and 2) the user should start by
entering at least one person and then be asked if he wants to enter
additional...

I thought of using the &&-operator, but couldn't figure out how because
one solution require a while-loop but the other requires a do-while-loop
(see code below).
// while( !persons.isFull() )
// {
// persons.addperson();
// cout << "Enter another (y/n)? ";
// if( !persons.should_continue() )
// break;
// }

do{
if( !persons.isFull() )
{
persons.addperson();
cout << "Enter another (y/n)? ";
}
else
break;
} while( persons.should_continue() );

How about:

do {
perrsons.addperson();
} while ( ! persons.isFull() && should_continue() );

The above uses the 'should_continue' function I showed at top.
 
?

=?ISO-8859-1?Q?Martin_J=F8rgensen?=

Daniel said:
How about:

do {
perrsons.addperson();
} while ( ! persons.isFull() && should_continue() );

The above uses the 'should_continue' function I showed at top.

Then we're not using the return value of addperson(), but that's okay.
Nice exercise... And perhaps enough now... I have some new topics I'm
going to look at: derivation, abstract classes, friend function,
operator overloading etc...

New code:
- - - - - - - - - - - - - - - - - - - - - - - - -
#include <iostream>
#include <string> //for string class

//const int max_names =4;

using namespace std;
////////////////////////////////////////////////////////////////
class person //class of persons
{
protected:
string name; //person's name

public:
void setName() //set the name
{ cout << "Enter name: "; cin >> name; }
void printName() //display the name
{ cout << endl << name; }
string getName() //return the name
{ return name; }
~person() { cout << endl << endl << "Person class object
destroyed!" << endl; }
};


////////////////////////////////////////////////////////////////


bool should_continue() {
cout << "Enter another (y/n)? ";
char choice;
cin >> choice;
return choice != 'n';

}

////////////////////////////////////////////////////////////////

class PersonArray
{
private:
static const int max_names = 4;
int n;
person* persPtr[max_names]; //pointer to each person

void order(person** pp1, person** pp2) //orders two pointers
{ //if 1st larger than 2nd,
if( (*pp1)->getName() > (*pp2)->getName() )
{
person* tempptr = *pp1; //swap the pointers
*pp1 = *pp2;
*pp2 = tempptr;
}
}
public:
PersonArray() : n(0) { } /* constructor */
~PersonArray() { cout << endl << endl << "PersonArray object
destroyed" << endl; }
int get_n() const { return n; }

void print_persons();
bool addperson();
void bsort(); //sort pointers to persons
void delete_them(); // delete them all & reset n
bool isFull(); // is personArray full?
};


void PersonArray::print_persons()
{
if ( n <= max_names)
for ( int j = 0; j < n; ++j )
persPtr[j]->printName();
}

bool PersonArray::addperson()
{
/* last name ? */
if( n == max_names ) /* or >= perhaps = */
{
return(false);
}

/* add person */
persPtr[n] = new person;
persPtr[n] -> setName();
n++;

/* else finish and return normally */
return(true);
}

void PersonArray::bsort() //sort pointers to persons
{
int j, k; //indexes to array

for(j=0; j<n-1; j++) //outer loop
for(k=j+1; k<n; k++) //inner loop starts at outer
order(persPtr+j, persPtr+k); //order the pointer contents
}

void PersonArray::delete_them()
{
for ( int j = 0; j < n; ++j )
delete persPtr[j];
n = 0;
}


bool PersonArray::isFull()
{
return n == max_names ? true : false;
}

////////////////////////////////////////////////////////////////
int main()
{
void bsort(person**, int); //prototype
PersonArray persons; //persons-array...


do {
persons.addperson();
} while ( ! persons.isFull() && should_continue() );

/* is the array full ? */
if( persons.isFull() )
cout << endl << "No room for more persons." << endl;

cout << "\n\nUnsorted list:";

persons.print_persons();

persons.bsort();
cout << "\n\n\nSorted list:";

persons.print_persons();

persons.delete_them();

cout << endl;
return 0;
}

- - - - - - - - - - - - - - - - - - - - - - - - -

Best regards / Med venlig hilsen
Martin Jørgensen
 
D

Daniel T.

Martin Jørgensen said:
Then we're not using the return value of addperson(), but that's okay.

No we're not and that's a good thing. There is a principle called
command/query separation
<http://en.wikipedia.org/wiki/Command-Query_Separation>. The addperson
is breaking that principle because, when you think about it, the bool
returned tells us if the array is full.

We eventually found a better solution, two functions, one to add a
person, and a different one to tell us if the array is full.

class PersonArray {
public:
void add_person() {
if ( is_full() ) return;
// add a person
}
bool is_full() const { return n == max_names; }
};


Since you are done with this particular project, here is my solution.
Depending on the amount of ram in your machine, and the size of each
name, this solution can probably handle millions of names but I put the
error code in 'get_names' anyway (I wouldn't normally bother. :)


#include <algorithm> // for copy & sort
#include <iostream> // for cout
#include <iterator> // for ostream_iterator
#include <string>
#include <vector>

using namespace std;

bool should_continue()
{
cout << "Continue? (y/n) ";
char choice;
cin >> choice;
return choice == 'y';
}

void get_names( vector<string>& names )
{
try {
do {
names.push_back( string() );
cout << "Enter name: ";
cin >> names.back();
} while ( should_continue() );
}
catch ( ... ) {
cout << "Can't accept any more names.\n";
}
}

int main()
{
vector<string> names;
get_names( names );

cout << "\nUnsorted:\n";
copy( names.begin(), names.end(),
ostream_iterator<string>( cout, "\n" ) );
sort( names.begin(), names.end() );
cout << "\nSorted:\n";
copy( names.begin(), names.end(),
ostream_iterator<string>( cout, "\n" ) );
}
 
?

=?ISO-8859-1?Q?Martin_J=F8rgensen?=

Daniel said:
No we're not and that's a good thing. There is a principle called
command/query separation
<http://en.wikipedia.org/wiki/Command-Query_Separation>. The addperson
is breaking that principle because, when you think about it, the bool
returned tells us if the array is full.
Yep.

We eventually found a better solution, two functions, one to add a
person, and a different one to tell us if the array is full.

class PersonArray {
public:
void add_person() {
if ( is_full() ) return;
// add a person
}
bool is_full() const { return n == max_names; }
};

Yep.

Since you are done with this particular project, here is my solution.
Depending on the amount of ram in your machine, and the size of each
name, this solution can probably handle millions of names but I put the
error code in 'get_names' anyway (I wouldn't normally bother. :)


#include <algorithm> // for copy & sort
#include <iostream> // for cout
#include <iterator> // for ostream_iterator
#include <string>
#include <vector>

using namespace std;

bool should_continue()
{
cout << "Continue? (y/n) ";
char choice;
cin >> choice;
return choice == 'y';
}

void get_names( vector<string>& names )
{
try {
do {
names.push_back( string() );
cout << "Enter name: ";
cin >> names.back();
} while ( should_continue() );
}
catch ( ... ) {
cout << "Can't accept any more names.\n";
}
}

int main()
{
vector<string> names;
get_names( names );

cout << "\nUnsorted:\n";
copy( names.begin(), names.end(),
ostream_iterator<string>( cout, "\n" ) );
sort( names.begin(), names.end() );
cout << "\nSorted:\n";
copy( names.begin(), names.end(),
ostream_iterator<string>( cout, "\n" ) );
}

Really nice....... I just saved this program... It looks like an
excellent case study so I should (hopefully) be able to understand the
program fully in a few weeks...


Best regards / Med venlig hilsen
Martin Jørgensen
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,821
Latest member
AleidaSchi

Latest Threads

Top