Linked List Help!! (Now have 23 errors with code)

Pages: 123
For this code, I have to create a program using linked list that will ask the user to enter the month and the amount of rainfall that month got. I'm confused on how I add the month and rainfall amount to the linked list. Also, I confused on if the user wants to edit the linked list for that month. It should look like this. I don't understand how I'm suppose to get my code to do this.
Choice: E

Enter Month: Mar

ERROR: Invalid Month

Enter Month: Feb

Enter Rainfall (In Inches): 24

The project includes a rainfall.cpp, list.cpp, driver.cpp, list.h, and rainfall.h.
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


 // Driver.cpp -- Contains the main and any unique subroutines.

#include <iostream>
#include <string>
#include "List.h"
#include "Rainfall.h"
int main() {

	// Declare variables
	char userAnswer;  // user answer for either A,E,P or, Q
	std::string month;
	int rainfall;
	List Rainfall;

	// Print out choices for user
	// Get user choice
	std::cout << "A--Add a month of statistics\n";
	std::cout << "E--Edit a month of statistics\n";
	std::cout << "P--Print report\n";
	std::cout << "Q--Quit\n";
	std::cout << "Choice: ";
	std::cin >> userAnswer;


	// If user answer is A ask user for month and rainfall
	if (userAnswer = 'A') {
		std::cout << "Enter month: ";
			std::cin >> month;
			// Need to add month to linked list
			std::cout << "Enter temp";
				std::cin >> rainfall;
				Rainfall.addNode(rainfall); // add rainfall to linked list
	}
	else if (userAnswer = 'E') { // If the user selects edit a certain month
		std::cout << "Enter month: ";
		std::cin >> month;
                std::cout << "Enter temp";
				std::cin >> rainfall;
				Rainfall.addNode(rainfall); // add rainfall to
		if ()
	}

}


// List.cpp -- Contains the implementation

#include "List.h"
#include <cstdlib>
#include <iostream>

List::List() {
	head = NULL;
	temp = NULL;
	curr = NULL;
}

void List::addNode(int addData) {
	nodePtr n = new node; // node pointer equals new node
	n->next = NULL;
	n->data = addData;

	if (head != NULL) {
		curr = head;
		while (curr->next != NULL) {
			curr = curr->next;

		}
		curr->next = n;
	}
	else {
		head = n;
	}
}

void List::deleteNode(int delData) {
	nodePtr delPtr = NULL;
	temp = head;
	curr = head;

	while (curr != NULL && curr->data != delData) {
		temp = curr;
		curr = curr->next;
	}

	if (curr == NULL) {
		std::cout << delData << "was not in the list\n";
		delete delPtr;
	}
	else {
		delPtr = curr;
		curr = curr->next;
		temp->next = curr;
		if (delPtr == head) {
			head = head->next;
			temp = NULL;
		}
		delete delPtr;
		std::cout << "The value " << delData << "was deleted\n";
	}
}

void List::printList() {
	curr = head;
	while (curr != NULL) {
		std::cout << curr->data << std::endl;
		curr = curr->next;
	}
}

// Rainfall.cpp -- Contains the implementation of the Rainfall class

#include "RainFall.h"
#include "List.h"

int RainFall::getLowestRainfall() const
{
	List* nodePtr;
	nodePtr = head;
	int lowest = nodePtr->value;

	while (nodePtr)
	{
		if (nodePtr->value < lowest)
			lowest = nodePtr->value;
		nodePtr = nodePtr->next;
	}

	return lowest;
}

int RainFall::getHighestRainfall() const
{
	List* nodePtr;
	nodePtr = head;
	int highest = nodePtr->value;

	while (nodePtr)
	{
		if (nodePtr->value > highest)
			highest = nodePtr->value;
		nodePtr = nodePtr->next;
	}

	return highest;
}

int RainFall::getTotal() const
{
	List* nodePtr;
	nodePtr = head;
	int total = 0;

	while (nodePtr)
	{
		total += nodePtr->value;
		nodePtr = nodePtr->next;
	}

	return total;
}

void RainFall::appendNode(int num)
{
	List* newNode;
	List* nodePtr;

	newNode = new List;
	newNode->value = num;
	newNode->next = NULL;

	if (!head)
		head = newNode;
	else
	{
		nodePtr = head;

		while (nodePtr->next)
			nodePtr = nodePtr->next;
		nodePtr->next = newNode;
	}
}

void RainFall::displayList() const
{
	List* nodePtr;
	nodePtr = head;

	while (nodePtr)
	{
		std::cout << "Element " << nodePtr->value;
		nodePtr = nodePtr->next;
	}
}

// List.h -- Contains the header information for your linked list class.


#ifndef LIST_H
#define LIST_H

class List {
private:

	struct node {
		int data; // Store the data of each node
		node* next; // Will point to the next node in the list
	};

	typedef struct node* nodePtr;

	nodePtr head; // head of node
	nodePtr temp; // temparory node
	nodePtr curr; // current node

public:
	List();
	void addNode(int addData);
	void deleteNode(int delData);
	void printList();
};

#endif // LIST_H

// Rainfall.h -- Contains the header information for the Rainfall class

#ifndef RAINFALL_H
#define RAINFALL_H

#include <iostream>

class RainFall
{
private:
	struct List
	{
		int value;
		List* next;
	};

	List* head;

public:
	RainFall()
	{
		head = NULL;
	}

	void appendNode(int num);
	void displayList() const;
	int getHighestRainfall() const;
	int getLowestRainfall() const;
	int getTotal() const;
};



#endif // RAINFALL_H 
Last edited on
Hello Lacy9265,

Some things I have noticed so far:

In "main" "userAnswer" would be better as an "int" and for the menu you can do this:
1
2
3
4
5
6
7
std::cout <<
    "1 -- Add a month of statistics\n"
    "2 -- Edit a month of statistics\n"
    "3 -- Print report\n"
    "4 -- Quit\n"
    "  Enter Choice: ";
std::cin >> userAnswer;

You do not need a "cout" for every line. Each line in double quotes is considered 1 big string. This gives you the advantage of being easy to edit and it looks more like what your output will be.

For your if statement you have: if (userAnswer = 'A'). A single = means assign, so this is always true no mater what you enter for "userAnswer". You need (==) to compare.

You also need a way to check for either case: if (userAnswer == 'A' || userAnswer == 'a') or if (std:toupper(userAnswer) == 'A'), could also use tolower, or userAnswer = std::toupper(userAnswer); which would follow the "cin >> userAnswer;".

Another option is to replace the if statements with a "switch" where you could do:
1
2
3
4
5
6
7
8
9
switch (userAnswer)
{
    case 'a':
    case 'A':
        // Code here
        break;
    default:
        break;
}

Same concept for the other letters, but these letters should be replaced by numbers, no single quotes. Of course the choice is yours to make.

Line 42 has no use. This may produce an error or just a warning. Not sure which until I compile the code.

So far I have not figured out how you are storing the month. It looks like it may be an "int", but if you are going to use "Mar" it should be a string. I will know more when I get the code split up.

Andy
Shouldn't Rainfall be using List from List.h instead of defining it's own list struct?
Hello Lacy9265,

I did not get as far a dutch did. I tend to debug a program the same as I write a program, in small steps. The first step is the menu and if statement. For this I get this output:

 A--Add a month of statistics
 E--Edit a month of statistics
 P--Print report
 Q--Quit
  Enter Choice: f

     Add Month

 Enter month:  // <--- How? What are you looking for, a number or a string?


As you can see it does not matter what letter you enter it always ends up at Add Month because of the (=). Based on the prompt I would be more likely to enter a number than a word. It helps to give the user an idea of what is expected.

The more I see " Enter month:" I start thing of what or how to compare to something or what to compare it to.

Your next input:
1
2
std::cout << "Enter temp";
std::cin >> rainfall;

Do you want a temperature or an amount of rainfall?

Andy
Here is my new code. I'm having trouble figuring out three things for this code.
1. Do I add the month and rainfall amount to the same link listed. How do I get it so when I print the user answers the amount of rain goes with what that month.
2. When the user types E. How do you have it so the user can enter a month and enter the rainfall for that month. Example
Choice: E

Enter Month: Mar

ERROR: Invalid Month

Enter Month: Feb

Enter Rainfall (In Inches): 24

3. For the Rainfall.cpp I have to be able to calculate the average rainfall for all those months and which month had the most rainfall. I do I access the link list from my rainfall.cpp and rainfall.h files.

Also, Andy for when the user enters the month. I want a string (March, April, May, etc...)


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
// Driver.cpp -- Contains the main and any unique subroutines.

#include <iostream>
#include <string>
#include "List.h"
#include "Rainfall.h"

int main() {

	// Declare variables
	char userAnswer;  // user answer for either A,E,P or, Q
	std::string month;
	int rainfall;
	List Rainfall;

	// Do until user answer is Q
	do {
		// Print out choices for menu
		// Get user choice
		std::cout << "A--Add a month of statistics\n";
		std::cout << "E--Edit a month of statistics\n";
		std::cout << "P--Print report\n";
		std::cout << "Q--Quit\n";
		std::cout << "Choice: ";
		std::cin >> userAnswer;


		switch (userAnswer) {
			// If user answer is A ask user for month and rainfall
		case 'A':
			std::cout << "Enter month: ";
			std::cin >> month;
			// Need to add month to linked list
			std::cout << "Enter rainfall (in Inches): ";
			std::cin >> rainfall;
			Rainfall.addNode(rainfall); // add rainfall to linked list
			break;


		case 'E':
			std::cout << "Enter month: ";
			std::cin >> month;
			break;

			// If user is P print out statistics
		case 'P':
			// Print out total rainfall
			
			
			// Print out average rainfall

			// Print out most rainfall
			int largestElement(struct Node* head);

			// Print out least rain fall
			break;


		}

	} while (userAnswer != 'Q'); // user answer not Q
		return 0;  
	

}

// List.cpp -- Contains the implementation

#include "List.h"
#include <cstdlib>
#include <iostream>

List::List() {
	head = NULL;
	temp = NULL;
	curr = NULL;
}

void List::addNode(int addData) {
	nodePtr n = new node; // node pointer equals new node
	n->next = NULL;
	n->data = addData;

	if (head != NULL) {
		curr = head;
		while (curr->next != NULL) {
			curr = curr->next;

		}
		curr->next = n;
	}
	else {
		head = n;
	}
}

void List::deleteNode(int delData) {
	nodePtr delPtr = NULL;
	temp = head;
	curr = head;

	while (curr != NULL && curr->data != delData) {
		temp = curr;
		curr = curr->next;
	}

	if (curr == NULL) {
		std::cout << delData << "was not in the list\n";
		delete delPtr;
	}
	else {
		delPtr = curr;
		curr = curr->next;
		temp->next = curr;
		if (delPtr == head) {
			head = head->next;
			temp = NULL;
		}
		delete delPtr;
		std::cout << "The value " << delData << "was deleted\n";
	}
}

void List::printList() {
	curr = head;
	while (curr != NULL) {
		std::cout << curr->data << std::endl;
		curr = curr->next;
	}
}

#include "Rainfall.h"
#include "List.h"


struct Node {
    int data;
    struct Node* next;
};

// Function that returns the largest element
// from the linked list.
int largestElement(struct Node* head)
{
    // Declare a max variable and initialize
    // it with INT_MIN value.
    // INT_MIN is integer type and its value
    // is -32767 or less.
    int max = INT_MIN;

    // Check loop while head not equal to NULL
    while (head != NULL) {

        // If max is less then head->data then
        // assign value of head->data to max
        // otherwise node point to next node.
        if (max < head->data)
            max = head->data;
        head = head->next;
    }
    std::cout << "Most rainfall: " << max;
    return max;
}

// List.h -- Contains the header information for your linked list class.


#ifndef LIST_H
#define LIST_H

class List {
private:

	struct node {
		int data; // Store the data of each node
		node* next; // Will point to the next node in the list
	};

	typedef struct node* nodePtr;

	nodePtr head; // head of node
	nodePtr temp; // temparory node
	nodePtr curr; // current node

public:
	List();
	void addNode(int addData);
	void deleteNode(int delData);
	void printList();
};

#endif // LIST_H


// Rainfall.h -- Contains the header information for the Rainfall class



#include <iostream>
#include "List.h"


int largestElement(struct Node* head);

Last edited on
Hello Lacy9265,

First get case 'A' working. do not worry about the rest yet. Until you have the add function working the rest will be working and reworking until the linked list is correct.

I see that you have added a "do/while " loop which is good.

in your switch you need:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
switch (userAnswer)
{
    // If user answer is A ask user for month and rainfall
    case 'a':
    case 'A':
        std::cout << "Enter month: ";
        std::cin >> month;

        // Need to add month to linked list
        std::cout << "Enter rainfall (in Inches): ";
        std::cin >> rainfall;

        Rainfall.addNode(rainfall, month, year); // add rainfall to linked list
        break;

Writing the 2 case statements will all them to fall through until the "break" is reached. This way you can catch either case.

You have already entered a month and rain fall amount you just need to change the struct to store these variables and change the "addNode" to put those other values in the struct. It already works for rain fall adding anything else is easy.

For rain fall you have defined all your variables and return values as "int"s. The rain fall amounts I see are floating point numbers with 2 decimal places. Consider changing the "int"s to "double"s.

Since you are writing a C++ program and I would guess that the IDE and compiler are set up to use at least the C++11 standards you should change all "NULL"s to "nullptr" to make better use of the language.

Then you might want to adjust your "List::printList" function to include the new variables added to the struct.

You should also include the header file <iomanip> to use "setprecision" and maybe "setw()" for positioning the output. That part can come later.

For question 2 you only want to deal with the month. The month is easy to find and the rain fall amount may not be available information or you may only have a new rain fall amount for the edit. But first create the linked list.

For number 3 this will fall into place once you have a proper linked list to work with.

Also, Andy for when the user enters the month. I want a string (March, April, May, etc...)
Not a problem.

Andy
There are various errors with the list implementation etc.

As a first major re-factorisation to fix various issues, consider (as one file - you'll need to split into .h/.cpp files if needed):

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
#include <iostream>
#include <iomanip>

template<typename T>
class List {
private:
	struct node {
		node(const T& d) : data(d) {}
		T data {};		// Store the data of each node
		node* next {};	// Will point to the next node in the list
	};

	using nodePtr = node*;

	nodePtr head {};	// head of node

public:
	List() {}
	~List();
	List(const List&) = delete;
	List& operator=(const List&) = delete;
	void addNode(const T& addData);
	void deleteNode(const T& delData);
	void printList() const;
	const nodePtr getHead() const { return head; }
	nodePtr find(const T& d);
};

template<typename T>
List<T>::~List<T>() {
	while (head) {
		const auto curr {head};

		head = head->next;
		delete curr;
	}
}

template<typename T>
List<T>::nodePtr List<T>::find(const T& d) {
	for (auto curr = head; curr; curr = curr->next)
		if (curr->data == d)
			return curr;

	return nullptr;
}

template<typename T>
void List<T>::addNode(const T& addData) {
	const auto n {new node(addData)};	// node pointer equals new node

	if (head) {
		auto curr {head};

		for (; curr->next; curr = curr->next);
		curr->next = n;
	} else
		head = n;
}

template<typename T>
void List<T>::deleteNode(const T& delData) {
	auto temp {head};
	auto curr {head};

	while (curr && curr->data != delData) {
		temp = curr;
		curr = curr->next;
	}

	if (curr == nullptr)
		std::cout << delData << " was not in the list\n";
	else {
		auto delPtr {curr};

		curr = curr->next;
		temp->next = curr;

		if (delPtr == head)
			head = curr;

		//std::cout << "The value " << delData << "was deleted\n";
		delete delPtr;
	}
}

template<typename T>
void List<T>::printList() const {
	for (auto curr = head; curr; curr = curr->next)
		std::cout << curr->data << '\n';
}

class RainFall {
public:
	struct Data {
		int month {};
		int rain {};
	};

	friend bool operator==(const Data& d, int m) {
		return d.month == m;
	}

	friend bool operator!=(const Data& d1, const Data& d2) {
		return !(d1.month == d2.month && d2.rain == d2.rain);
	}

	RainFall() {}

	int getHighestRainfall() const;
	int getLowestRainfall() const;
	int getTotalRainfall() const;
	void appendNode(const Data& num);
	void displayList() const;

	auto find(int m) {
		auto curr {rlist.getHead()};

		for (; curr; curr = curr->next)
			if (curr->data.month == m)
				return curr;

		return (decltype(curr)) nullptr;
	}

	void remove(const Data& d) {
		rlist.deleteNode(d);
	}

private:
	List<Data> rlist;
};

std::ostream& operator<<(std::ostream& os, const RainFall::Data& d)
{
	return os << std::setw(3) << d.month << "  " << std::setw(4) << d.rain;
}

int RainFall::getLowestRainfall() const
{
	int lowrain {9999};

	for (auto nodePtr = rlist.getHead(); nodePtr; nodePtr = nodePtr->next)
		if (nodePtr->data.rain < lowrain)
			lowrain = nodePtr->data.rain;

	return lowrain;
}

int RainFall::getHighestRainfall() const
{
	int highrain {-9999};

	for (auto nodePtr = rlist.getHead(); nodePtr; nodePtr = nodePtr->next)
		if (nodePtr->data.rain > highrain)
			highrain = nodePtr->data.rain;

	return highrain;
}

int RainFall::getTotalRainfall() const
{
	int total {};

	for (auto nodePtr = rlist.getHead(); nodePtr; nodePtr = nodePtr->next)
		total += nodePtr->data.rain;

	return total;
}

void RainFall::appendNode(const RainFall::Data& num)
{
	rlist.addNode(num);
}

void RainFall::displayList() const
{
	std::cout << std::left << "Mon" << "  Rain\n";

	for (auto nodePtr = rlist.getHead(); nodePtr; nodePtr = nodePtr->next)
		std::cout << std::right << nodePtr->data << '\n';
}

int main() {
	char userAnswer {};
	RainFall rf;

	do {
		std::cout << "\nA--Add a month of statistics\n"
			<< "R--Remove a month of statistics\n"
			<< "E--Edit a month of statistics\n"
			<< "P--Print report\n"
			<< "D--Display details\n"
			<< "Q--Quit\n"
			<< "\nChoice: ";

		std::cin >> userAnswer;

		switch (userAnswer) {
			case 'A':
			case 'a':
			{
				RainFall::Data rd;

				std::cout << "Enter month: ";
				std::cin >> rd.month;

				std::cout << "Enter rainfall: ";
				std::cin >> rd.rain;

				rf.appendNode(rd);
			}
				break;

			case 'E':
			case 'e':
			{
				int m {};

				std::cout << "Enter month: ";
				std::cin >> m;

				if (const auto f {rf.find(m)}; f != nullptr) {
					std::cout << "Current rainfall value is " << f->data.rain << '\n';
					std::cout << "Enter new rainfall: ";
					std::cin >> f->data.rain;
				} else
					std::cout << "Month not found\n";
			}
				break;

			case 'R':
			case 'r':
			{
				int m {};

				std::cout << "Enter month: ";
				std::cin >> m;

				if (const auto f {rf.find(m)}; f != nullptr)
					rf.remove(f->data);
				else
					std::cout << "Month not found\n";
			}
			break;

			case 'D':
			case 'd':
				rf.displayList();
				break;

			case 'P':
			case 'p':
				std::cout << "\nLow rain is " << rf.getLowestRainfall() << '\n';
				std::cout << "High rain is " << rf.getHighestRainfall() << '\n';
				std::cout << "Total rain is " << rf.getTotalRainfall() << '\n';
				break;

			case 'Q':
			case 'q':
				break;

		}
	} while (userAnswer != 'q' && userAnswer != 'Q');
}

Hello Lacy9265,

Looking at your second code I found everything except what should be in "Rainfall.cpp". Did you miss that part or is that part thet is not well commented as to what it is for?

Andy
Rainfall.cpp starts at L113 in the OP code.

Note my re-factored code above.
On line 223 and 240 of seeplus's code. You get an error saying expected ). Why do you have it with the }; ?
Last edited on
@Lacy9265

Line 223 of seeplus code has an if with an init statement, it requires c++17 standard. The ; is the end of the init statement, before the condition. The braces are a type of direct initilisation: the compiler will produce an error if there is narrowing of a type, like long to int for example.

https://en.cppreference.com/w/cpp/language/if
Okay, how to I fix it so I don't get that error anymore or have that statement not use c++ 17 standards.
Last edited on
What compiler are you using? As has been said above, you need to compile as at least C++17.
Visual Studio 2019.
compile with c++17 standard, or higher:

g++ -std=c++20 -Wall -Wextra -pedantic-errors main.cpp -o MyProg.exe

or put the equivalent setting into your IDE.

I always try to have the latest compiler for my system, and generally compile to the latest standard. I could actually compile to c++23, even though there are relatively few things implemented in it atm. The reason I go for the latest, is that the compiler vendors fix things on a continuing basis (related to compiler version) and the latest standard will cope with anything that has been implemented by the compiler vendor.
VS2019 compiles C++17/20 just fine - but defaults to C++14. I use VS2019 and that code compiled OK for me.

Project/Properties/Configuration/General Set C++ language standard to Preview. This will give you C++20 as well (assuming you're using the latest version 16.10.2).
Last edited on
Did what seeplus said got it working now. Thank you for your help.
However, now I'm having issues with the list.h and rainfall.h files. On lines 56, 80, 30 I keep getting errors about List template. I have commented on each line what errors I get.

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
// List.h -- Contains the header information for your linked list class.


#include <iostream>
#include <iomanip>

template<typename T>
class List {
private:
	struct node {
		node(const T& d) : data(d) {}
		T data{};		// Store the data of each node
		node* next{};	// Will point to the next node in the list
	};

	using nodePtr = node*;

	nodePtr head{};	// head of node

public:
	List() {}
	~List();
	List(const List&) = delete;
	List& operator=(const List&) = delete;
	void addNode(const T& addData);
	void deleteNode(const T& delData);
	void printList() const;
	const nodePtr getHead() const { return head; }
	nodePtr find(const T& d);
};  //List class template jas alreday been defined


// Rainfall.h -- Contains the header information for the Rainfall class



#include <iostream>
#include "List.h"


class RainFall {
public:
	struct Data {
		int month{};
		int rain{};
	};

	friend bool operator==(const Data& d, int m) {
		return d.month == m;
	}

	friend bool operator!=(const Data& d1, const Data& d2) {
		return !(d1.month == d2.month && d2.rain == d2.rain);
	}

	RainFall() {} //List no appropriate default constructor avaiable

	int getHighestRainfall() const;
	int getLowestRainfall() const;
	int getTotalRainfall() const;
	void appendNode(const Data& num);
	void displayList() const;

	auto find(int m) {
		auto curr{ rlist.getHead() }; 
									

		for (; curr; curr = curr->next)
			if (curr->data.month == m)
				return curr; 
							

		return (decltype(curr)) nullptr;
	}

	void remove(const Data& d) {
		rlist.deleteNode(d);  
	}
private:
	List<Data> rlist; //List use of class template requires template argurment
};

std::ostream& operator<<(std::ostream& os, const RainFall::Data& d)
{
	return os << std::setw(3) << d.month << "  " << std::setw(4) << d.rain;
}

Last edited on
You can't split list into list.h and list .cpp - as they are templated code. All the code needs to be in the same file.

As the split may not be clear, this is as split into 4 files:

list.hpp
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
#pragma once

#include <iostream>

template<typename T>
class List {
private:
	struct node {
		node(const T& d) : data(d) {}
		T data {};		// Store the data of each node
		node* next {};	// Will point to the next node in the list
	};

	using nodePtr = node*;

	nodePtr head {};	// head of node

public:
	List() {}
	~List();
	List(const List&) = delete;
	List& operator=(const List&) = delete;
	void addNode(const T& addData);
	void deleteNode(const T& delData);
	void printList() const;
	const nodePtr getHead() const { return head; }
	nodePtr find(const T& d);
};

template<typename T>
inline List<T>::~List<T>() {
	while (head) {
		const auto curr {head};

		head = head->next;
		delete curr;
	}
}

template<typename T>
inline List<T>::nodePtr List<T>::find(const T& d) {
	for (auto curr = head; curr; curr = curr->next)
		if (curr->data == d)
			return curr;

	return nullptr;
}

template<typename T>
inline void List<T>::addNode(const T& addData) {
	const auto n {new node(addData)};	// node pointer equals new node

	if (head) {
		auto curr {head};

		for (; curr->next; curr = curr->next);
		curr->next = n;
	} else
		head = n;
}

template<typename T>
inline void List<T>::deleteNode(const T& delData) {
	auto temp {head};
	auto curr {head};

	while (curr && curr->data != delData) {
		temp = curr;
		curr = curr->next;
	}

	if (curr == nullptr)
		std::cout << delData << " was not in the list\n";
	else {
		auto delPtr {curr};

		curr = curr->next;
		temp->next = curr;

		if (delPtr == head)
			head = curr;

		//std::cout << "The value " << delData << "was deleted\n";
		delete delPtr;
	}
}

template<typename T>
inline void List<T>::printList() const {
	for (auto curr = head; curr; curr = curr->next)
		std::cout << curr->data << '\n';
}


rainfall.h
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
#pragma once

#include <iostream>
#include <iomanip>
#include "list.hpp"

class RainFall {
public:
	struct Data {
		int month {};
		int rain {};
	};

	friend bool operator==(const Data& d, int m) {
		return d.month == m;
	}

	friend bool operator!=(const Data& d1, const Data& d2) {
		return !(d1.month == d2.month && d2.rain == d2.rain);
	}

	RainFall() {}

	int getHighestRainfall() const;
	int getLowestRainfall() const;
	int getTotalRainfall() const;
	void appendNode(const Data& num);
	void displayList() const;

	auto find(int m) {
		auto curr {rlist.getHead()};

		for (; curr; curr = curr->next)
			if (curr->data.month == m)
				return curr;

		return (decltype(curr)) nullptr;
	}

	void remove(const Data& d) {
		rlist.deleteNode(d);
	}

private:
	List<Data> rlist;
};

inline std::ostream& operator<<(std::ostream& os, const RainFall::Data& d)
{
	return os << std::setw(3) << d.month << "  " << std::setw(4) << d.rain;
}


rainfall.cpp
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
#include <iostream>
#include <iomanip>
#include "rainfall.h"


int RainFall::getLowestRainfall() const
{
	int lowrain {9999};

	for (auto nodePtr = rlist.getHead(); nodePtr; nodePtr = nodePtr->next)
		if (nodePtr->data.rain < lowrain)
			lowrain = nodePtr->data.rain;

	return lowrain;
}

int RainFall::getHighestRainfall() const
{
	int highrain {-9999};

	for (auto nodePtr = rlist.getHead(); nodePtr; nodePtr = nodePtr->next)
		if (nodePtr->data.rain > highrain)
			highrain = nodePtr->data.rain;

	return highrain;
}

int RainFall::getTotalRainfall() const
{
	int total {};

	for (auto nodePtr = rlist.getHead(); nodePtr; nodePtr = nodePtr->next)
		total += nodePtr->data.rain;

	return total;
}

void RainFall::appendNode(const RainFall::Data& num)
{
	rlist.addNode(num);
}

void RainFall::displayList() const
{
	std::cout << std::left << "Mon" << "  Rain\n";

	for (auto nodePtr = rlist.getHead(); nodePtr; nodePtr = nodePtr->next)
		std::cout << std::right << nodePtr->data << '\n';
}


driver.cpp
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
#include <iostream>
#include "rainfall.h"

int main() {
	char userAnswer {};
	RainFall rf;

	do {
		std::cout << "\nA--Add a month of statistics\n"
			<< "R--Remove a month of statistics\n"
			<< "E--Edit a month of statistics\n"
			<< "P--Print report\n"
			<< "D--Display details\n"
			<< "Q--Quit\n"
			<< "\nChoice: ";

		std::cin >> userAnswer;

		switch (userAnswer) {
			case 'A':
			case 'a':
			{
				RainFall::Data rd;

				std::cout << "Enter month: ";
				std::cin >> rd.month;

				std::cout << "Enter rainfall: ";
				std::cin >> rd.rain;

				rf.appendNode(rd);
			}
			break;

			case 'E':
			case 'e':
			{
				int m {};

				std::cout << "Enter month: ";
				std::cin >> m;

				if (const auto f {rf.find(m)}; f != nullptr) {
					std::cout << "Current rainfall value is " << f->data.rain << '\n';
					std::cout << "Enter new rainfall: ";
					std::cin >> f->data.rain;
				} else
					std::cout << "Month not found\n";
			}
			break;

			case 'R':
			case 'r':
			{
				int m {};

				std::cout << "Enter month: ";
				std::cin >> m;

				if (const auto f {rf.find(m)}; f != nullptr)
					rf.remove(f->data);
				else
					std::cout << "Month not found\n";
			}
			break;

			case 'D':
			case 'd':
				rf.displayList();
				break;

			case 'P':
			case 'p':
				std::cout << "\nLow rain is " << rf.getLowestRainfall() << '\n';
				std::cout << "High rain is " << rf.getHighestRainfall() << '\n';
				std::cout << "Total rain is " << rf.getTotalRainfall() << '\n';
				break;

			case 'Q':
			case 'q':
				break;

		}
	} while (userAnswer != 'q' && userAnswer != 'Q');
}



VS solution/source files should have the 2 items rainfall.cpp and driver.cpp
Now compiles OK for me as split fils using VS.
Last edited on
For my code I must use file list.cpp and list.h. I cannot combine list.cpp and list.h into one file. I do I take what see plus has for the link.hpp file but make it two separate file called link.h and link.cpp
Last edited on
Pages: 123