Stacks with dynamic data without Classes/STL

I am having major problems here. I am still in the early testing stages of a program that is supposed to use Stacks and Queues to interpret file data. The catch is that I cannot use classes, templates, or STL. All of it has to be done in linked lists via structs. The book hasn't been helpful because all examples use classes and templates, STL, etc. Right now I am at a roadblock with my code because I keep getting a SIGSEGV error when I debug. The program won't run it just quits on me. The problem appears to be with my initVStack / initAStack functions. I am not sure whats wrong.

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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
#include <iostream>
#include <iomanip>
#include <string>
#include <cctype>
#include <sstream>
#include <fstream>
#define NDEBUG
#include <cassert>
#include <cstdlib>
using namespace std;

const int EXPECTED_NUM_ARGS = 3;
const int SEEK_SENTINEL = 3;
const int ARGV_CELL2 = 1;
const int ARGV_CELL3 = 2;
const char VAN = 'V';
const char AUTOV = 'A';
const char CHECKOUT = 'C';
const char RETURNED = 'R';
const string VEHICLE_DATA = "Vehicle_Data.txt";
const string CHECK_RETURN_DATA = "Checkout_Return_Data.txt";

struct vRecordNode {
	char vehicleType; 
	string licensePlate;
	int capacity;
	vRecordNode *next;
	
};

struct vStack{
    vRecordNode *topOfStack;
    int counter;
    
};

struct eRecordNode {
	int numWaiting;
	eRecordNode *next;
	
};

struct aStack{
    vRecordNode *topOfStack;
    int counter;
    
};

struct waitQueue {
	eRecordNode *queueFront;
	eRecordNode *queueBack;
};

bool CheckParameters(int argc, char *argv[]);
vRecordNode* CreateVNode(string fileName);
eRecordNode* CreateENode(string fileName);
void initVStack(vStack* &(v));
void initAStack(aStack* &(a));
int getVStackCount(vStack *v);
int getAStackCount(aStack *a);
void pushVStack(vStack* &(v), vRecordNode *newNode);
void pushAStack(aStack* &(a), vRecordNode *newNode);
vStack vTop(vStack *v);
aStack aTop(aStack *a);
void popV(vStack &v);
void popA(aStack &a);
bool isVEmpty(vStack *v);
bool isAEmpty(aStack *a);

int main(int argc, char *argv[]){

	int vStackCount = 0, aStackCount = 0;
	bool correctParam = false;
	vRecordNode *vNode;
	eRecordNode *eNode;
	vStack *v;
	aStack *a;
	string fileName = " ";			
	ofstream dataOut;						//var to write data to file

	correctParam = CheckParameters(argc, argv);
	
	if(correctParam){
		
		initVStack(v);						//initialize van stack
		initAStack(a);						//initialize auto stack
		fileName = argv[ARGV_CELL2];		//read first cmd file
		
		vNode = CreateVNode(fileName);
		
		while(vNode->next != NULL){
			
			if(vNode->vehicleType == VAN){
			
				pushVStack(v,vNode);
				
			} else {
				
				pushAStack(a,vNode);
				
			} // end if-else
			
			vNode = vNode->next;
			
		} // end while
		
		vStackCount = getVStackCount(v);
		aStackCount = getAStackCount(a);
		
		cout << vStackCount << endl;
		
	}
	
	return 0;
}

bool CheckParameters(int argc, char *argv[]){

	bool correct = false;

	if (argc != EXPECTED_NUM_ARGS){
	
    	cout << "Error - must both file names as command line arguments"
        	 << endl << "You must restart the program, after entering the arguments." 
         	 << endl << endl;
    
	} else {

		for(int i = 1; i < argc; i++){
	
			if (argv[ARGV_CELL2] != VEHICLE_DATA || argv[ARGV_CELL3] != CHECK_RETURN_DATA){
			
				cout << "Error - invalid file names. Please re-check the names of the files and try again."
					 << endl << endl;
			
			} else {
				
				correct = true;
				
			}
		
		}
		
	}	
	
	return correct;
	
}

vRecordNode* CreateVNode(string fileName){
	
	int counter = 0;
	vRecordNode *newNode, *topNode, *botNode = NULL;	// pointers for creation of linked lists
	ifstream dataIn;									// var to read data in from file

	dataIn.open(fileName.c_str()); 						// try to open file
	
	// if file cannot be opened display error
	if(dataIn.fail()){
			
		cerr << endl << "Error opening input file or " 
			 << "could not find file." << endl;
			
	} else {
			
		while(!dataIn.eof()){

			newNode = new (nothrow) vRecordNode; 		// allocate memory to newNode from vehicleRecord

			dataIn >> newNode->vehicleType;	    // read data from file assign to vehicleType in node
			dataIn >> newNode->licensePlate; 	// read data from file assign to licensePlate in node
			dataIn >> newNode->capacity;	  	// read data from file assign to capacity in node
			newNode->next = NULL;			   	// next will point to NULL
		
			// continue if memory was allocated
			if(newNode != NULL){
			
				if(topNode == NULL){
					
					topNode = newNode;				// pointer to newNode
					botNode = newNode;				// pointer to newNode
				
				} else {
					
					topNode = newNode->next;		// pointer to top of the list
				
					while(topNode->next != NULL){
					
						topNode = topNode->next;	// upon loop exit we are at top of list
						
					} // end while
					
					botNode->next = newNode;
					
				} // end if-else

			} else {
				
				cout << "Cannot add data to the list." << endl;

			} // end if-else
		
		} // end while
		
	} // end if-else

	dataIn.close();
	
	return newNode;
	
}



void initVStack(vStack* &(v)){
	
	vRecordNode *temp = new (nothrow) vRecordNode;
	vStack *topOfStack = new (nothrow) vStack;
	
	while(topOfStack != NULL){
		
		temp = v->topOfStack;
		
		v->topOfStack = v->topOfStack->next;
		
		delete temp;
		delete topOfStack;
	}	 
}

void initAStack(aStack* &(a)){
	
	vRecordNode *temp;
	
	while(a->topOfStack != NULL){
		
		temp = a->topOfStack;
		
		a->topOfStack = a->topOfStack->next;
		
		delete temp;
	}	
}

int getVStackCount(vStack *v){
	
    return v->counter;
}

int getAStackCount(aStack *a){
	
    return a->counter;
}

void pushVStack(vStack* &(v), vRecordNode *newNode){
	vRecordNode *currNode;
	
    if(v->topOfStack == NULL){
	
		v->topOfStack = newNode; 
		currNode = newNode;
		
    } else {
    	
    	v->topOfStack = newNode;
    	newNode->next = currNode;
    	
	}
	
	v->counter++;
}

void pushAStack(aStack* &(a), vRecordNode *newNode)
{
	vRecordNode *currNode;
	
    if(a->topOfStack == NULL){
	
		a->topOfStack = newNode; 
		currNode = newNode;
		
    } else {
    	
    	a->topOfStack = newNode;
    	newNode->next = currNode;
    	
	}
	
	a->counter++;
}

vRecordNode *vTop(vStack v){
	
	assert(v->topOfStack != NULL); 	//if stack is empty terminate program
	
	return v.topOfStack;			//return data from top of stack
	
}

vRecordNode *aTop(aStack a){
	
	assert(a->topOfStack != NULL); 	//if stack is empty terminate program
	
	return a.topOfStack;			//return data from top of stack
	
}

void popV(vStack &v){
	
	vRecordNode *temp; 				// pointer to deallocate memory
	
	if(v.topOfStack != NULL){
		
		temp = v.topOfStack;		// set temp to point to the top node
		
		v.topOfStack = v.topOfStack->next; 	//advance topOfStack to the next node
		
		delete temp;
		v.counter--;	// deincrement counter for eStack
	}
    
}

void popA(aStack &a){
	
	vRecordNode *temp; 				// pointer to deallocate memory
	
	if(a.topOfStack != NULL){
		
		temp = a.topOfStack;		// set temp to point to the top node
		
		a.topOfStack = a.topOfStack->next; 	//advance topOfStack to the next node
		
		delete temp;
		a.counter--;	// deincrement counter for eStack
	}
    
}


bool isVEmpty(vStack *v){
	
	bool isEmpty = false;
	
	if(v->topOfStack == NULL){
			 
		isEmpty = true;		
		
	} 
	
    return isEmpty;
}	


bool isAEmpty(aStack *a){	
	
	bool isEmpty = false;
	
	if(a->topOfStack == NULL){
			 
		isEmpty = true;		
		
	} 
	
    return isEmpty;
}

Last edited on
I don't claim to have read all your code, or even understand it if I did, but what are you trying to do here?

215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
void initVStack(vStack* &(v)){
	
	vRecordNode *temp = new (nothrow) vRecordNode;
	vStack *topOfStack = new (nothrow) vStack;
	
	while(topOfStack != NULL){
		
		temp = v->topOfStack;
		
		v->topOfStack = v->topOfStack->next;
		
		delete temp;
		delete topOfStack;
	}	 
}


Doesn't it just boil down to

1
2
3
void initVStack(vStack* &(v)){
    v->topOfStack = v->topOfStack->next;
}


I mean, you declare a vRecordNode pointer named temp and assign v->topOfStack to it, but almost immediately afterwards, you delete it. You don't actually use it to do anything.

As for topOfStack, it's a vStack pointer but all you do is make it point to a new vStack. Then you use it as the control variable for your loop, where you delete it, thereby invalidating loop conditions. In other words, you make sure the loop only runs once. And you don't do anything with the new vStack you made it point to.

As for this other function

231
232
233
234
235
236
237
238
239
240
241
242
243
void initAStack(aStack* &(a)){
	
	vRecordNode *temp;
	
	while(a->topOfStack != NULL){
		
		temp = a->topOfStack;
		
		a->topOfStack = a->topOfStack->next;
		
		delete temp;
	}	
}


Again, why do you need the pointer temp? All you do is assign a->topOfStack to it and then delete it almost immediately afterwards without using it for anything.
Last edited on
Thank you for the reply fg.

As you can see I don't really know what I am doing. I am taking what code I can from my course book and attempting to make sense of it.

The goal is to create a vehicle record struct and fill it with information from a file. Then I need to assign the nodes to a given stack based on the file data that was read. My initVStack and initAStack functions are attempts at initializing the 'stack' to allow for the linked nodes to be entered in.

v = van
a = auto

Does this kind of clear things up and help you see what I am attempting to accomplish?
Took a short look at the main function, and you are creating pointers v and a without assigning anything to them. Then you attempt to call the two aforementioned functions on them. Of course that would lead to an error. You are attempting to access data from something that doesn't exist yet.

I'm not sure how to help you. You are using a lot of pointers, but you say you're not allowed to use classes. That means you can't make a destructor function for your structs, which means throwing new around would lead to a lot of memory leaks.
fg109,

Yeah, it is a mess. I'm sorry for that. I allocated memory to my pointers that I created in main and the program executed... that is a step in the right direction I think. I got rid of the initialize functions because, like you said, they were doing nothing. I believe I got confused because of trying to emulate stack templates mentioned in my course book with functions / structs.

Could you take a look at my CreateVNode function and let me know if I am heading in the right direction there? I am trying to link my struct stack to all of my linked nodes that are created from the CreateNode functions.

Frosty
You should get rid of

botNode->next = newNode;

You are trying to keep track of both ends of your linked list. Since topNode is always updated to point to the newest node, then botNode should always point to the oldest.

The other thing is that botNode and topNode should not be declared inside this function. They should be declared in main and then passed to this function as parameters. Otherwise, how will you know the top and bottom of your list once you return from that function?
Last edited on
I updated my linked list node.

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
vRecordNode* CreateVNode(string fileName, vRecordNode* (&top), vRecordNode* &(bottom)){
	
	int counter = 0;
	vRecordNode *newNode;	// pointers for creation of linked lists
	ifstream dataIn;									// var to read data in from file

	dataIn.open(fileName.c_str()); 						// try to open file
	
	// if file cannot be opened display error
	if(dataIn.fail()){
			
		cerr << endl << "Error opening input file or " 
			 << "could not find file." << endl;
			
	} else {
			
			top = NULL;
			bottom = NULL;
			
		while(!dataIn.eof()){

			newNode = new (nothrow) vRecordNode; 		// allocate memory to newNode from vehicleRecord

			dataIn >> newNode->vehicleType;	    // read data from file assign to vehicleType in node
			dataIn >> newNode->licensePlate; 	// read data from file assign to licensePlate in node
			dataIn >> newNode->capacity;	  	// read data from file assign to capacity in node
			newNode->next = NULL;			   	// next will point to NULL	
			
			if(top == NULL){
					
				top = newNode;				// pointer to newNode
				bottom = newNode;				// pointer to newNode
				
			} else {
					
				top->next = newNode;		// pointer to top of the list
				top = newNode;
				
			} // end if-else
		
		} // end while
		
	} // end if-else

	dataIn.close();
	
}


I feel this is correct, but i am still getting a SIGSEGV fault when I try to test the data in the stack with my cout statements in main.. see below.

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
int main(int argc, char *argv[]){

	int vStackCount = 0, aStackCount = 0;
	bool correctParam = false;
	vRecordNode *vNode = new (nothrow) vRecordNode, *seek, *top, *bottom;
	eRecordNode *eNode = new (nothrow) eRecordNode;
	vStack *v = new (nothrow) vStack;
	aStack *a = new (nothrow) aStack;
	string fileName = " ";			
	ofstream dataOut;						//var to write data to file

	correctParam = CheckParameters(argc, argv);
	
	if(correctParam){
		
		v->counter = 0;						//initialize counter for vStack
		a->counter = 0;						//initialize counter for aStack
		
		fileName = argv[ARGV_CELL2];		//read first cmd file
		
		CreateVNode(fileName, top, bottom);	//create linked list node structure from data file
		vNode = bottom;
		seek = vNode;						//pointer used to traverse linked list
		
		// loop until last node is push into applicable stack
		do {
			
			if(seek->vehicleType == VAN){
			
				pushVStack(v, seek);	// if van push node into stack and count
				
			} else {
				
				pushAStack(a, seek);	// if auto push node into stack and count
				
			} // end if-else
			
			seek = seek->next;			// go to next node
			
		}while(seek != NULL); // end while

		vStackCount = getVStackCount(v);
		aStackCount = getAStackCount(a);
		
		cout << v->topOfStack->vehicleType << " " << v->topOfStack->licensePlate <<  endl		// used for debug, check counter??
			 << v->topOfStack->next->vehicleType << " " << v->topOfStack->next->licensePlate <<  endl	// POINTS TO NOTHING DAMNIT
			 << a->topOfStack->vehicleType << " " << a->topOfStack->licensePlate <<  endl
			 << a->topOfStack->next->vehicleType << " " << a->topOfStack->next->licensePlate <<  endl
			 << vStackCount << " " << aStackCount;
		
		//fileName = argv[ARGV_CELL3];
		
		//CreateENode(eList, fileName);
		
	}
	
	return 0;
}


I am not sure what is wrong at this point, but in case it is my pushStack function I will link that as wel.

1
2
3
4
5
6
7
8
9
10
11
void pushVStack(vStack* &(v), vRecordNode *newNode){
	
	vRecordNode *data = new (nothrow) vRecordNode;
	
	data->vehicleType = newNode->vehicleType;
	data->licensePlate = newNode->licensePlate;
	data->capacity = newNode->capacity;
	data->next = v->topOfStack;
	v->topOfStack = newNode; 
	v->counter++;
}



Any help to point me in the right direction will be very much appreciate. Also, I can give free internet cookies... the yummy imaginary kind!

-Frosty
vRecordNode* CreateVNode(string fileName, vRecordNode* (&top), vRecordNode* &(bottom)){

should be

vRecordNode* CreateVNode(string fileName, vRecordNode* top, vRecordNode* bottom){

Remember to fix your function call and prototype too. And now that I look at them, your push functions suffer from the same problem.

As for why it's wrong, when you have that '*' in after a variable type in the function parameters, it means you want to pass a pointer of that type. The '&' in front of a variable means you're passing by reference, basically you're passing the address of the variable. Put together, that means you're trying to pass a pointer to something like 0x0002ef (not really sure how addresses are represented).
fg109,

Thank you for your assistance. I was able to get my program to work with your help! You rock!!

-Frosty
Topic archived. No new replies allowed.