Problem with a Dynamic Array of Structs

Hi, I'm hoping someone can help me to fix a problem I'm having with part of a C++ assignment.

Basically I need an array of patients names, addresses, ID, amount owing, and number of treatments, so I created a struct called patient with a typedef P.

I create a new array with just one value initially, after which I want to increase the array size by 1 each time I want to add in another patient.

I the code below, I have a function to display my menu, and another to enter a new patient.

Finally when I choose Q to quit, the program prints out the list entered. (although it's not working yet!).

When I run the code, it is fine for 1 entry, however when I try to enter in any extra patient it appears to work but when I quit, it generates an unhandled expression and crashes out.

Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <iostream>
#include <iomanip>

using namespace std;
		
struct Patient{
		int pID;
		string pName;
		string pAddress;
		float amountOwing;
		int noTreatments;
		};
		typedef struct Patient P;
		
void enterPatients(P *parray, int &pCount);

char getOption();

void main()
     {
          int pCount=1; // allow for 1 patient to start with

          P * parray = new P[pCount];        
                         
          char option;
          
          do
          {
          option = getOption();
          
          switch(option)
          {
          
          case 'P': enterPatients(parray, pCount);
          			pCount++;
          			cout << " in swich statement " << pCount << endl;
          			break; 
          // more cases to come!			
           }
 		   
		}while(option!='Q');

//output the patients to check if stored correctly:
       	for(int i=0;i<pCount;i++) 
               {
               cout << parray[i].pName << " " << parray[i].pID << " " << parray[i].pAddress << " " << parray[i].amountOwing << endl;
               }

       
     }
 

void enterPatients(P *parray, int &pCount)
     {
                
     			if(pCount==1) // enter just the first patient details
     			{
     		  	cin.get();
              		cout << "Please enter patient details:\n";
              		parray[pCount-1].pID = pCount-1;
              		cout << "Enter patient name " << pCount-1 << endl;
			  	getline(cin, parray[pCount-1].pName);
              		cout << "Enter patient address \n";
              		getline(cin, parray[pCount-1].pAddress);
              		parray[pCount-1].amountOwing = 0.00; // initially patient owes nothing
              		parray[pCount-1].noTreatments = 0; // initially patient has no treatments
     			cout << pCount << " in pcount ==1 looop "<< endl;
     			return;
     			}
     		
     			// for entering 2nd and subsequent patients
              		cout << pCount << " in loop for pCount > 1 "<< endl;
              		P * temparray = new P[pCount];
              		// new temparray to transfer original details into bigger array
              		for(int i=0;i<pCount-1; i++)
              			{
              			temparray[i].pID = parray[i].pID;
            	  		temparray[i].pName = parray[i].pName;
              			temparray[i].pAddress = parray[i].pAddress;
              			temparray[i].amountOwing = parray[i].amountOwing;
              			temparray[i].noTreatments = parray[i].noTreatments;
              			}
              	
              	
              	delete [] parray; // is this correct to remove the original array of structs?
              	
              	parray = temparray; // is this correct to point at the copied array?
              	
              	// should I delete the temparray now?
              	       	          	              	
              	cin.get();
              	cout << "Please enter patient details:\n";
              	parray[pCount-1].pID = pCount-1;
              	cout << "Enter patient name " << pCount-1 << endl;
			 	getline(cin, parray[pCount-1].pName);
             	cout << "Enter patient address \n";
             	getline(cin, parray[pCount-1].pAddress);
             	parray[pCount-1].amountOwing = 0.00; // initially patient owes nothing
             	parray[pCount-1].noTreatments = 0; // initially patient has no treatments
     }


char getOption()
	{
	//system("CLS");
	
	char option;
	cout << "What would you like to do next?\n\n" ;
	cout << setw(10) << "Press P to enter a new patient\n";
	cout << setw(10) << "Press Q to quit\n";
	cin >> option;
	//cin.get();
	option = toupper(option);
	return option;
	
	}
Why don't you use a std::vector and save yourself the trouble of relocating the data yourself, and speed up the new entry function by an O(n) factor?
I love that idea, however I have to stick to the tutors notes. She's not being very helpful as her notes don't work either!
line 87 is not correct.

you either have to pass parray as a reference or as a double pointer.
She's not being very helpful as her notes don't work either!

Sorry for that... (but I recommend telling her that the STL actually is a part of the C++ standard and that there really isn't any reason not to use it (or, if there is, that she should explain it to you). If you do it nicely, it might actually help. There *are* tutors who want to improve themselves, although they are rare. If nothing else helps, you can always give her a copy of ISO 14882 as a Christmas present... In that actual case, you could argue that Stroustrup discourages the use of built-in dynamic arrays altogether in favor of std::vector)
nothing else helps, you can always give her a copy of ISO 14882 as a Christmas present... In that actual case, you could argue that Stroustrup discourages the use of built-in dynamic arrays altogether in favor of std::vector)


Thank you for that info. I will certainly do a bit of quoting shortly. I had come across something to that end on my google searches for an answer but you have put a label on it! Many thanks.

line 87 is not correct.

you either have to pass parray as a reference or as a double pointer.


Thanks for that - I'll try that out tomorrow at this stage as I'm all C++'d out now! 10:30pm Irish time!

Why shouldn't arrays be taught??
Why shouldn't arrays be taught??


My uneducated guess is that arrays should be taught, however dynamic arrays are just too damn error prone. Vectors look like a much easier to manage solution to the needs of dynamic memory allocation for arrays.

I might be wrong as I'm only just getting to grips with all things dynamic, maybe someone with more knowledge can verify or refute my assumptions.
Last edited on
You are exactly right. You have to learn to walk before you can run. Arrays have to be taught as they are a fundamental concept in programming, but in practice vectors free the programmer from all the details of memory management / memory stomps and allow him/her to focus on higher level problems.

Sorted - with many thanks to the words of advice here!

you either have to pass parray as a reference or as a double pointer.


void enterPatients(P* &parray, int &pCount); was the correct code rather than:
void enterPatients(P *parray, int &pCount);

and also incorrect was getline(cin, parray[pCount-1].pName);

the [pCount-1] is incorrect in all my code as it cannot do calculations within the array it seems... not sure how best to word that, So I assigned an int k equal to pCount - 1 and used k instead throughout the function!

The complete code is below which I hope will help future victims of dynamic arrays of structs!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include <iostream>
#include <iomanip>

using namespace std;
		
struct Patient{
	                int pID;
		string pName;
		string pAddress;
		float amountOwing;
		int noTreatments;
	      };
		typedef struct Patient P;
		
void enterPatients(P* &parray, int &pCount);
		
//void enterPatients(P *parray, int &pCount);// incorrect

char getOption();

void main()
     {
          int pCount=1; // allow for 1 patient to start with

          P * parray = new P[pCount];        
                         
          char option;
          
          do
          {
          option = getOption();
          
          switch(option)
          {
          
          case 'P': enterPatients(parray, pCount);
          			pCount++;
          			cout << " in swich statement " << pCount << endl;
          			break; 
          // more cases to come!			
           }
 		   
		}while(option!='Q');

//output the patients to check if stored correctly:
       	for(int i=0;i<pCount-1;i++) 
               {
               cout << parray[i].pName << ", " 
               << parray[i].pID << ", " 
               << parray[i].pAddress << ", " 
               << parray[i].amountOwing << ", "
               << parray[i].noTreatments << "."
               << endl;
               }

       
     }
 
void enterPatients(P* &parray, int &pCount)
     {
     			
       int k = pCount-1; // use k instaed of pCount-1
       if(k==1) // enter just the first patient details
     		{
     		  cin.get();
              cout << "Please enter patient details:\n";
              parray[k].pID = k;
              cout << "Enter patient name " << k << endl;
			  getline(cin, parray[k].pName);
              cout << "Enter patient address \n";
              getline(cin, parray[k].pAddress);
              parray[k].amountOwing = 0.00; // initially patient owes nothing
              parray[k].noTreatments = 0; // initially patient has no treatments
     		  cout << k << " in pcount ==1 looop "<< endl;
     		  return;
     		}
     		
     		  // for entering 2nd and subsequent patients
              cout << k << " in loop for pCount > 1 "<< endl;
              P * temparray = new P[pCount];
              // new temparray to transfer original details into bigger array
              for(int i=0;i<k; i++)
              	{
              		temparray[i].pID = parray[i].pID;
              		temparray[i].pName = parray[i].pName;
              		temparray[i].pAddress = parray[i].pAddress;
              		temparray[i].amountOwing = parray[i].amountOwing;
              		temparray[i].noTreatments = parray[i].noTreatments;
              	}
              	
              	
              	delete [] parray; // is this correct to remove the original array of structs?
              	
              	parray = temparray; // is this correct to point at the copied array?
              	
              	// should I delete the temparray now?
              	       	          	              	
              	cin.get();
              	cout << "Please enter patient details:\n";
              	parray[k].pID = k;
              	cout << "Enter patient name " << k << endl;
			 	getline(cin, parray[k].pName);
             	cout << "Enter patient address \n";
             	getline(cin, parray[k].pAddress);
             	parray[k].amountOwing = 0.00; // initially patient owes nothing
             	parray[k].noTreatments = 0; // initially patient has no treatments
     }


char getOption()
	{
		//system("CLS");
		char option;
		cout << "What would you like to do next?\n\n" ;
		cout << setw(10) << "Press P to enter a new patient\n";
		cout << setw(10) << "Press Q to quit\n";
		cin >> option;
		option = toupper(option);
		return option;
	}
Arrays have to be taught as they are a fundamental concept in programming

That's a valid point. However, in my opinion they have to be taught in a "Algorithm/Data Structures" lecture, not in a programming course. Furthermore, I wouldn't mix a AlgDat lecture with a C++ introduction (because I think that C++ is much to complex to be taught casually). And in a C++ programming course, the built-in arrays shouldn't be unmentioned, but the usage of the STL should be encouraged instead of prohibited (in valid situations, which is for instance always when the array is dynamic).
Last edited on
Topic archived. No new replies allowed.