Review My Code and Progress

Hello Guys

I am new to this forum so if I have broken any forum rules in what I'm doing then I do apologies.


I've been teaching myself C++ for about 3 months and it's time to have my code reviewed by others so that I can learn and grow.
I've decided to take all that I've learned and create a little user login application where you can create a new user with a password. The user will then store his favorite number. That's it.

when you compile and start the app you will get this screen:
-------------------------------------------

Could not open user.uls

Press Enter to continue........
--------------------------------------------

That is the file the the user will be saved to.

the Main Menu screen will look like this:

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

User List

[Enter a number]

0. New user

-1. Save and Exit
------------------------------------------------

after you create a user and come back to this screen it will update the list with your username(s) e.g
----------------------------------------------

User List

[Enter a number]

1. joeUser
2. joeUser
0. New user

-1. Save and Exit
------------------------------------------------

enter the number next to the username and then it will prompt for a password.
If you forget your password then type "admin1234" to get in.

And that's about it.

It's bare bones but this program was more for practice; particularly in creating linked list and file management.

Review and be as brutally honest as possible.

the code and documentation is quite large so it will take a couple of posts

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
#define NOMINMAX
#include <windows.h>
#include <iostream>
#include <fstream>
#include <cstring>

/* User info output file name */
const char* FILE_NAME     = "user.uls";

/* used as a passowrd override */
const char* OVERRIDE      = "admin1234";

/* global constants for various flags */
const int   FORCE_EXIT    = 1,
	    NO_FORCE_EXIT = 0,
	    ENTER_INFO    = 1,
	    NEW_USER      = 1,
	    BUFFER_CLEAR  = 0,
	    ERROR_MESSAGE = 1,
	    PAUSE         = 2,
	    EXIT_MESSAGE  = 3,
	    MAX_CHAR      = 4;

//----------------------------------------------//
/* utility(int):
   clears buffer, displays a message, and clears 
   cin error flag if necessary.
   Can be used to pause the program.            */
//----------------------------------------------//
void utility(int message)
{
	if (std::cin.fail())
		std::cin.clear();
	
	if (message == PAUSE)  
		std::cout << "\nPress Enter to continue....\n";

	if (message == EXIT_MESSAGE)  
		std::cout << "\nPress Enter to exit....\n";

	/* clear cin buffer */
	std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );

	if (message == ERROR_MESSAGE)  {

		std::cout << "INVALID INPUT\n";
		std::cout << "TRY AGAIN\n\n";
	}

	if (message == MAX_CHAR)  {

		std::cout << "TOO MANY CHARACTERS\n";
		std::cout << "TRY AGAIN\n\n";
	}
}

//------------------------------------------//
/* clear_screen():
   Uses Windows API to clear console screen */
//------------------------------------------//
void clear_screen()
{
	HANDLE                     hStdOut;
	CONSOLE_SCREEN_BUFFER_INFO csbi;
	DWORD                      count;
	DWORD                      cellCount;
	COORD                      homeCoords = { 0, 0 };

	hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );

	if (hStdOut == INVALID_HANDLE_VALUE) 
		return;

	/* Get the number of cells in the current buffer */
	if (!GetConsoleScreenBufferInfo( hStdOut, &csbi )) 
		return;

	cellCount = csbi.dwSize.X *csbi.dwSize.Y;

	/* Fill the entire buffer with spaces */
	if (!FillConsoleOutputCharacter( hStdOut, (TCHAR) ' ', cellCount, homeCoords, &count )) 
		return;

	/* Fill the entire buffer with the current colors and attributes */
	if (!FillConsoleOutputAttribute( hStdOut, csbi.wAttributes, cellCount, homeCoords, &count ))
		return;

	/* Move the cursor home */
	SetConsoleCursorPosition( hStdOut, homeCoords );
}

//------------------------------------//
/* FILE_HANDLE:
   template structure to handle files */
//------------------------------------//
template<class TYPE>
struct FILE_HANDLE
{
	TYPE file;  // ifstream, ofstream, or fstream data type

	FILE_HANDLE(const char* f_name, int mode, int force_exit)
	{
		file.open( f_name, mode );

		if (file.fail())  {

			std::cout << "\nCould not open " << f_name << '\n';

			if (force_exit)  {

				utility( EXIT_MESSAGE );
				exit(1);
			}
			else
				utility( PAUSE );
		}
	}
	/* close file upon destruction of handle */
	~FILE_HANDLE() { file.close(); }
};

//------------------------------------------------------------------------------------------------------//
/* UserList:
   This class uses a linked list structure to store users and their
   info.

   The design is (kinda like) a privately contained user interface. The program just needs to
   call mainMenu() method and the Object does the rest.
   
   Private Methods:
	void mainMenuPrompt()         clear screen and prompt for the main menu 
	void userMenuPrompt()         clear screen and prompt fot the user menu
	void newUser(int = 0)         creates new user node in linked list
	void getUser(int)             selects user node
	bool correctPassword(char[])  checks string input
	void userMenu()               menu for current user
	void showInfo()               clear screen and display current user's info
	void enterInfo(int = 0)       enters or edits current user's info
	void deleteUser()             deletes current user node
	void encryption()             encrypts or decrypts user's data
	void readFile()               reads list data from file and creates nodes from data
	void writeFile()              writes list data to file and deletes all nodes
	
  Public Methods:
	UserList()                    calls readFile()
	~UserList()                   calls writeFile()
	void mainMenu()               main 'run' method for User List
	void printUsers()             prints a list of saved user's

  -----------------------------------------------------------------------------------------------------
	                               [User List user interface Flow:]

						  mainMenu() [loop]
						     /      \
				      newUser(int = 0)       getUser(int)
					   |                           |
			       enterInfo(int = 0)	  	    userMenu() [loop]
				  |			  		  |
		        userMenu() [loop]		       -------------------------
			      |				      /           |             \
	          -------------------------	      showInfo()   enterInfo(int = 0)   deleteUser()
	         /            |             \
	 showInfo()   enterInfo(int = 0)   deleteUser()
                                                                                                        */
//------------------------------------------------------------------------------------------------------//
class UserList
{

//-----------------//
/* private membors */
//-----------------//

	static const int USERNAME_SIZE = 31,              
		         PASSWORD_SIZE = 11;

	             int user_node_count,     // node counter
		         current_node_id;     // assigns a different ID to each node

	/* Node/Node Pointer Structure */
	typedef struct user_node  {

		char       user_name[USERNAME_SIZE];     // array to hold username
		char       user_password[PASSWORD_SIZE]; // array to hold password
		int        user_id,                      // stores unique user id
		           secret_number;                // user's secret data
		user_node* next;                         // points to next node in list

	}* user_node_ptr;

	/* pointers to manipulate linked list */
	user_node_ptr head;  // points to first node in the list at all times
	user_node_ptr curr;  // points to current node that is being manipulated
	user_node_ptr temp;  // temporary pointer: used for writing nodes to a file and/or deleting nodes 


continued....
Last edited on
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
//-----------------//
/* Private Methods */
//-----------------//

	void mainMenuPrompt()
	{
		clear_screen();
		std::cout << "\n   User List\n";
		std::cout << "\n[Enter a number]\n\n";
		printUsers();
		std::cout << "0. New User\n";
		std::cout << "\n-1. Save and Exit\n\n";
	}

	void userMenuPrompt()
	{
		clear_screen();
		std::cout << "\n   User Menu\n";
		std::cout << "\n[Enter a number]\n\n";
		std::cout << "1. Show info\n";
		std::cout << "2. Edit Account\n";
		std::cout << "3. Delete Account\n";
		std::cout << "0. Back to User List\n\n";
	}

	//------------------------------------------------//
	/* newUser():
	   Takes a parameter which specifies whether this 
	   method was called from readFile() or from 
	   mainMenu(). It defaults to 0 */
	//------------------------------------------------//
	void newUser(int enter_info = 0)
	{
		/* creates a new node called 'n'
		   and make it point to NULL*/
		user_node_ptr n = new user_node;
		n->next = NULL;

		/* if 'n' is not the first node created in the list... */
		if (head != NULL)  {

			/* move 'curr' pointer to last node in list */
			curr = head;
			while (curr->next != NULL)
				curr = curr->next;

			/* make the last node point to new node 'n'
			   so that 'n' is now the last node in the
			   list */
			curr->next = n;
		}
		/* else 'n' is the first node...*/
		else  {

			/* make 'n' the head */
			head = n;
		}

		/* make sure 'curr' pointer is pointing to newly
		   created node */
		curr = n;

		/* if this method is called from mainMenu() then
		   info will be entered manually by the user */
		if (enter_info)  {

			/* increment node id and call method
			   to enter data */
			current_node_id++;
			enterInfo( NEW_USER );
		}
	}

	//------------------------------------------------//
	/* getUser():
	   Takes a parameter which specifies which node in 
	   list to have the 'curr' pointer point to */
	//------------------------------------------------//
	void getUser(int user_choice)
	{
		clear_screen();

		/* move 'curr' pointer to specified user
		   choice */
		curr = head;
		for (int i = 1; i < user_choice; i++)
			curr = curr->next;

		/* prompt for password */
		char input[PASSWORD_SIZE];
		std::cout << "\nEnter Password: ";
		std::cin.getline( input, PASSWORD_SIZE );

		/* if password checks good then go to
		   current user menu else display
		   message */
		if (correctPassword( input )) 
			userMenu();
		else  {

			std::cout << "\nWrong Password\n";
			utility(PAUSE);
		}
	}

	//--------------------------------------------------//
	/* correctPassword():
	   First it checks if string entered matches the 
	   override password. If that fails then it checks 
	   if string matches password that is in the current
	   node. If both fail then the method returns false */
	//--------------------------------------------------//
	bool correctPassword(char test[])
	{
		bool correct = true;

		/* match with override password */
		int index = 0;
		int test_length = strlen(test);
		int string_length = strlen(OVERRIDE);

		if (test_length != string_length)
			correct = false;

		while (index < string_length && correct)  {

			if (test[index] != OVERRIDE[index])
				correct = false;
			index++;
		}

		
		if (!correct)  {

			/* match with current stored user password */
			correct = true;
			index = 0;
			string_length = strlen(curr->user_password);

			if (test_length != string_length)
				correct = false;

			while (index < string_length && correct)  {

				if (test[index] != curr->user_password[index])
					correct = false;
				index++;			
			}
		}
		return correct;			
	}

	//----------------------------------//
	/* userMenu():
	   displays a menu where the user 
	   can edit his/her account.
	   three options:
	   1. show info
	   2. edit info
	   3. delete account                */
	//----------------------------------//
	void userMenu()
	{
		int user_choice = 0;

		/* Loop until User is chooses to exit */
		do  {
			/* input validation loop */
			userMenuPrompt();
			while (!(std::cin >> user_choice) || user_choice < 0 || user_choice > 3)  {
			
				userMenuPrompt();
				utility( ERROR_MESSAGE );
			}
			utility( BUFFER_CLEAR );
			
			/* Menu Options */
			if (user_choice == 1)
				showInfo();

			if (user_choice == 2)
				enterInfo();

			if (user_choice == 3)
				deleteUser();

		} while (user_choice == 1 || user_choice == 2);
	}

	//----------------------------//
	/* showInfo():
	   Displays user account info */   
	//----------------------------//
	void showInfo()
	{
		clear_screen();
		std::cout << "\nUsername: " << curr->user_name << '\n';
		std::cout << "Password: " << curr->user_password << '\n';
		std::cout << "User ID: " << curr->user_id << '\n';
		std::cout << "Favorite Number: " << curr->secret_number << '\n';
		utility( PAUSE );
	}

	//------------------------------------------------//
	/* enterInfo():
	   Method to enter or edit current user data.
           Takes a parameter which specifies whether this 
	   method was called from newUser() or from 
	   userMenu(). It defaults to 0	                 */   
	//-----------------------------------------------//
	void enterInfo(int new_user = 0)
	{
		clear_screen();	

		/* if this method is called from newUser()..*/
		if (new_user)  {

			if (user_node_count == 15)  {

				std::cout << "Already at Max number of Users.";
				utility( PAUSE );
				return;
			}
			
			/* increment the node counter and then assign new
			   node with a unique ID.
			   Note: each node created will have a different ID
			         even if all node are then deleted */
			user_node_count++;
			curr->user_id = current_node_id;
		}

		/* Enter/edit info */

		/* input validation loop */
		std::cout << "\nEnter a new Username\n<Max: 30 characters>\n: ";
		while (!std::cin.getline( curr->user_name, USERNAME_SIZE ))  {

			utility( MAX_CHAR );	
			std::cout << "Enter a new Username\n<Max: 30 characters>\n: ";
		}

		/* input validation loop */
		std::cout << "\nEnter a new Password\n<Max: 10 characters>\n: ";
		while(!std::cin.getline( curr->user_password, PASSWORD_SIZE ))  {

			utility( MAX_CHAR );	
			std::cout << "Enter a new Password\n<Max: 10 characters>\n: ";
		}

		/* input validation loop */
		std::cout << "\nEnter Favorite Number: ";
		while(!(std::cin >> curr->secret_number))  {

			utility( ERROR_MESSAGE );	
			std::cout << "Enter Favorite Number: ";
		}		

		/* If this is a newly created node then this method 
		   was called from newUser(). Thus go to userMenu(). 
		   See [User List Interface Flow] chart at the top
		   of class definition */
		if (new_user)
			userMenu();
	}
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
        //------------------------------------//
	/* deleteUser():
	   Method to delete current user node */   
	//------------------------------------//
	void deleteUser()
	{
		/* create a pointer to use for deletion */
		user_node_ptr del;
		
		/* make 'temp' point to the first node */
		temp = head;

		/* if the node to be deleted (curr) IS NOT the head
		   then move 'temp' pointer to the node right
		   before the node that 'curr' is pointing to */
		temp = head;
		if (curr != head)  {

			while(temp->next != curr)
				temp = temp->next;
		}

		/* if the node to be deleted IS the head then
		   move 'head' pointer to the next node (or
		   to NULL if this is the only node left in the 
		   list) */
		else
			head = head->next;

		/* move deletion pointer to it's destination */
		del = curr;

		/* move 'curr' pointer to the next node (or NULL) */
		curr = curr->next;

		/* make the node that 'temp' is pointing to point to
		   'curr' node so that the list will still be intact
		   (or to NULL) */
		temp->next = curr;

		/* now that the user node is isolated, it can be
		   deleted and then retire 'temp' pointer */
		delete del;
		temp = NULL;
		
		/* decrement the node counter */
		user_node_count--;

		clear_screen();
		std::cout << "\nUser Deleted.\n";
		utility(PAUSE);
	}

	//------------------------------------//
	/* encryption():
	   Method to encrypt or decrypt username,
	   password, favorite number, and ID in
	   node */   
	//------------------------------------//
	void encryption()
	{
		char key1 = 'k';
		int key2 = 286;

		for (int i = 0; i < USERNAME_SIZE; i++)
			curr->user_name[i] ^= key1;

		for (int i = 0; i < PASSWORD_SIZE; i++)
			curr->user_password[i] ^= key1;	

		curr->secret_number ^= key2;
		curr->user_id       ^= key2;
	}
	
	//-----------------------------------------------//
	/* readFile():
	   Method to read data from file and then load it
	   into a newly created node. Process repeats until
	   all users from file are in nodes.
	   The first data in the file will be the number
	   of users in the list.
	   The second data will, be the current node ID
	   number.                                       */   
	//-----------------------------------------------//
	void readFile()
	{
		FILE_HANDLE<std::ifstream> user( FILE_NAME, std::ios::binary, NO_FORCE_EXIT );

		/* if file exits */
		if (user.file)  {

			/* Read data that specifies how many user are in the file */
			user.file.read( reinterpret_cast<char*>(&user_node_count), sizeof(user_node_count) );
			
			/* Read data that specifies current unique ID number */
			user.file.read( reinterpret_cast<char*>(&current_node_id), sizeof(current_node_id) );
			
			/* this loop will iterate until all users from file are read */ 
			for (int i = 0; i < user_node_count; i++)  {

				/* create new node */
				newUser();

				/* load node with encrypted data */
				user.file.read( reinterpret_cast<char*>(curr), sizeof(*curr) );

				/* decrypted the data and then make sure the node
				   points to NULL */
				encryption();	
				curr->next = NULL;
			}
		}
	}

	//-----------------------------------------------//
	/* writeFile():
	   Method to read data from file and then load it
	   into a newly created node. Process repeats until
	   all users from file are in nodes.
	   The first data in the file will be the number
	   of users in the list.
	   The second data will, be the current node ID
	   number.                                       */   
	//-----------------------------------------------//
	void writeFile()
	{
		FILE_HANDLE<std::ofstream> user( FILE_NAME, std::ios::binary, NO_FORCE_EXIT );

		/* write the number of current users to file */
		user.file.write( reinterpret_cast<char*>(&user_node_count), sizeof(user_node_count) );

		/* write current unique ID to file */
		user.file.write( reinterpret_cast<char*>(&current_node_id), sizeof(current_node_id) );

		/* move 'temp' and 'curr' to 'head' and then 
		   retire 'head' pointer */
		curr = head;
		temp = head;
		head = NULL;
		
		/* loop until all node have been written to file and 
		   deleted from memory */
		while (temp != NULL)  {

			/* move temp to next node (or NULL) */
			temp = temp->next;

			/* encrypt data in 'curr' node */
			encryption();

			/* write encrypted data in 'curr' node to file */
			user.file.write( reinterpret_cast<char*>(curr), sizeof(*curr) );

			/* delete 'curr' node from memory */
			delete curr;

			/* move curr to next node (or NULL) */
			curr = temp;
		}
	}
	
public:

	//--------------//
	/* CONSTRUCTOR */	   
	//--------------//
	UserList()
	{
		/* initialize membors */
		head = NULL;
		curr = NULL;
		temp = NULL;

		user_node_count = 0;
		current_node_id = 0;

		/* load saved user's into nodes */
		readFile();
	}

	//-------------//
	/* DESTRUCTOR */	   
	//-------------//
	~UserList() 
	{ 
		/* save user's to file upon object's destruction */
		writeFile(); 
	}	

	//------------------------------------------//
	/* mainMenu():
	   Method used as a interface to navigate 
	   and manipulate list object.
	   
	   Main Menu Options:
	    #. select a user from list
	    0. create a new user
	   -1. exit and save                       */
	//-----------------------------------------//
	void mainMenu()
	{
		int user_choice = 0;

		do  {
			/* input validation loop */
			mainMenuPrompt();
			while (!(std::cin >> user_choice) || user_choice < -1 || user_choice > user_node_count)  {

				mainMenuPrompt();				
				utility( ERROR_MESSAGE );
			}
			utility(BUFFER_CLEAR);

			/* Menu Options */
			if (user_choice == 0)
				newUser( ENTER_INFO );

			else if (user_choice != -1)
				getUser( user_choice );
		
		} while (user_choice != -1);
	}

	//------------------------------//
	/* printUser():
	   prints a list of saved users */
	//------------------------------//
	void printUsers()
	{
		int count = 1;
		curr = head;
		while (curr != NULL)  {

			std::cout << count << ". " << curr->user_name << "\n";
			curr = curr->next;
			count++;
		}
	}
};

//------------------------------//
/* createList();
   Function to create object and
   start list menu.
   Note: This function was more
         of a means to test the 
         life and death of the
         UserList object: e.g
         if the object properly
         writes to file during
         destruction.           */
//------------------------------//
void createList()
{
	/* creat list object */
	UserList test;

	/* start list manipulation program */
	test.mainMenu();	
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//------------------------------//
/* MAIN():
   Loops createList() function */
//------------------------------//
int main(int argc, char** argv)
{
	int again = 0;

	do  {
		createList();
		std::cout << "\nRecreate User List object? ";
		std::cin >> again;
		utility( BUFFER_CLEAR );

	} while (again);

	utility( EXIT_MESSAGE );

	return 0;
}
Again if this is too large for this forum, I'm sorry
I was skimming so I might be wrong, but I don't see a reason why you included Windows.h, that's a pretty heavy library to include if you aren't using it. Other than that I don't have anything bad to say about the program.

It looks like you know how to use dynamic memory, so (if you haven't already) now would be a good time to learn the container libraries like "vector.h" because they are more stable and a bit easier to use (less likely to cause memory leaks).

Your program shows a good level of understanding in native C++, looks like you are ready to take on a graphics library (like Windows.h or SFML) if you wanted to.

If you wanted more practice in C++ then try out a couple of Euler Project problems, they are brain teasers meant specifically for programmers.
Thanks for your input.

As far as the windows.h library, I needed it for the function 'clear_screen()' which uses the windows library so that I could clear the screen without using that hated system( ) functions.

I guess it is time for me to move on to vectors and <strings>.

I must say that graphics libraries seem overwhelming. I'm not sure if I'm ready for that....yet. :)
closed account (o1vk4iN6)
1
2
3
4
5
6
7
8
9
const int   FORCE_EXIT    = 1,
	    NO_FORCE_EXIT = 0,
	    ENTER_INFO    = 1,
	    NEW_USER      = 1,
	    BUFFER_CLEAR  = 0,
	    ERROR_MESSAGE = 1,
	    PAUSE         = 2,
	    EXIT_MESSAGE  = 3,
	    MAX_CHAR      = 4;


Using enum here instead of defining a bunch of constants of the same type that can accidentally be used unintentionally would be ideal. That is to say it would be a pain to debug if such a mistake were to occur.

~FILE_HANDLE() { file.close(); }

You don't need to call the close function as closing is handled in the destructors of *fstreams. You could also use static_assert and type_traits if you are using C++11 to ensure the type passed to FILE_HANDLE is derived from the streams.
Last edited on
Topic archived. No new replies allowed.