Tag Archives: While Loop
C++ || Multi Digit, Decimal & Negative Number Infix To Postfix Conversion & Evaluation
The following is sample code which demonstrates the implementation of a multi digit, decimal, and negative number infix to postfix converter and evaluator using a Finite State Machine
REQUIRED KNOWLEDGE FOR THIS PROGRAM
How To Convert Infix To Postfix
How To Evaluate A Postfix Expression
What Is A Finite State Machine?
Using a Finite State Machine, the program demonstrated on this page has the ability to convert and evaluate a single digit, multi digit, decimal number, and/or negative number infix equation. So for example, if the the infix equation of (19.87 * -2) was entered into the program, the converted postfix expression of 19.87 ~2* would display to the screen, as well as the final evaluated answer of -39.74.
NOTE: In this program, negative numbers are represented by the “~” symbol on the postfix string. This is used to differentiate between a negative number and a subtraction symbol.
This program has the following flow of control:
• Get an infix expression from the user
• Convert the infix expression to postfix
• Use a Finite State Machine to isolate all of the math operators, multi digit, decimal, negative and single digit numbers that are found in the postfix expression
• Evaluate the postfix expression using the tokens found from the above step
• Display the evaluated answer to the screen
The above steps are implemented 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 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 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 |
// ============================================================================ // Author: Kenneth Perkins // Taken From: http://programmingnotes.org/ // Date: Jan 31, 2014 // File: InToPostEval.cpp // Description: The following demonstrates the implementation of an infix to // postfix converter and evaluator. Using a Finite State Machine, this // program has the ability to convert and evaluate multi digit, decimal, // negative and positive values. // ============================================================================ #include <iostream> #include <cstdlib> #include <cmath> #include <cctype> #include <string> #include <vector> #include <stack> #include <algorithm> using namespace std; /* This holds the transition states for our Finite State Machine -- They are placed in numerical order for easy understanding within the FSM array, which is located below */ enum FSM_TRANSITIONS { REJECT = 0, INTEGER, REAL, NEGATIVE, OPERATOR, UNKNOWN, SPACE }; /* This is the Finite State Machine -- The zero represents a place holder, so the row in the array starts on row 1 instead of 0 integer, real, negative, operator, unknown, space */ int stateTable[][7] = { {0, INTEGER, REAL, NEGATIVE, OPERATOR, UNKNOWN, SPACE}, /* STATE 1 */ {INTEGER, INTEGER, REAL, REJECT, REJECT, REJECT, REJECT}, /* STATE 2 */ {REAL, REAL, REJECT, REJECT, REJECT, REJECT, REJECT}, /* STATE 3 */ {NEGATIVE, INTEGER, REAL, REJECT, REJECT, REJECT, REJECT}, /* STATE 4 */ {OPERATOR, REJECT, REJECT, REJECT, REJECT, REJECT, REJECT}, /* STATE 5 */ {UNKNOWN, REJECT, REJECT, REJECT, REJECT, UNKNOWN, REJECT}, /* STATE 6 */ {SPACE, REJECT, REJECT, REJECT, REJECT, REJECT, REJECT} }; // function prototypes void DisplayDirections(); string ConvertInfixToPostfix(string infix); bool IsMathOperator(char token); int OrderOfOperations(char token); vector<string> Lexer(string postfix); int Get_FSM_Col(char& currentChar); double EvaluatePostfix(const vector<string>& postfix); double Calculate(char token, double op1, double op2); int main() { // declare variables string infix = ""; string postfix = ""; double answer = 0; vector<string> tokens; // display directions to user DisplayDirections(); // get data from user cout << "\nPlease enter an Infix expression: "; getline(cin, infix); postfix = ConvertInfixToPostfix(infix); // use the "Lexer" function to isolate multi digit, negative and decimal // numbers, aswell as single digit numbers and math operators tokens = Lexer(postfix); // display the found tokens to the screen //for (unsigned x = 0; x < tokens.size(); ++x) //{ // cout<<tokens.at(x)<<endl; //} cout << "\nThe Infix expression = " << infix; cout << "\nThe Postfix expression = " << postfix << endl; answer = EvaluatePostfix(tokens); cout << "\nFinal answer = " << answer << endl; cin.get(); return 0; }// end of main void DisplayDirections() {// this function displays instructions to the screen cout << "\n==== Infix To Postfix Conversion & Evaluation ====\n" << "\nMath Operators:\n" << "+ || Addition\n" << "- || Subtraction\n" << "* || Multiplication\n" << "/ || Division\n" << "% || Modulus\n" << "^ || Power\n" << "$ || Square Root\n" << "s || Sine\n" << "c || Cosine\n" << "t || Tangent\n" << "- || Negative Number\n" << "Sample Infix Equation: ((s(-4^5)*1.4)/($(23+2)--2.8))*(c(1%2)/(7.28*.1987)^(t23))\n"; // ((sin(-4^5)*1.4)/(sqrt(23+2)--2.8))*(cos(1%2)/(7.28*.1987)^(tan(23))) }// end of DisplayDirections string ConvertInfixToPostfix(string infix) {// this function converts an infix expression to postfix // declare function variables string postfix; stack<char> charStack; // remove all whitespace from the string infix.erase(std::remove_if(infix.begin(), infix.end(), [](char c) { return std::isspace(static_cast<unsigned char>(c)); }), infix.end()); // automatically convert negative numbers to have the ~ symbol for (unsigned x = 0; x < infix.length(); ++x) { if (infix[x] != '-') { continue; } else if (x + 1 < infix.length() && IsMathOperator(infix[x + 1])) { continue; } if (x == 0 || infix[x - 1] == '(' || IsMathOperator(infix[x - 1])) { infix[x] = '~'; } } // loop thru array until there is no more data for (unsigned x = 0; x < infix.length(); ++x) { // place numbers (standard, decimal, & negative) // numbers onto the 'postfix' string if ((isdigit(infix[x])) || (infix[x] == '.') || (infix[x] == '~')) { postfix += infix[x]; } else if (isspace(infix[x])) { continue; } else if (IsMathOperator(infix[x])) { postfix += " "; // use the 'OrderOfOperations' function to check equality // of the math operator at the top of the stack compared to // the current math operator in the infix string while ((!charStack.empty()) && (OrderOfOperations(charStack.top()) >= OrderOfOperations(infix[x]))) { // place the math operator from the top of the // stack onto the postfix string and continue the // process until complete postfix += charStack.top(); charStack.pop(); } // push the remaining math operator onto the stack charStack.push(infix[x]); } // push outer parentheses onto stack else if (infix[x] == '(') { charStack.push(infix[x]); } else if (infix[x] == ')') { // pop the current math operator from the stack while ((!charStack.empty()) && (charStack.top() != '(')) { // place the math operator onto the postfix string postfix += charStack.top(); // pop the next operator from the stack and // continue the process until complete charStack.pop(); } if (!charStack.empty()) // pop '(' symbol off the stack { charStack.pop(); } else // no matching '(' { cout << "\nPARENTHESES MISMATCH #1\n"; exit(1); } } else { cout << "\nINVALID INPUT #1\n"; exit(1); } } // place any remaining math operators from the stack onto // the postfix array while (!charStack.empty()) { postfix += charStack.top(); charStack.pop(); } return postfix; }// end of ConvertInfixToPostfix bool IsMathOperator(char token) {// this function checks if operand is a math operator switch (tolower(token)) { case '+': case '-': case '*': case '/': case '%': case '^': case '$': case 'c': case 's': case 't': return true; break; default: return false; break; } }// end of IsMathOperator int OrderOfOperations(char token) {// this function returns the priority of each math operator int priority = 0; switch (tolower(token)) { case 'c': case 's': case 't': priority = 5; break; case '^': case '$': priority = 4; break; case '*': case '/': case '%': priority = 3; break; case '-': priority = 2; break; case '+': priority = 1; break; } return priority; }// end of OrderOfOperations vector<string> Lexer(string postfix) {// this function parses a postfix string using an FSM to generate // each individual token in the expression vector<string> tokens; char currentChar = ' '; int col = REJECT; int currentState = REJECT; string currentToken = ""; // use an FSM to parse multidigit and decimal numbers // also does error check for invalid input of decimals for (unsigned x = 0; x < postfix.length();) { currentChar = postfix[x]; // get the column number for the current character col = Get_FSM_Col(currentChar); // exit if the real number has multiple periods "." // in the expression (i.e: 19.3427.23) if ((currentState == REAL) && (col == REAL)) { cerr << "\nINVALID INPUT #2\n"; exit(1); } /* ======================================================== THIS IS WHERE WE CHECK THE FINITE STATE MACHINE TABLE USING THE "col" VARIABLE FROM ABOVE ^ ========================================================= */ // get the current state of our machine currentState = stateTable[currentState][col]; /* =================================================== THIS IS WHERE WE CHECK FOR A SUCCESSFUL PARSE - If the current state in our machine == REJECT (the starting state), then we have successfully parsed a token, which is returned to its caller - ELSE we continue trying to find a successful token =================================================== */ if (currentState == REJECT) { if (currentToken != " ") // we dont care about whitespace { tokens.push_back(currentToken); } currentToken = ""; } else { currentToken += currentChar; ++x; } } // this ensures the last token gets saved when // we reach the end of the postfix string buffer if (currentToken != " ") // we dont care about whitespace { tokens.push_back(currentToken); } return tokens; }// end of Lexer int Get_FSM_Col(char& currentChar) {// this function determines the state of the type of character being examined // check for whitespace if (isspace(currentChar)) { return SPACE; } // check for integer numbers else if (isdigit(currentChar)) { return INTEGER; } // check for real numbers else if (currentChar == '.') { return REAL; } // check for negative numbers else if (currentChar == '~') { currentChar = '-'; return NEGATIVE; } // check for math operators else if (IsMathOperator(currentChar)) { return OPERATOR; } return UNKNOWN; }// end of Get_FSM_Col double EvaluatePostfix(const vector<string>& postfix) {// this function evaluates a postfix expression // declare function variables double op1 = 0; double op2 = 0; double answer = 0; stack<double> doubleStack; cout << "\nCalculations:\n"; // loop thru array until there is no more data for (unsigned x = 0; x < postfix.size(); ++x) { // push numbers onto the stack if ((isdigit(postfix[x][0])) || (postfix[x][0] == '.')) { doubleStack.push(atof(postfix[x].c_str())); } // push negative numbers onto the stack else if ((postfix[x].length() > 1) && ((postfix[x][0] == '-') && (isdigit(postfix[x][1]) || (postfix[x][1] == '.')))) { doubleStack.push(atof(postfix[x].c_str())); } // if expression is a math operator, pop numbers from stack // & send the popped numbers to the 'Calculate' function else if (IsMathOperator(postfix[x][0]) && (!doubleStack.empty())) { char token = tolower(postfix[x][0]); // if expression is square root, sin, cos, // or tan operation only pop stack once if (token == '$' || token == 's' || token == 'c' || token == 't') { op2 = 0; op1 = doubleStack.top(); doubleStack.pop(); answer = Calculate(token, op1, op2); doubleStack.push(answer); } else if (doubleStack.size() > 1) { op2 = doubleStack.top(); doubleStack.pop(); op1 = doubleStack.top(); doubleStack.pop(); answer = Calculate(token, op1, op2); doubleStack.push(answer); } } else // this should never execute, & if it does, something went really wrong { cout << "\nINVALID INPUT #3\n"; exit(1); } } // pop the final answer from the stack, and return to main if (!doubleStack.empty()) { answer = doubleStack.top(); } return answer; }// end of EvaluatePostfix double Calculate(char token, double op1, double op2) {// this function carries out the actual math process double ans = 0; switch (tolower(token)) { case '+': cout << op1 << token << op2 << " = "; ans = op1 + op2; break; case '-': cout << op1 << token << op2 << " = "; ans = op1 - op2; break; case '*': cout << op1 << token << op2 << " = "; ans = op1 * op2; break; case '/': cout << op1 << token << op2 << " = "; ans = op1 / op2; break; case '%': cout << op1 << token << op2 << " = "; ans = ((int)op1 % (int)op2) + modf(op1, &op2); break; case '^': cout << op1 << token << op2 << " = "; ans = pow(op1, op2); break; case '$': cout << char(251) << op1 << " = "; ans = sqrt(op1); break; case 'c': cout << "cos(" << op1 << ") = "; ans = cos(op1); break; case 's': cout << "sin(" << op1 << ") = "; ans = sin(op1); break; case 't': cout << "tan(" << op1 << ") = "; ans = tan(op1); break; default: ans = 0; break; } cout << ans << endl; return ans; }// http://programmingnotes.org/ |
QUICK NOTES:
The highlighted lines are sections of interest to look out for.
The code is heavily commented, so no further insight is necessary. If you have any questions, feel free to leave a comment below.
The following is sample output.
====== RUN 1 ======
==== Infix To Postfix Conversion & Evaluation ====Math Operators:
+ || Addition
- || Subtraction
* || Multiplication
/ || Division
% || Modulus
^ || Power
$ || Square Root
s || Sine
c || Cosine
t || Tangent
~ || Negative NumberSample Infix Equation: ((s(~4^5)*1.4)/($(23+2)-~2.8))*(c(1%2)/(7.28*.1987)^(t23))
Please enter an Infix expression: 12/3*9
The Infix expression = 12/3*9
The Postfix expression = 12 3 /9*Calculations:
12/3 = 4
4*9 = 36Final answer = 36
====== RUN 2 ======
==== Infix To Postfix Conversion & Evaluation ====
Math Operators:
+ || Addition
- || Subtraction
* || Multiplication
/ || Division
% || Modulus
^ || Power
$ || Square Root
s || Sine
c || Cosine
t || Tangent
~ || Negative NumberSample Infix Equation: ((s(~4^5)*1.4)/($(23+2)-~2.8))*(c(1%2)/(7.28*.1987)^(t23))
Please enter an Infix expression: -150.89996 - 87.56643
The Infix expression = -150.89996 - 87.56643
The Postfix expression = ~150.89996 87.56643-Calculations:
-150.9-87.5664 = -238.466Final answer = -238.466
====== RUN 3 ======
==== Infix To Postfix Conversion & Evaluation ====
Math Operators:
+ || Addition
- || Subtraction
* || Multiplication
/ || Division
% || Modulus
^ || Power
$ || Square Root
s || Sine
c || Cosine
t || Tangent
~ || Negative NumberSample Infix Equation: ((s(~4^5)*1.4)/($(23+2)-~2.8))*(c(1%2)/(7.28*.1987)^(t23))
Please enter an Infix expression: ((s(~4^5)*1.4)/($(23+2)-~2.8))*(c(1%2)/(7.28*.1987)^(t23))
The Infix expression = ((s(-4^5)*1.4)/($(23+2)--2.8))*(c(1%2)/(7.28*.1987)^(t23))
The Postfix expression = ~4 5^ s1.4* 23 2+ $~2.8-/ 1 2% c7.28 .1987* 23t^/*Calculations:
-4^5 = -1024
sin(-1024) = 0.158533
0.158533*1.4 = 0.221947
23+2 = 25
√25 = 5
5--2.8 = 7.8
0.221947/7.8 = 0.0284547
1%2 = 1
cos(1) = 0.540302
7.28*0.1987 = 1.44654
tan(23) = 1.58815
1.44654^1.58815 = 1.79733
0.540302/1.79733 = 0.300614
0.0284547*0.300614 = 0.00855389Final answer = 0.00855389
====== RUN 4 ======
==== Infix To Postfix Conversion & Evaluation ====
Math Operators:
+ || Addition
- || Subtraction
* || Multiplication
/ || Division
% || Modulus
^ || Power
$ || Square Root
s || Sine
c || Cosine
t || Tangent
- || Negative Number
Sample Infix Equation: ((s(-4^5)*1.4)/($(23+2)--2.8))*(c(1%2)/(7.28*.1987)^(t23))Please enter an Infix expression: (1987 + 1991) * -1
The Infix expression = (1987 + 1991) * -1
The Postfix expression = 1987 1991+ ~1*Calculations:
1987+1991 = 3978
3978*-1 = -3978Final answer = -3978
Python || Random Number Guessing Game Using Random MyRNG & While Loop
Here is another homework assignment which was presented in introduction class. The following is a simple guessing game using commandline arguments, which demonstrates the use of generating random numbers.
REQUIRED KNOWLEDGE FOR THIS PROGRAM
How To Get User Input
Getting Commandline Arguments
While Loops
MyRNG.py - Random Number Class
==== 1. DESCRIPTION ====
The following program is a simple guessing game which demonstrates how to generate random numbers using python. This program will seed the random number generator (located in the file MyRNG.py), select a number at random, and then ask the user for a guess. Using a while loop, the user will keep attempting to guess the selected random number until the correct guess is obtained, afterwhich the user will have the option of continuing play or exiting.
==== 2. USAGE ====
The user enters various options into the program via the commandline. An example of how the commandline can be used is given below.
python3 guess.py [-h] [-v] -s [seed] -m 2 -M 353
Where the brackets are meant to represent features which are optional, meaning the user does not have to specify them at run time.
The -m and -M options are mandatory.
• -M is best picked as a large prime integer
• -m is best picked as an integer in the range of 2,3,..,M-1
NOTE: The use of commandline arguments is not mandatory. If any of the mandatory options are not selected, the program uses its own logic to generate random numbers.
==== 3. FEATURES ====
The following lists and explains the command line argument options.
• -s (seed): Seed takes an integer as a parameter and is used to seed the random number generator. When omitted, the program uses its own logic to seed the generator
• -v (verbose): Turn on debugging messages.
• -h (help): Print out a help message which tells the user how to run the program and a brief description of the program.
• -m (minimum): Set the minimum of the range of numbers the program will select its numbers from.
• -M (maximum): Set the maximum of the range of numbers the program will select its numbers from.
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 |
# ============================================================================= # Name: K Perkins # Date: Aug 6, 2013 # Taken From: http://programmingnotes.org/ # File: guess.py # Description: This is the guess.py module which uses a random number # generator to simulate a simple guessing game. This program will seed the # random number generator (located in the file MyRNG.py), select a number at # random, and then ask the user for a guess. The user will keep attempting # to guess the selected random number until the correct guess is obtained, # afterwhich the user will have the option of continuing play or exiting # ============================================================================= # Sample commandline: guess.py -s 3454 -m 1 -M 1000 import sys, pdb from MyRNG import * def Usage(status, msg = ""): # Function prints out usage directions aswell as a simple # message if a string is sent as a 2nd parameter if(msg): print(msg) print("nUSAGE:n ", sys.argv[0],"[-h help] [-v] [-s seed] [-m minimum number]", "[-M maximum number]") sys.exit(status) def IsWarmer(userGuess, numGuess, randomNumber): # Function determines if the current number the user guesses is closer # to the random number than the previous guess. # Function returns TRUE if current user guess is 'warmer' # than previous, otherwise returns FALSE currGuessDifference = userGuess[numGuess] - randomNumber currGuessDifference = math.fabs(currGuessDifference) prevGuessDifference = userGuess[numGuess-1] - randomNumber prevGuessDifference = math.fabs(prevGuessDifference) if(currGuessDifference < prevGuessDifference): return True else: return False def main(): # This is the 'main' function which first takes a string via the commandline # and parses it to determine various modes of operation, namely being # 'seed,' 'minimum,' and 'maximum.' After the commandline options # are obtained, that information is sent to the MyRNG class in order # to generate a random number. After a random number is found, using # a while loop, the user is prompted to try and guess that specified # number, repeatedly doing so until a correct guess is found # declare variables index = 0 # counter which is used to index the sys.argv string verbose = False choices = (("y"),("yes"),("n"),("no")) # This is to be used for the while loop seed = 806189064 # saves the seed from the command line minimum = 1 # saves the minimum num from the command line maximum = 1000 # saves the maximum num from the command line loop = True # this controls the while loop randomNumber = 0 # this saves the random number from the generator userGuess = [] # this saves the user guesses numGuess = 0 # this is the counter wgich keeps track of the num of usr guesses newGame = True # bool to determine if the user is playing a new game programDescr = """nDESCRIPTION: The following is a simple guessing game in which the user is prompted to guess a number and the computer determines if the guess is above, below or exactly the random number which was selected.""" # == determine if the user entered enough args via commandline == # if(len(sys.argv) < 1): #if not enough args, stop the program and print an error message Usage(1, "n** Must provide atleast 1 argument") # == parse thru the argv string to find the appropriate tokens == # for currentArg in sys.argv: if(currentArg == "-h"): # print out the usage message and exit. Usage(2, programDescr) elif(currentArg == "-v"): # set verbose mode to be true for debugging messages verbose = True elif(currentArg == "-s"): # set the seed here # if the user doesnt specify a seed, the # default is my CWID if((index+1 < len(sys.argv)) and (sys.argv[index+1].isdigit())): seed = int(sys.argv[index+1]) else: seed = 806189064 elif currentArg == "-m": # set the minimum here # if the user doesnt specify a min, the default is 1 if((index+1 < len(sys.argv)) and (sys.argv[index+1].isdigit())): minimum = int(sys.argv[index+1]) else: minimum = 1 elif currentArg == "-M": # set the maximum here # if the user doesnt specify a max, the default is 1000 if((index+1 < len(sys.argv)) and (sys.argv[index+1].isdigit())): maximum = int(sys.argv[index+1]) else: maximum = 1000 # increment the index counter index += 1 # print debugging messages if debug mode is on if(verbose): print ("nThis message only appears if verbose mode is turned on.") print (""" ** To continue seeing debugging messages, press the "n" button when prompted. To print the current value of variables, press the "p" button followed by the name of the variable you wish to print. Press the "l" button to visually see where you are in the programs souce code. To quit debugging, press the "c" button.n""") pdb.set_trace() print("nSeed = %d, Minimum = %d, Maximum = %d" %(seed, minimum, maximum)) # == declare the class object == # random = MyRNG(minimum, maximum) random.Seed(seed) randomNumber = random.Next() print("nI'm thinking of a number between %d and %d" ". Go ahead and make your first guess. " %(minimum, maximum)) # * this is the while loop which simulates a guessing game. # * the loop gets a number from the user and determines if the # user input is a "winner, warmer, or colder" in relation to the # random number which was generated. # * once the user guesses correctly, they have a choice of continuing # play or exiting the game. If they choose to play again, a new # random number is generated while(loop): userGuess.append(int(input(">> "))) if(newGame): newGame = False if((userGuess[numGuess] > randomNumber) or (userGuess[numGuess] < randomNumber)): print("nSorry that was not correct, please try again...n") elif((userGuess[numGuess] > randomNumber) or (userGuess[numGuess] < randomNumber)): if(IsWarmer(userGuess, numGuess, randomNumber)): print("nWARMERn") else: print("nCOLDERn") if(userGuess[numGuess] == randomNumber): print("nWINNER! You have guessed correctly!") print("It took you %d attempt(s) to find the answer!" %(numGuess+1)) del userGuess[:] numGuess = -1 answer = input("nWould you like to play again? (Yes or No): ") answer = answer.lower() if(answer in choices[:2]): randomNumber = random.Next() print("nMake a guess between %d and %dn" %(minimum, maximum)) newGame = True elif((answer in choices[2:]) or (answer not in choices[2:])): loop = False numGuess += 1 print("nThanks for playing!!") if __name__ == "__main__": main() # http://programmingnotes.org/ |
QUICK NOTES:
The highlighted lines are sections of interest to look out for.
The code is heavily commented, so no further insight is necessary. If you have any questions, feel free to leave a comment below.
Once compiled, you should get this as your output:
Seed = 806189064, Minimum = 1, Maximum = 1000
I'm thinking of a number between 1 and 1000. Go ahead and make your first guess.
>> 500Sorry that was not correct, please try again...
>> 400
WARMER
>> 600
COLDER
>> 300
WARMER
>> 150
WARMER
>> 100
COLDER
>> 180
COLDER
>> 190
COLDER
>> 130
WARMER
>> 128
WINNER! You have guessed correctly!
It took you 10 attempt(s) to find the answer!Would you like to play again? (Yes or No): y
------------------------------------------------------------
Make a guess between 1 and 1000
>> 500
Sorry that was not correct, please try again...
>> 600
COLDER
>> 400
WARMER
>> 300
WARMER
>> 280
WARMER
>> 260
WARMER
>> 250
COLDER
>> 256
WINNER! You have guessed correctly!
It took you 8 attempt(s) to find the answer!Would you like to play again? (Yes or No): n
Thanks for playing!!
C++ || Custom Template Hash Map With Iterator Using Separate Chaining
Before we get into the code, what is a Hash Map? Simply put, a Hash Map is an extension of a Hash Table; which is a data structure used to map unique “keys” to specific “values.” The Hash Map demonstrated on this page is different from the previous Hash Table implementation in that key/value pairs do not need to be the same datatype, they can be completely different. So for example, if you wish to map a string “key” to an integer “value“, utilizing a Hash Map is ideal.
In its most simplest form, a Hash Map can be thought of as an associative array, or a “dictionary.” Hash Map’s are composed of a collection of key/value pairs, such that each possible key appears atleast once in the collection for a given value. While a standard array requires that indice subscripts be integers, a hash map can use a string, an integer, or even a floating point value as the index. That index is called the “key,” and the contents within the array at that specific index location is called the “value.” A hash map uses a hash function to generate an index into the table, creating buckets or slots, from which the correct value can be found.
To illustrate, suppose that you’re working with some data that has values associated with strings — for instance, you might have student names and you wish to assign them grades. How would you store this data? Depending on your skill level, you might use multiple arrays during the implementation. For example, in terms of a one dimensional array, if we wanted to access the data for a student located at index #25, we could access it by doing:
studentNames[25]; // do something with the data
studentGrades[25];
Here, we dont have to search through each element in the array to find what we need, we just access it at index #25. The question is, how do we know that index #25 holds the data that we are looking for? If we have a large set of data, not only will keeping track of multiple arrays become tiresome, but doing a sequential search over each item within the separate arrays can become very inefficient. That is where hashing comes in handy. Using a Hash Map, we can use the students name as the “key,” and the students grade as the data “value.” Given this “key” (the students name), we can apply a hash function to map a unique index or bucket within the hash table to find the data “value” (the students grade) that we wish to access.
So in essence, a Hash Map is an extension of a hash table, which is a data structure that stores key/value pairs. Hash tables are typically used because they are ideal for doing a quick search of items.
Though hashing is ideal, it isnt perfect. It is possible for multiple “keys” to be hashed into the same location. Hash “collisions” are practically unavoidable when hashing large data sets. The code demonstrated on this page handles collisions via separate chaining, utilizing an array of linked list head nodes to store multiple keys within one bucket – should any collisions occur.
A special feature of this current hash map class is that its implemented as a multimap, meaning that more than one “value” can be associated with a given “key.” For example, in a student enrollment system where students may be enrolled in multiple classes simultaneously, there might be an association for each enrollment where the “key” is the student ID, and the “value” is the course ID. In this example, if a given student is enrolled in three courses, there will be three associated “values” (course ID’s) for one “key” (student ID) in the Hash Map.
An iterator was also implemented, making data access that much more simple within the hash map class. Click here for an overview demonstrating how custom iterators can be built.
=== CUSTOM TEMPLATE HASH MAP WITH ITERATOR ===
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 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 |
// ============================================================================ // Author: Kenneth Perkins // Date: June 11, 2013 // Taken From: http://programmingnotes.org/ // File: HashMap.h // Description: This is a class which implements various functions // demonstrating the use of a Hash Map. // ============================================================================ #ifndef TEMPLATE_HASH_MAP #define TEMPLATE_HASH_MAP #include <iostream> #include <string> #include <sstream> #include <cstdlib> // if user doesnt define, this is the // default hash map size const int HASH_SIZE = 350; template <class Key, class Value> class HashMap { public: HashMap(int hashSze = HASH_SIZE); /* Function: Constructor initializes hash map Precondition: None Postcondition: Defines private variables */ bool IsEmpty(int keyIndex); /* Function: Determines whether hash map is empty at the given hash map key index Precondition: Hash map has been created Postcondition: The function = true if the hash map is empty and the function = false if hash map is not empty */ bool IsFull(); /* Function: Determines whether hash map is full Precondition: Hash map has been created Postcondition: The function = true if the hash map is full and the function = false if hash map is not full */ int Hash(Key m_key); /* Function: Computes and returns a hash map key index for a given item The returned key index is the given cell where the item resides Precondition: Hash map has been created and is not full Postcondition: The hash key is returned */ void Insert(Key m_key, Value m_value); /* Function: Adds new item to the back of the list at a given key in the hash map A unique hash key is automatically generated for each new item Precondition: Hash map has been created and is not full Postcondition: Item is in the hash map */ bool Remove(Key m_key, Value deleteItem); /* Function: Removes the first instance from the map whose value is "deleteItem" Precondition: Hash map has been created and is not empty Postcondition: The function = true if deleteItem is found and the function = false if deleteItem is not found */ void Sort(int keyIndex); /* Function: Sort the items in the map at the given hashmap key index Precondition: Hash map has been initialized Postcondition: The hash map is sorted */ int TableSize(); /* Function: Return the size of the hash map Precondition: Hash map has been initialized Postcondition: The size of the hash map is returned */ int TotalElems(); /* Function: Return the total number of elements contained in the hash map Precondition: Hash map has been initialized Postcondition: The size of the hash map is returned */ int BucketSize(int keyIndex); /* Function: Return the number of items contained in the hash map cell at the given hashmap key index Precondition: Hash map has been initialized Postcondition: The size of the given key cell is returned */ int Count(Key m_key, Value searchItem); /* Function: Return the number of times searchItem appears in the map at the given key Precondition: Hash map has been initialized Postcondition: The number of times searchItem appears in the map is returned */ int ContainsKey(Key m_key); /* Function: Return the number of times the given key appears in the hashmap Precondition: Hash map has been initialized Postcondition: The number of times the given key appears in the map is returned */ void MakeEmpty(); /* Function: Initializes hash map to an empty state Precondition: Hash map has been created Postcondition: Hash map no longer exists */ ~HashMap(); /* Function: Removes the hash map Precondition: Hash map has been declared Postcondition: Hash map no longer exists */ // -- ITERATOR CLASS -- class Iterator; /* Function: Class declaration to the iterator Precondition: Hash map has been declared Postcondition: Hash Iterator has been declared */ Iterator begin(int keyIndex){return(!IsEmpty(keyIndex)) ? head[keyIndex]:NULL;} /* Function: Returns the beginning of the current hashmap key index Precondition: Hash map has been declared Postcondition: Hash cell has been returned to the Iterator */ Iterator end(int keyIndex=0){return NULL;} /* Function: Returns the end of the current hashmap key index Precondition: Hash map has been declared Postcondition: Hash cell has been returned to the Iterator */ private: struct KeyValue // struct to hold key/value pairs { Key key; Value value; }; struct node { KeyValue currentItem; node* next; }; node** head; // array of linked list declaration - front of each hash map cell int hashSize; // the size of the hash map (how many cells it has) int totElems; // holds the total number of elements in the entire table int* bucketSize; // holds the total number of elems in each specific hash map cell }; //========================= Implementation ================================// template <class Key, class Value> HashMap<Key, Value>::HashMap(int hashSze) { hashSize = hashSze; head = new node*[hashSize]; bucketSize = new int[hashSize]; for(int x=0; x < hashSize; ++x) { head[x] = NULL; bucketSize[x] = 0; } totElems = 0; }/* End of HashMap */ template <class Key, class Value> bool HashMap<Key, Value>::IsEmpty(int keyIndex) { if(keyIndex >=0 && keyIndex < hashSize) { return head[keyIndex] == NULL; } return true; }/* End of IsEmpty */ template <class Key, class Value> bool HashMap<Key, Value>::IsFull() { try { node* location = new node; delete location; return false; } catch(std::bad_alloc&) { return true; } }/* End of IsFull */ template <class Key, class Value> int HashMap<Key, Value>::Hash(Key m_key) { long h = 19937; std::stringstream convert; // convert the parameter to a string using "stringstream" which is done // so we can hash multiple datatypes using only one function convert << m_key; std::string temp = convert.str(); for(unsigned x=0; x < temp.length(); ++x) { h = (h << 6) ^ (h >> 26) ^ temp[x]; } return abs(h % hashSize); } /* End of Hash */ template <class Key, class Value> void HashMap<Key, Value>::Insert(Key m_key, Value m_value) { if(IsFull()) { //std::cout<<"\nINSERT ERROR - HASH MAP FULL\n"; } else { int keyIndex = Hash(m_key); node* newNode = new node; // add new node newNode-> currentItem.key = m_key; newNode-> currentItem.value = m_value; newNode-> next = NULL; if(IsEmpty(keyIndex)) { head[keyIndex] = newNode; } else { node* temp = head[keyIndex]; while(temp-> next != NULL) { temp = temp-> next; } temp-> next = newNode; } ++bucketSize[keyIndex]; ++totElems; } }/* End of Insert */ template <class Key, class Value> bool HashMap<Key, Value>::Remove(Key m_key, Value deleteItem) { bool isFound = false; node* temp; int keyIndex = Hash(m_key); if(IsEmpty(keyIndex)) { //std::cout<<"\nREMOVE ERROR - HASH MAP EMPTY\n"; } else if(head[keyIndex]->currentItem.key == m_key && head[keyIndex]->currentItem.value == deleteItem) { temp = head[keyIndex]; head[keyIndex] = head[keyIndex]-> next; delete temp; --totElems; --bucketSize[keyIndex]; isFound = true; } else { for(temp = head[keyIndex];temp->next!=NULL;temp=temp->next) { if(temp->next->currentItem.key == m_key && temp->next->currentItem.value == deleteItem) { node* deleteNode = temp->next; temp-> next = temp-> next-> next; delete deleteNode; isFound = true; --totElems; --bucketSize[keyIndex]; break; } } } return isFound; }/* End of Remove */ template <class Key, class Value> void HashMap<Key, Value>::Sort(int keyIndex) { if(IsEmpty(keyIndex)) { //std::cout<<"\nSORT ERROR - HASH MAP EMPTY\n"; } else { int listSize = BucketSize(keyIndex); bool sorted = false; do{ sorted = true; int x = 0; for(node* temp = head[keyIndex]; temp->next!=NULL && x < listSize-1; temp=temp->next,++x) { if(temp-> currentItem.value > temp->next->currentItem.value) { std::swap(temp-> currentItem,temp->next->currentItem); sorted = false; } } --listSize; }while(!sorted); } }/* End of Sort */ template <class Key, class Value> int HashMap<Key, Value>::TableSize() { return hashSize; }/* End of TableSize */ template <class Key, class Value> int HashMap<Key, Value>::TotalElems() { return totElems; }/* End of TotalElems */ template <class Key, class Value> int HashMap<Key, Value>::BucketSize(int keyIndex) { return(!IsEmpty(keyIndex)) ? bucketSize[keyIndex]:0; }/* End of BucketSize */ template <class Key, class Value> int HashMap<Key, Value>::Count(Key m_key, Value searchItem) { int keyIndex = Hash(m_key); int search = 0; if(IsEmpty(keyIndex)) { //std::cout<<"\nCOUNT ERROR - HASH MAP EMPTY\n"; } else { for(node* temp = head[keyIndex];temp!=NULL;temp=temp->next) { if(temp->currentItem.key == m_key && temp->currentItem.value == searchItem) { ++search; } } } return search; }/* End of Count */ template <class Key, class Value> int HashMap<Key, Value>::ContainsKey(Key m_key) { int keyIndex = Hash(m_key); int search = 0; if(IsEmpty(keyIndex)) { //std::cout<<"\nCONTAINS KEY ERROR - HASH MAP EMPTY\n"; } else { for(node* temp = head[keyIndex];temp!=NULL;temp=temp->next) { if(temp->currentItem.key == m_key) { ++search; } } } return search; }/* End of ContainsKey */ template <class Key, class Value> void HashMap<Key, Value>::MakeEmpty() { totElems = 0; for(int x=0; x < hashSize; ++x) { if(!IsEmpty(x)) { //std::cout << "Destroying nodes ...\n"; while(!IsEmpty(x)) { node* temp = head[x]; //std::cout << temp-> currentItem.value <<std::endl; head[x] = head[x]-> next; delete temp; } } bucketSize[x] = 0; } }/* End of MakeEmpty */ template <class Key, class Value> HashMap<Key, Value>::~HashMap() { MakeEmpty(); delete[] head; delete[] bucketSize; }/* End of ~HashMap */ // END OF THE HASH MAP CLASS // ----------------------------------------------------------- // START OF THE HASH MAP ITERATOR CLASS template <class Key, class Value> class HashMap<Key, Value>::Iterator : public std::iterator<std::forward_iterator_tag,Value>, public HashMap<Key, Value> { public: // Iterator constructor Iterator(node* otherIter = NULL) { itHead = otherIter; } ~Iterator() {} // The assignment and relational operators are straightforward Iterator& operator=(const Iterator& other) { itHead = other.itHead; return(*this); } bool operator==(const Iterator& other)const { return itHead == other.itHead; } bool operator!=(const Iterator& other)const { return itHead != other.itHead; } bool operator<(const Iterator& other)const { return itHead < other.itHead; } bool operator>(const Iterator& other)const { return other.itHead < itHead; } bool operator<=(const Iterator& other)const { return (!(other.itHead < itHead)); } bool operator>=(const Iterator& other)const { return (!(itHead < other.itHead)); } // Update my state such that I refer to the next element in the // HashMap. Iterator operator+(int incr) { node* temp = itHead; for(int x=0; x < incr && temp!= NULL; ++x) { temp = temp->next; } return temp; } Iterator operator+=(int incr) { for(int x=0; x < incr && itHead!= NULL; ++x) { itHead = itHead->next; } return itHead; } Iterator& operator++() // pre increment { if(itHead != NULL) { itHead = itHead->next; } return(*this); } Iterator operator++(int) // post increment { node* temp = itHead; this->operator++(); return temp; } KeyValue& operator[](int incr) { // Return "junk" data // to prevent the program from crashing if(itHead == NULL || (*this + incr) == NULL) { return junk; } return(*(*this + incr)); } // Return a reference to the value in the node. I do this instead // of returning by value so a caller can update the value in the // node directly. KeyValue& operator*() { // Return "junk" data // to prevent the program from crashing if(itHead == NULL) { return junk; } return itHead->currentItem; } KeyValue* operator->() { return(&**this); } private: node* itHead; KeyValue junk; }; #endif // http://programmingnotes.org/ |
QUICK NOTES:
The highlighted lines are sections of interest to look out for.
The iterator class starts on line #381, and is built to support most of the standard relational operators, as well as arithmetic operators such as ‘+,+=,++’ (pre/post increment). The * (star), bracket [] and -> arrow operators are also supported. Click here for an overview demonstrating how custom iterators can be built.
The rest of the code is heavily commented, so no further insight is necessary. If you have any questions, feel free to leave a comment below.
===== DEMONSTRATION HOW TO USE =====
Use of the above template class is the same as many of its STL template class counterparts. Here are sample programs demonstrating its use.
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 |
// DEMONSTRATE BASIC USE AND THE REMOVE / SORT FUNCTIONS #include <iostream> #include <string> #include "HashMap.h" using namespace std; // iterator declaration typedef HashMap<string, int>::Iterator iterDec; int main() { // declare variables HashMap<string, int> hashMap; // place items into the hash map using the 'insert' function // NOTE: its OK for dupicate keys to be inserted into the hash map hashMap.Insert("BIOL", 585); hashMap.Insert("CPSC", 386); hashMap.Insert("ART", 101); hashMap.Insert("CPSC", 462); hashMap.Insert("HIST", 251); hashMap.Insert("CPSC", 301); hashMap.Insert("MATH", 270); hashMap.Insert("PE", 145); hashMap.Insert("BIOL", 134); hashMap.Insert("GEOL", 201); hashMap.Insert("CIS", 465); hashMap.Insert("CPSC", 240); hashMap.Insert("GEOL", 101); hashMap.Insert("MATH", 150); hashMap.Insert("DANCE", 134); hashMap.Insert("CPSC", 131); hashMap.Insert("ART", 345); hashMap.Insert("CHEM", 185); hashMap.Insert("PE", 125); hashMap.Insert("CPSC", 120); // display the number of times the key "CPSC" appears in the hashmap cout<<"The key 'CPSC' appears in the hash map "<< hashMap.ContainsKey("CPSC")<<" time(s)\n"; // declare an iterator for the "CPSC" key so we can display data to screen iterDec it = hashMap.begin(hashMap.Hash("CPSC")); // display the first value cout<<"\nThe first item with the key 'CPSC' is: " <<it[0].value<<endl; // display all the values in the hash map whose key matches "CPSC" // NOTE: its possible for multiple different keys types // to be placed into the same hash map bucket cout<<"\nThese are all the items in the hash map whose key is 'CPSC': \n"; for(int x=0; x < hashMap.BucketSize(hashMap.Hash("CPSC")); ++x) { if(it[x].key == "CPSC") // make sure this is the key we are looking for { cout<<" Key-> "<<it[x].key<<"\tValue-> "<<it[x].value<<endl; } } // remove the first value from the key "CPSC" cout<<"\n[REMOVE THE VALUE '"<<it[0].value<<"' FROM THE KEY '"<<it[0].key<<"']\n"; hashMap.Remove("CPSC",it[0].value); // display the number of times the key "CPSC" appears in the hashmap cout<<"\nNow the key 'CPSC' only appears in the hash map "<< hashMap.ContainsKey("CPSC")<<" time(s)\n"; // update the iterator to the current hash map state it = hashMap.begin(hashMap.Hash("CPSC")); // sort the values in the hash map bucket whose key is "CSPC" hashMap.Sort(hashMap.Hash("CPSC")); // display the values whose key matches "CPSC" cout<<"\nThese are the sorted items in the hash map whose key is 'CPSC': \n"; for(int x=0; x < hashMap.BucketSize(hashMap.Hash("CPSC")); ++x) { if(it[x].key == "CPSC") { cout<<" Key-> "<<it[x].key<<"\tValue-> "<<it[x].value<<endl; } } // display all the key/values in the entire hash map cout<<"\nThese are all of the items in the entire hash map: \n"; for(int x=0; x < hashMap.TableSize(); ++x) { if(!hashMap.IsEmpty(x)) { for(iterDec iter = hashMap.begin(x); iter != hashMap.end(x); ++iter) { cout<<" Key-> "<<(*iter).key<<"\tValue-> "<<iter->value<<endl; } cout<<endl; } } // display the total number of items in the hash map cout<<"The total number of items in the hash map is: "<< hashMap.TotalElems()<<endl; return 0; }// http://programmingnotes.org/ |
SAMPLE OUTPUT:
The key 'CPSC' appears in the hash map 6 time(s)
The first item with the key 'CPSC' is: 386
These are all the items in the hash map whose key is 'CPSC':
Key-> CPSC Value-> 386
Key-> CPSC Value-> 462
Key-> CPSC Value-> 301
Key-> CPSC Value-> 240
Key-> CPSC Value-> 131
Key-> CPSC Value-> 120[REMOVE THE VALUE '386' FROM THE KEY 'CPSC']
Now the key 'CPSC' only appears in the hash map 5 time(s)
These are the sorted items in the hash map whose key is 'CPSC':
Key-> CPSC Value-> 120
Key-> CPSC Value-> 131
Key-> CPSC Value-> 240
Key-> CPSC Value-> 301
Key-> CPSC Value-> 462These are all of the items in the entire hash map:
Key-> CIS Value-> 465Key-> DANCE Value-> 134
Key-> PE Value-> 145
Key-> PE Value-> 125Key-> MATH Value-> 270
Key-> MATH Value-> 150Key-> GEOL Value-> 201
Key-> GEOL Value-> 101Key-> CPSC Value-> 120
Key-> CPSC Value-> 131
Key-> CPSC Value-> 240
Key-> CPSC Value-> 301
Key-> CPSC Value-> 462Key-> BIOL Value-> 585
Key-> BIOL Value-> 134Key-> ART Value-> 101
Key-> ART Value-> 345Key-> CHEM Value-> 185
Key-> HIST Value-> 251
The total number of items in the hash map is: 19
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 |
// DISPLAY ALL DATA INSIDE HASH MAP USING STD::STRING / INT / DOUBLE / STRUCT #include <iostream> #include <string> #include "HashMap.h" using namespace std; // sample struct demo struct MyStruct { string car; int year; double mpg; // struct comparison operators // used for 'remove' function bool operator == (const MyStruct& rhs)const { return car == rhs.car && year == rhs.year && mpg == rhs.mpg; } // used for 'sort' function bool operator > (const MyStruct& rhs)const { return car > rhs.car; } };// end of MyStruct // iterator declaration typedef HashMap<string, MyStruct>::Iterator iterDec; int main() { // declare variables MyStruct access; HashMap<string, MyStruct> hashMap(10); // --- initialize data for car #1 --- access.car = "Ford Fusion"; access.year = 2006; access.mpg = 28.5; hashMap.Insert("Kenneth",access); // --- initialize data for car #2 --- access.car = "BMW 535i"; access.year = 2014; access.mpg = 25.4; hashMap.Insert("Kenneth",access); // --- initialize data for car #3 --- access.car = "Nissan Altima"; access.year = 2011; access.mpg = 30.7; hashMap.Insert("Jessica",access); // --- initialize data for car #4 --- access.car = "Acura Integra"; access.year = 2001; access.mpg = 20.2; hashMap.Insert("Kenneth",access); // diplay how many cars "Kenneth" owns cout <<"'Kenneth' owns "<<hashMap.ContainsKey("Kenneth")<<" cars"<<endl; // display all items in the hash map // NOTE: its possible for multiple different keys types // to be placed into the same hash map bucket cout<<"\nThese are all of the cars in the hash map: \n"; for(int x=0; x < hashMap.TableSize(); ++x) { if(!hashMap.IsEmpty(x)) { // initialize an iterator iterDec iter = hashMap.begin(x); // display the key cout<<(*iter).key<<"'s car(s)\n"; // display all the values for(;iter != hashMap.end(x); ++iter) { cout<<"\tCar: "<<iter->value.car <<"\n\tYear: "<<iter->value.year <<"\n\tMPG: "<<iter->value.mpg<<endl<<endl; } } } // display the number of items in the hash map cout<<"The total number of cars in the hash map is: "<< hashMap.TotalElems()<<endl; // sort the cars that "Kenneth" owns by name cout<<"\nSorting the cars that 'Kenneth' owns by name.. \n"; hashMap.Sort(hashMap.Hash("Kenneth")); // display all items in the hash map again cout<<"\nAgain, these are all of the cars in the hash map: \n"; for(int x=0; x < hashMap.TableSize(); ++x) { if(!hashMap.IsEmpty(x)) { // initialize an iterator iterDec iter = hashMap.begin(x); // display the key cout<<iter->key<<"'s car(s)\n"; // display all the values for(;iter != hashMap.end(x); ++iter) { cout<<"\tCar: "<<(*iter).value.car <<"\n\tYear: "<<(*iter).value.year <<"\n\tMPG: "<<(*iter).value.mpg<<endl<<endl; } } } // remove the car 'Acura Integra' from "Kenneth's" inventory for(iterDec iter = hashMap.begin(hashMap.Hash("Kenneth")); iter != hashMap.end(hashMap.Hash("Kenneth")); ++iter) { if(iter->value.car == "Acura Integra") { cout<<"'"<<iter->value.car<<"' has been removed from 'Kenneth's' inventory..\n"; hashMap.Remove("Kenneth",(*iter).value); break; } } // display how many cars "Kenneth" owns cout <<"\n'Kenneth' now owns only "<<hashMap.ContainsKey("Kenneth")<<" cars"<<endl; // display all items in the hash map one more time cout<<"\nThese are all of the cars in the hash map with the 'Acura Integra' removed: \n"; for(int x=0; x < hashMap.TableSize(); ++x) { if(!hashMap.IsEmpty(x)) { // initialize an iterator iterDec iter = hashMap.begin(x); // display the key cout<<(*iter).key<<"'s car(s)\n"; // display all the values for(;iter != hashMap.end(x); ++iter) { cout<<"\tCar: "<<iter->value.car <<"\n\tYear: "<<iter->value.year <<"\n\tMPG: "<<iter->value.mpg<<endl<<endl; } } } // display the number of items in the hash map cout<<"The total number of cars in the hash map is: "<< hashMap.TotalElems()<<endl; return 0; }// http://programmingnotes.org/ |
SAMPLE OUTPUT:
'Kenneth' owns 3 cars
These are all of the cars in the hash map:
Jessica's car(s)
Car: Nissan Altima
Year: 2011
MPG: 30.7Kenneth's car(s)
Car: Ford Fusion
Year: 2006
MPG: 28.5Car: BMW 535i
Year: 2014
MPG: 25.4Car: Acura Integra
Year: 2001
MPG: 20.2
-----------------------------------------------------The total number of cars in the hash map is: 4
Sorting the cars that 'Kenneth' owns by name..
Again, these are all of the cars in the hash map:
Jessica's car(s)
Car: Nissan Altima
Year: 2011
MPG: 30.7Kenneth's car(s)
Car: Acura Integra
Year: 2001
MPG: 20.2Car: BMW 535i
Year: 2014
MPG: 25.4Car: Ford Fusion
Year: 2006
MPG: 28.5
-----------------------------------------------------'Acura Integra' has been removed from 'Kenneth's' inventory..
'Kenneth' now owns only 2 cars
These are all of the cars in the hash map with the 'Acura Integra' removed:
Jessica's car(s)
Car: Nissan Altima
Year: 2011
MPG: 30.7Kenneth's car(s)
Car: BMW 535i
Year: 2014
MPG: 25.4Car: Ford Fusion
Year: 2006
MPG: 28.5
-----------------------------------------------------The total number of cars in the hash map is: 3
C++ || Snippet – How To Convert A Decimal Number Into Binary
This page will demonstrate how to convert a decimal number (i.e a whole number) into its binary equivalent. So for example, if the decimal number of 26 was entered into the program, it would display the converted binary value of 11010.
REQUIRED KNOWLEDGE FOR THIS SNIPPET
How To Count In Binary
The "Long" Datatype - What Is It?
While Loops
Online Binary to Decimal Converter - Verify For Correct Results
How To Reverse A String
If you are looking for sample code which converts binary to decimal, check back here soon!
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 |
#include <iostream> #include <string> #include <algorithm> using namespace std; // function prototype string DecToBin(long long decNum); int main() { // declare variables long long decNum = 0; string binaryNum=""; // use a string instead of an int to avoid // overflow, because binary numbers can grow large quick cout<<"Please enter an integer value: "; cin >> decNum; if(decNum < 0) { binaryNum = "-"; } // call function to convert decimal to binary binaryNum += DecToBin(decNum); // display data to user cout<<"nThe integer value of "<<decNum<<" = "<<binaryNum<<" in binary"<<endl; return 0; } string DecToBin(long long decNum) { string binary = ""; // use this string to save the binary number if(decNum < 0) // if input is a neg number, make it positive { decNum *= -1; } // converts decimal to binary using division and modulus while(decNum > 0) { binary += (decNum % 2)+'0'; // convert int to char decNum /= 2; } // reverse the string reverse(binary.begin(), binary.end()); return binary; }// http://programmingnotes.org/ |
The highlighted lines are sections of interest to look out for.
The code is heavily commented, so no further insight is necessary. If you have any questions, feel free to leave a comment below.
Once compiled, you should get this as your output
Note: The code was compiled 3 separate times to display different output
====== RUN 1 ======
Please enter an integer value: 1987
The integer value of 1987 = 11111000011 in binary
====== RUN 2 ======
Please enter an integer value: -26
The integer value of -26 = -11010 in binary
====== RUN 3 ======
Please enter an integer value: 12345678910
The integer value of 12345678910 = 1011011111110111000001110000111110 in binary
C++ || Custom Template Hash Table With Iterator Using Separate Chaining
Looking for sample code for a Hash Map? Click here!
Before we get into the code, what is a Hash Table? Simply put, a Hash Table is a data structure used to implement an associative array; one that can map unique “keys” to specific values. While a standard array requires that indice subscripts be integers, a hash table can use a floating point value, a string, another array, or even a structure as the index. That index is called the “key,” and the contents within the array at that specific index location is called the value. A hash table uses a hash function to generate an index into the table, creating buckets or slots, from which the correct value can be found.
To illustrate, compare a standard array full of data (100 elements). If the position was known for the specific item that we wanted to access within the array, we could quickly access it. For example, if we wanted to access the data located at index #5 in the array, we could access it by doing:
array[5]; // do something with the data
Here, we dont have to search through each element in the array to find what we need, we just access it at index #5. The question is, how do we know that index #5 stores the data that we are looking for? If we have a large set of data, doing a sequential search over each item within the array can be very inefficient. That is where hashing comes in handy. Given a “key,” we can apply a hash function to a unique index or bucket to find the data that we wish to access.
So in essence, a hash table is a data structure that stores key/value pairs, and is typically used because they are ideal for doing a quick search of items.
Though hashing is ideal, it isnt perfect. It is possible for multiple items to be hashed into the same location. Hash “collisions” are practically unavoidable when hashing large data sets. The code demonstrated on this page handles collisions via separate chaining, utilizing an array of linked list head nodes to store multiple values within one bucket – should any collisions occur.
An iterator was also implemented, making data access that much more simple within the hash table class. Click here for an overview demonstrating how custom iterators can be built.
Looking for sample code for a Hash Map? Click here!
=== CUSTOM TEMPLATE HASH TABLE WITH ITERATOR ===
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 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 |
// ============================================================================ // Author: Kenneth Perkins // Date: Jan 18, 2013 // Taken From: http://programmingnotes.org/ // File: HashTable.h // Description: This is a class which implements various functions which // demonstrates the use of a Hash Table. // ============================================================================ #ifndef TEMPLATE_HASH_TABLE #define TEMPLATE_HASH_TABLE #include <iostream> #include <string> #include <sstream> #include <cstdlib> // if user doesnt define, this is the // default hash table size const int HASH_SIZE = 100; template <class ItemType> class HashTable { public: HashTable(int hashSze = HASH_SIZE); /* Function: Constructor initializes hash table Precondition: None Postcondition: Defines private variables */ bool IsEmpty(int key); /* Function: Determines whether hash table is empty at the given key Precondition: Hash table has been created Postcondition: The function = true if the hash table is empty and the function = false if hash table is not empty */ bool IsFull(); /* Function: Determines whether hash table is full Precondition: Hash table has been created Postcondition: The function = true if the hash table is full and the function = false if hash table is not full */ int Hash(ItemType newItem); /* Function: Computes and returns a unique hash key for a given item The returned key is the given cell where the item resides Precondition: Hash table has been created and is not full Postcondition: The hash key is returned */ void Insert(ItemType newItem); /* Function: Adds newItem to the back of the list at a given key in the hash table A unique hash key is automatically generated for each newItem Precondition: Hash table has been created and is not full Postcondition: Item is in the hash table */ void Append(int key, ItemType newItem); /* Function: Adds new item to the end of the list at a given key in the hash table Precondition: Hash table has been created and is not full Postcondition: Item is in the hash table */ bool Remove(ItemType deleteItem, int key = -1); /* Function: Removes the first instance from the table whose value is "deleteItem" Optional second parameter indicates the key where deleteItem is located Precondition: Hash table has been created and is not empty Postcondition: The function = true if deleteItem is found and the function = false if deleteItem is not found */ void Sort(int key); /* Function: Sort the items in the table at the given key Precondition: Hash table has been initialized Postcondition: The hash table is sorted */ int TableSize(); /* Function: Return the size of the hash table Precondition: Hash table has been initialized Postcondition: The size of the hash table is returned */ int TotalElems(); /* Function: Return the total number of elements contained in the hash table Precondition: Hash table has been initialized Postcondition: The size of the hash table is returned */ int BucketSize(int key); /* Function: Return the number of items contained in the hash table cell at the given key Precondition: Hash table has been initialized Postcondition: The size of the given key cell is returned */ int Count(ItemType searchItem); /* Function: Return the number of times searchItem appears in the table. Only works on items located in their correctly hashed cells Precondition: Hash table has been initialized Postcondition: The number of times searchItem appears in the table is returned */ void MakeEmpty(); /* Function: Initializes hash table to an empty state Precondition: Hash table has been created Postcondition: Hash table no longer exists */ ~HashTable(); /* Function: Removes the hash table Precondition: Hash table has been declared Postcondition: Hash table no longer exists */ // -- ITERATOR CLASS -- class Iterator; /* Function: Class declaration to the iterator Precondition: Hash table has been declared Postcondition: Hash Iterator has been declared */ Iterator begin(int key){return(!IsEmpty(key)) ? head[key]:NULL;} /* Function: Returns the beginning of the current hash cell list Precondition: Hash table has been declared Postcondition: Hash cell has been returned to the Iterator */ Iterator end(int key=0){return NULL;} /* Function: Returns the end of the current hash cell list Precondition: Hash table has been declared Postcondition: Hash cell has been returned to the Iterator */ private: struct node { ItemType currentItem; node* next; }; node** head; // array of linked list declaration - front of each hash table cell int hashSize; // the size of the hash table (how many cells it has) int totElems; // holds the total number of elements in the entire table int* bucketSize; // holds the total number of elems in each specific hash table cell }; //========================= Implementation ================================// template<class ItemType> HashTable<ItemType>::HashTable(int hashSze) { hashSize = hashSze; head = new node*[hashSize]; bucketSize = new int[hashSize]; for(int x=0; x < hashSize; ++x) { head[x] = NULL; bucketSize[x] = 0; } totElems = 0; }/* End of HashTable */ template<class ItemType> bool HashTable<ItemType>::IsEmpty(int key) { if(key >=0 && key < hashSize) { return head[key] == NULL; } return true; }/* End of IsEmpty */ template<class ItemType> bool HashTable<ItemType>::IsFull() { try { node* location = new node; delete location; return false; } catch(std::bad_alloc&) { return true; } }/* End of IsFull */ template<class ItemType> int HashTable<ItemType>::Hash(ItemType newItem) { long h = 19937; std::stringstream convert; // convert the parameter to a string using "stringstream" which is done // so we can hash multiple datatypes using only one function convert << newItem; std::string temp = convert.str(); for(unsigned x=0; x < temp.length(); ++x) { h = (h << 6) ^ (h >> 26) ^ temp[x]; } return abs(h % hashSize); } /* End of Hash */ template<class ItemType> void HashTable<ItemType>::Insert(ItemType newItem) { if(IsFull()) { //std::cout<<"nINSERT ERROR - HASH TABLE FULLn"; } else { int key = Hash(newItem); Append(key,newItem); } }/* End of Insert */ template<class ItemType> void HashTable<ItemType>::Append(int key, ItemType newItem) { if(IsFull()) { //std::cout<<"nAPPEND ERROR - HASH TABLE FULLn"; } else { node* newNode = new node; // adds new node newNode-> currentItem = newItem; newNode-> next = NULL; if(IsEmpty(key)) { head[key] = newNode; } else { node* tempPtr = head[key]; while(tempPtr-> next != NULL) { tempPtr = tempPtr-> next; } tempPtr-> next = newNode; } ++bucketSize[key]; ++totElems; } }/* End of Append */ template<class ItemType> bool HashTable<ItemType>::Remove(ItemType deleteItem, int key) { bool isFound = false; node* tempPtr; if(key == -1) { key = Hash(deleteItem); } if(IsEmpty(key)) { //std::cout<<"nREMOVE ERROR - HASH TABLE EMPTYn"; } else if(head[key]->currentItem == deleteItem) { tempPtr = head[key]; head[key] = head[key]-> next; delete tempPtr; --totElems; --bucketSize[key]; isFound = true; } else { for(tempPtr = head[key];tempPtr->next!=NULL;tempPtr=tempPtr->next) { if(tempPtr->next->currentItem == deleteItem) { node* deleteNode = tempPtr->next; tempPtr-> next = tempPtr-> next-> next; delete deleteNode; isFound = true; --totElems; --bucketSize[key]; break; } } } return isFound; }/* End of Remove */ template<class ItemType> void HashTable<ItemType>::Sort(int key) { if(IsEmpty(key)) { //std::cout<<"nSORT ERROR - HASH TABLE EMPTYn"; } else { int listSize = BucketSize(key); bool sorted = false; do{ sorted = true; int x = 0; for(node* tempPtr = head[key]; tempPtr->next!=NULL && x < listSize-1; tempPtr=tempPtr->next,++x) { if(tempPtr-> currentItem > tempPtr->next->currentItem) { ItemType temp = tempPtr-> currentItem; tempPtr-> currentItem = tempPtr->next->currentItem; tempPtr->next->currentItem = temp; sorted = false; } } --listSize; }while(!sorted); } }/* End of Sort */ template<class ItemType> int HashTable<ItemType>::TableSize() { return hashSize; }/* End of TableSize */ template<class ItemType> int HashTable<ItemType>::TotalElems() { return totElems; }/* End of TotalElems */ template<class ItemType> int HashTable<ItemType>::BucketSize(int key) { return(!IsEmpty(key)) ? bucketSize[key]:0; }/* End of BucketSize */ template<class ItemType> int HashTable<ItemType>::Count(ItemType searchItem) { int key = Hash(searchItem); int search = 0; if(IsEmpty(key)) { //std::cout<<"nCOUNT ERROR - HASH TABLE EMPTYn"; } else { for(node* tempPtr = head[key];tempPtr!=NULL;tempPtr=tempPtr->next) { if(tempPtr->currentItem == searchItem) { ++search; } } } return search; }/* End of Count */ template<class ItemType> void HashTable<ItemType>::MakeEmpty() { totElems = 0; for(int x=0; x < hashSize; ++x) { if(!IsEmpty(x)) { //std::cout << "Destroying nodes ...n"; while(!IsEmpty(x)) { node* temp = head[x]; //std::cout << temp-> currentItem <<std::endl; head[x] = head[x]-> next; delete temp; } } bucketSize[x] = 0; } }/* End of MakeEmpty */ template<class ItemType> HashTable<ItemType>::~HashTable() { MakeEmpty(); delete[] head; delete[] bucketSize; }/* End of ~HashTable */ // END OF THE HASH TABLE CLASS // ----------------------------------------------------------- // START OF THE HASH TABLE ITERATOR CLASS template <class ItemType> class HashTable<ItemType>::Iterator : public std::iterator<std::forward_iterator_tag,ItemType>, public HashTable<ItemType> { public: // Iterator constructor Iterator(node* otherIter = NULL) { itHead = otherIter; } ~Iterator() {} // The assignment and relational operators are straightforward Iterator& operator=(const Iterator& other) { itHead = other.itHead; return(*this); } bool operator==(const Iterator& other)const { return itHead == other.itHead; } bool operator!=(const Iterator& other)const { return itHead != other.itHead; } bool operator<(const Iterator& other)const { return itHead < other.itHead; } bool operator>(const Iterator& other)const { return other.itHead < itHead; } bool operator<=(const Iterator& other)const { return (!(other.itHead < itHead)); } bool operator>=(const Iterator& other)const { return (!(itHead < other.itHead)); } // Update my state such that I refer to the next element in the // HashTable. Iterator operator+(int incr) { node* temp = itHead; for(int x=0; x < incr && temp!= NULL; ++x) { temp = temp->next; } return temp; } Iterator operator+=(int incr) { for(int x=0; x < incr && itHead!= NULL; ++x) { itHead = itHead->next; } return itHead; } Iterator& operator++() // pre increment { if(itHead != NULL) { itHead = itHead->next; } return(*this); } Iterator operator++(int) // post increment { node* temp = itHead; this->operator++(); return temp; } ItemType& operator[](int incr) { // Return "junk" data // to prevent the program from crashing if(itHead == NULL || (*this + incr) == NULL) { return junk; } return(*(*this + incr)); } // Return a reference to the value in the node. I do this instead // of returning by value so a caller can update the value in the // node directly. ItemType& operator*() { // Return "junk" data // to prevent the program from crashing if(itHead == NULL) { return junk; } return itHead->currentItem; } ItemType* operator->() { return(&**this); } private: node* itHead; ItemType junk; }; #endif // http://programmingnotes.org/ |
QUICK NOTES:
The highlighted lines are sections of interest to look out for.
The iterator class starts on line #368, and is built to support most of the standard relational operators, as well as arithmetic operators such as ‘+,+=,++’ (pre/post increment). The * (star), bracket [] and -> arrow operators are also supported. Click here for an overview demonstrating how custom iterators can be built.
The rest of the code is heavily commented, so no further insight is necessary. If you have any questions, feel free to leave a comment below.
Looking for sample code for a Hash Map? Click here!
===== DEMONSTRATION HOW TO USE =====
Use of the above template class is the same as many of its STL template class counterparts. Here are sample programs demonstrating its use.
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 |
// DEMONSTRATE USE OF THE REMOVE AND SORT FUNCTIONS #include <iostream> #include <ctime> #include <string> #include <cstdlib> #include <iomanip> #include "HashTable.h" using namespace std; // iterator declarations typedef HashTable<string>::Iterator strIterDec; // hash table size const int TABLE_SIZE = 5; int main() { // delcare variables srand(time(NULL)); const string names[]={"Alva","Edda","Hiram","Lemuel","Della","Roseann","Sang", "Evelia","Claire","Marylou","Magda","Irvin","Reagan","Deb","Hillary", "Tuyetm","Cherilyn","Amina","Justin","Neville","Jessica","Demi", "Graham","Cinderella","Freddy","Vivan","Marjorie","Krystal","Liza", "Spencer","Jordon","Bernie","Geraldine","Kati","Jetta","Carmella", "Chery","Earlene","Gene","Lorri","Albertina","Ula","Karena","Johanna", "Alex","Tobias","Lashawna","Domitila","Chantel","Deneen","Nigel", "Lashanda","Donn","Theda","Many","Jeramy","Jodee","Tamra","Dessie", "Lawrence","Jaime","Basil","Roger","Cythia","Homer","Lilliam","Victoria", "Tod","Harley","Meghann","Jacquelyne","Arie","Rosemarie","Lyndon","Blanch", "Kenneth","Perkins","Kaleena"}; int nameLen = sizeof(names)/sizeof(names[0]); // Hash table class declarations HashTable<string> strHash(TABLE_SIZE); // insert 10 items into each hash table for(int x=0; x < (TABLE_SIZE*2); ++x) { // place all data in bucket 0 // NOTE: you dont want to place all data into one // bucket, this is done for demo purposes only // Normally use the "Insert" function instead strHash.Append(0,names[rand()%(nameLen-1)]); } // assign the iterator to bucket 0 strIterDec it = strHash.begin(0); // display bucket size cout<<"Bucket #0 has "<<strHash.BucketSize(0)<<" items"<<endl; // display the first item cout<<"The first element in bucket #0 is "<< it[0] <<endl; // remove the first item in bucket 0 // NOTE: the second parameter is optional // but since we know we want bucket 0, we use it here strHash.Remove(it[0],0); // update the iterator to the new table state it = strHash.begin(0); // display the new first item cout<<"nNow bucket #0 has "<<strHash.BucketSize(0)<<" items"<<endl; cout<<"The first element in bucket #0 is "<< it[0] <<endl; // display all the items within the "strHash" table cout<<"nThe unsorted items in strHash bucket #0:n"; for(int x=0; x < strHash.BucketSize(0); ++x) { cout << "it[] = " << it[x] << endl; } // sort the items in bucket 0 strHash.Sort(0); // display all the items within the "strHash" table cout<<"nThe sorted items in strHash bucket #0:n"; for(int x=0; x < strHash.BucketSize(0); ++x) { cout << "it[] = " << it[x] << endl; } return 0; }// http://programmingnotes.org/ |
SAMPLE OUTPUT:
Bucket #0 has 10 items
The first element in bucket #0 is HomerNow bucket #0 has 9 items
The first element in bucket #0 is TamraThe unsorted items in strHash bucket #0:
it[] = Tamra
it[] = Lyndon
it[] = Johanna
it[] = Perkins
it[] = Alva
it[] = Jordon
it[] = Neville
it[] = Lawrence
it[] = JettaThe sorted items in strHash bucket #0:
it[] = Alva
it[] = Jetta
it[] = Johanna
it[] = Jordon
it[] = Lawrence
it[] = Lyndon
it[] = Neville
it[] = Perkins
it[] = Tamra
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 |
// DISPLAY ALL DATA INSIDE TABLE USING STD::STRING / INT / STRUCT #include <iostream> #include <ctime> #include <string> #include <cstdlib> #include <iomanip> #include "HashTable.h" using namespace std; // sample struct demo struct MyStruct { string name; }; // iterator declarations typedef HashTable<string>::Iterator strIterDec; typedef HashTable<int>::Iterator intIterDec; typedef HashTable<MyStruct>::Iterator strctIterDec; // hash table size const int TABLE_SIZE = 10; int main() { // delcare variables srand(time(NULL)); const string names[]={"Alva","Edda","Hiram","Lemuel","Della","Roseann","Sang", "Evelia","Claire","Marylou","Magda","Irvin","Reagan","Deb","Hillary", "Tuyetm","Cherilyn","Amina","Justin","Neville","Jessica","Demi", "Graham","Cinderella","Freddy","Vivan","Marjorie","Krystal","Liza", "Spencer","Jordon","Bernie","Geraldine","Kati","Jetta","Carmella", "Chery","Earlene","Gene","Lorri","Albertina","Ula","Karena","Johanna", "Alex","Tobias","Lashawna","Domitila","Chantel","Deneen","Nigel", "Lashanda","Donn","Theda","Many","Jeramy","Jodee","Tamra","Dessie", "Lawrence","Jaime","Basil","Roger","Cythia","Homer","Lilliam","Victoria", "Tod","Harley","Meghann","Jacquelyne","Arie","Rosemarie","Lyndon","Blanch", "Kenneth","Perkins","Kaleena"}; int nameLen = sizeof(names)/sizeof(names[0]); // Hash table class declarations HashTable<string> strHash(TABLE_SIZE); HashTable<int> intHash = TABLE_SIZE; HashTable<MyStruct> strctHash = TABLE_SIZE; // access struct element MyStruct strctAccess; // insert 20 items into each hash table for(int x=0; x < (TABLE_SIZE*2); ++x) { // Use the "insert" function to place data into the hash table // this function automatically hashes the basic datatypes // i.e: int, double, char, char*, string strHash.Insert(names[rand()%(nameLen-1)]); intHash.Insert(rand()%10000); // The "insert" function cant be used on a struct, so we // use the "append" function for the struct declaration. // We use the "strHash" class declaration to use its // hash function, then place the struct in an appropriate // hashed bucket strctAccess.name = names[rand()%(nameLen-1)]; int strctHashKey = strHash.Hash(strctAccess.name); strctHash.Append(strctHashKey,strctAccess); } // display all the items within the "strHash" table for(int x=0; x < strHash.TableSize(); ++x) { if(!strHash.IsEmpty(x)) { cout<<"nstrHash Bucket #"<<x<<":n"; for(strIterDec it = strHash.begin(x); it != strHash.end(x); it+=1) { // access elements using the * (star) operator cout << "*it = " << *it << endl; } } } // creates a line seperator cout<<endl; cout.fill('-'); cout<<left<<setw(80)<<""<<endl; // display all the items within the "intHash" table for(int x=0; x < intHash.TableSize(); ++x) { intIterDec it = intHash.begin(x); if(!intHash.IsEmpty(x)) { cout<<"nintHash Bucket #"<<x<<":n"; for(int y = 0; y < intHash.BucketSize(x); ++y) { // access elements using the [] operator cout << "it[] = " << it[y] << endl; } } } // creates a line seperator cout<<endl; cout.fill('-'); cout<<left<<setw(80)<<""<<endl; // display all the items within the "strctHash" table for(int x=0; x < strctHash.TableSize(); ++x) { if(!strctHash.IsEmpty(x)) { cout<<"nstrctHash Bucket #"<<x<<":n"; for(strctIterDec it = strctHash.begin(x); it!=strctHash.end(x); it=it+1) { // access struct/class elements using the -> operator cout << "it-> = " << it->name << endl; } } } return 0; }// http://programmingnotes.org/ |
SAMPLE OUTPUT:
strHash Bucket #0:
*it = Cinderella
*it = Perkins
*it = Krystal
*it = Roger
*it = RogerstrHash Bucket #1:
*it = Lilliam
*it = Lilliam
*it = ThedastrHash Bucket #2:
*it = AriestrHash Bucket #3:
*it = MagdastrHash Bucket #6:
*it = Edda
*it = Irvin
*it = Kati
*it = LyndonstrHash Bucket #7:
*it = Deb
*it = JaimestrHash Bucket #8:
*it = Neville
*it = VictoriastrHash Bucket #9:
*it = Chery
*it = Evelia--------------------------------------------
intHash Bucket #0:
it[] = 2449
it[] = 6135intHash Bucket #1:
it[] = 1120
it[] = 852intHash Bucket #2:
it[] = 5727intHash Bucket #3:
it[] = 1174intHash Bucket #4:
it[] = 2775
it[] = 3525
it[] = 8375intHash Bucket #5:
it[] = 4322
it[] = 8722
it[] = 5016intHash Bucket #6:
it[] = 5053
it[] = 7231
it[] = 1571intHash Bucket #7:
it[] = 1666
it[] = 4510
it[] = 1548
it[] = 3646intHash Bucket #9:
it[] = 2756--------------------------------------------
strctHash Bucket #0:
it-> = Cherilyn
it-> = RogerstrctHash Bucket #1:
it-> = Tamra
it-> = Alex
it-> = ThedastrctHash Bucket #2:
it-> = Nigel
it-> = Alva
it-> = AriestrctHash Bucket #4:
it-> = BasilstrctHash Bucket #5:
it-> = TodstrctHash Bucket #6:
it-> = Irvin
it-> = LyndonstrctHash Bucket #7:
it-> = Amina
it-> = Hillary
it-> = Kenneth
it-> = AminastrctHash Bucket #8:
it-> = Gene
it-> = Lemuel
it-> = GenestrctHash Bucket #9:
it-> = Albertina
Java || Snippet – How To Read & Write Data From A File
This page will consist of a demonstration of a simple quadratic formula program, which highlights the use of the input/output mechanisms of manipulating a text file. This program will read in data from a file (numbers), manipulate that data, and output new data into a different text file.
REQUIRED KNOWLEDGE FOR THIS SNIPPET
Try/Catch - What Is It?
The "Math" Class - sqrt and pow
The "Scanner" Class - Used for the input file
The "FileWriter" Class - Used for the output file
The "File" Class - Used to locate the input/output files
Working With Files
NOTE: The data file that is used in this example can be downloaded here.
In order to read in the data .txt file, you need to save the .txt file in the same directory (or folder) as your .java file is saved in. If you are using Eclipse, the default directory will probably be:
Documents > Workspace > [Your project name]
Alternatively, you can execute this command, which will give you the current directory in which your source file resides:
System.out.println(System.getProperty("user.dir"));
Whatever the case, in order to read in the data .txt file, your program must know where it is located on the system.
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 |
import java.io.File; // used to locate the input/output files import java.io.FileWriter; // used for file output import java.util.Scanner; // used for file input public class ReadWriteFile { public static void main(String[] args) { // declare & initialize variables Scanner infile; FileWriter outfile; double a=0,b=0,c=0; double root1=0, root2=0; System.out.println("Welcome to My Programming Notes' Java Program.n"); // use a try/catch to check to see if the input file exists, & if not then EXIT try { // this opens the input file // YOUR INPUT FILE NAME GOES BELOW infile = new Scanner(new File("INPUT_Quadratic_programmingnotes_freeweq_com.txt")); // this opens the output file // if the file doesnt already exist, it will be created outfile = new FileWriter(new File("OUTPUT_Quadratic_programmingnotes_freeweq_com.txt")); // if the file was found, this try/catch will execute, and the loop will // attempt to get the 3 numbers from the input file and place // them inside the variables 'a,b,c' try { while(infile.hasNext()) { // this assigns the incoming data to the // variables 'a', 'b' and 'c' // NOTE: it is just like a normal scanner statement a = infile.nextInt(); b = infile.nextInt(); c = infile.nextInt(); // NOTE: if you want to read in data into an array // your declaration would be like this // ------------------------------------ // a[counter] = infile.nextInt(); // b[counter] = infile.nextInt(); // c[counter] = infile.nextInt(); // ++counter; } } catch(Exception e) { // if there was an error on input, (i.e the input file contains letters) // this block will execite, and the program will exit System.err.println("There is a formatting error in the input file!n" + "The input file should contain only 3 numbersn"); System.exit(1); } // this does the quadratic formula calculations root1 = ((-b) + Math.sqrt(Math.pow(b,2) - (4*a*c)))/(2*a); root2 = ((-b) - Math.sqrt(Math.pow(b,2) - (4*a*c)))/(2*a); // this displays the numbers to screen via stdout System.out.println("For the numbers:na = "+a+"nb = "+b+"nc = "+c); System.out.println("nroot 1 = "+root1+"nroot 2 = "+root2); // this saves the data to the output file // NOTE: its almost exactly the same as the above print statement, except // the 'write' function is dependent on the "newline" (NL) method // to generate a line break String NL = System.getProperty("line.separator"); outfile.write("For the numbers:"+NL+"a = "+a+NL+"b = "+b+NL+"c = "+c); outfile.write(NL+NL+"root 1 = "+root1+NL+"root 2 = "+root2); // close the input/output files once you are done using them infile.close(); outfile.close(); } catch(Exception e) { // if the file cannot be found, this block will execute, and the // program will exit System.err.println("Error, the input file could not be found!n" +e.getMessage()); System.exit(1); } System.out.println("nProgram Success!!n"); }// end of main }// http://programmingnotes.org/ |
QUICK NOTES:
The highlighted lines are sections of interest to look out for.
The code is heavily commented, so no further insight is necessary. If you have any questions, feel free to leave a comment below.
Once compiled, you should get this as your output
(Remember to include the example input file)
Welcome to My Programming Notes' Java Program.
For the numbers:
a = 2.0
b = 4.0
c = -16.0root 1 = 2.0
root 2 = -4.0Program Success!!
C++ || Snippet – Simple Linked List Using Delete, Insert, & Display Functions
The following is sample code for a simple linked list, which implements the following functions: “Delete, Insert, and Display.”
The sample code provided on this page is a stripped down version of a more robust linked list class which was previously discussed on this site. Sample code for that can be found here.
It is recommended you check that out as the functions implemented within that class are very useful.
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 |
// ============================================================================ // Author: Kenneth Perkins // Date: Aug 18, 2012 // Taken From: http://programmingnotes.org/ // File: SimpleList.cpp // Description: Demonstrates the use of a simple linked list. // ============================================================================ #include <iostream> #include <string> using namespace std; struct node { /* -- you can use different data types here -- instead of just a string char letter; int number; double fNumber; */ string name; node* next; }; // global variables // this is the front of the list node* head = NULL; // function prototype void Insert(string info); void Delete(string info); void Display(); void DestroyList(); int main() { // if you want to insert data into the list // this is one way you can do it, using a 'temp' pointer node* temp = new node; temp->name = "My Programming Notes"; temp->next = NULL; // set the head node to the data thats in the 'temp' pointer head = temp; // display data to the screen cout << head->name <<endl<<endl; // use the insert function to add new data to the list // NOTE: you could have also used the 'insert' function ^ above // to place data into the list Insert("Is An Awesome Site!"); // insert more data into the list Insert("August"); Display(); // delete the selected text from the list Delete("August"); Display(); // destroy the current pointers in the list // after you are finished using them DestroyList(); return 0; }// end of main void Insert(string info) { node* newItem = new node; newItem->name = info; newItem->next = NULL; // if the list is empty, add new item to the front if(head == NULL) { head = newItem; } else // if the list isnt empty, add new item to the end { node* iter = head; while(iter->next != NULL) { iter = iter->next; } iter->next = newItem; } }// end of Insert void Delete(string info) { node* iter = head; // if the list is empty, do nothing if(head == NULL) { return; } // delete the first item in the list else if(head->name == info) { head = head->next; delete iter; } // search the list until we find the desired item else { while(iter->next != NULL) { if(iter->next->name == info) { node* deleteNode = iter->next; iter->next = iter->next->next; delete deleteNode; break; } iter = iter->next; } } }// end of Delete void Display() { node* iter = head; // traverse thru the list, displaying the // text at each node location while(iter != NULL) { cout<<iter->name<<endl; iter = iter->next; } cout<<endl; }// end of Display void DestroyList() { if(head != NULL) { cout << "\n\nDestroying nodes...\n"; while(head != NULL) { node* temp = head; cout << temp->name <<endl; head = head->next; delete temp; } } }// http://programmingnotes.org/ |
QUICK NOTES:
The highlighted lines are sections of interest to look out for.
The code is heavily commented, so no further insight is necessary. If you have any questions, feel free to leave a comment below.
Once compiled, you should get this as your output
My Programming Notes
My Programming Notes
Is An Awesome Site!
August[DELETE THE TEXT "AUGUST"]
My Programming Notes
Is An Awesome Site!Destroying nodes...
My Programming Notes
Is An Awesome Site!
C++ || Snippet – Palindrome Checker Using A Stack & Queue
This page consists of a sample program which demonstrates how to use a stack and a queue to test for a palindrome. This program is great practice for understanding how the two data structures work.
REQUIRED KNOWLEDGE FOR THIS PROGRAM
Structs
Classes
Template Classes - What Are They?
Stacks
Queues
LIFO - Last In First Out
FIFO - First In First Out
#include 'SingleQueue.h'
#include 'ClassStackListType.h'
This program first asks the user to enter in text which they wish to compare for similarity. The data is then saved into the system using the “enqueue” and “push” functions available within the queue and stack classes. After the data is obtained, a while loop is used to iterate through both classes, checking to see if the characters at each location within both classes are the same. If the text within both classes are the same, it is a palindrome.
NOTE: This program uses two custom template.h classes. To obtain the code for both class, click here and here.
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 |
// ============================================================================ // Author: Kenneth Perkins // Date: Jul 22, 2012 // Taken From: http://programmingnotes.org/ // File: palindrome.cpp // Description: Demonstrates a palindrome checker using a stack & queue // ============================================================================ #include <iostream> #include <cctype> #include "SingleQueue.h" #include "ClassStackListType.h" using namespace std; int main() { // declare variable char singleChar = ' '; bool isPalindrome = true; SingleQueue<char> queue; StackListType<char> stack; // get data from user, then place them into the // queue and stack for storage. This loop also // displays the user input back to the screen via cout cout <<"Enter in some text to see if its a palindrome: "; while(cin.get(singleChar) && singleChar != '\n') { cout<<singleChar; queue.EnQueue(toupper(singleChar)); stack.Push(toupper(singleChar)); } // determine if the string is a palindrome while((!queue.IsEmpty() && !stack.IsEmpty()) && isPalindrome) { if(queue.Front() != stack.Top()) { isPalindrome = false; } else { queue.DeQueue(); stack.Pop(); } } // display results to the screen if(isPalindrome) { cout<<" is a palindrome!\n"; } else { cout<<" is NOT a palindrome..\n"; } return 0; }// http://programmingnotes.org/ |
QUICK NOTES:
The highlighted lines are sections of interest to look out for.
The code is heavily commented, so no further insight is necessary. If you have any questions, feel free to leave a comment below.
Once compiled, you should get this as your output
(Note: The code was compiled 2 separate times to demonstrate different output)
====== RUN 1 ======
Enter in some text to see if its a palindrome: StEP on No pETS
StEP on No pETS is a palindrome!
====== RUN 2 ======
Enter in some text to see if its a palindrome: Hello World
Hello World is NOT a palindrome..
Java || Snippet – How To Convert A Decimal Number Into Binary
This page will demonstrate how to convert a decimal number (i.e a whole number) into its binary equivalent. So for example, if the decimal number of 25 was entered into the program, it would display the converted binary value of 11001.
REQUIRED KNOWLEDGE FOR THIS SNIPPET
How To Count In Binary
The "Long" Datatype - What Is It?
Methods (A.K.A "Functions") - What Are They?
While Loops
Online Binary to Decimal Converter - Verify For Correct Results
If you are looking for sample code which converts binary to decimal, check back here soon!
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 |
import java.util.Scanner; public class DecimalToBinary { // global variable declaration static Scanner cin = new Scanner(System.in); public static void main(String[] args) { // declare variables long decNum = 0; String binaryNum = ""; // use a string instead of an int to avoid // overflow, because binary numbers can grow large quick // display message to screen System.out.println("Welcome to My Programming Notes' Java Program.n"); // get decimal number from user System.out.print("Please enter an integer value: "); decNum = cin.nextLong(); if(decNum < 0) // if user inputs a neg number, make the binary num neg too { binaryNum = "-"; } // method call to convert decimal to binary binaryNum += DecToBin(decNum); // display data to user System.out.println("nThe integer value of "+ decNum + " = " + binaryNum + " in binary"); }// end of main public static String DecToBin(long decNum) { // use this string to save the binary number String binary = ""; if(decNum < 0) // if input is a neg number, make it positive { decNum *= -1; } // converts decimal to binary using division and modulus while(decNum > 0) { binary += (decNum % 2); decNum /= 2; } // return the reversed string to main return new StringBuffer(binary).reverse().toString(); } }// http://programmingnotes.org/ |
QUICK NOTES:
The highlighted lines are sections of interest to look out for.
The code is heavily commented, so no further insight is necessary. If you have any questions, feel free to leave a comment below.
Once compiled, you should get this as your output
Note: The code was compiled 3 separate times to display different output
====== RUN 1 ======
Welcome to My Programming Notes' Java Program.
Please enter an integer value: 5
The integer value of 5 = 101 in binary
====== RUN 2 ======
Welcome to My Programming Notes' Java Program.
Please enter an integer value: -25
The integer value of -25 = -11001 in binary
====== RUN 3 ======
Welcome to My Programming Notes' Java Program.
Please enter an integer value: 12345678910
The integer value of 12345678910 = 1011011111110111000001110000111110 in binary
Java || Find The Prime, Perfect & All Known Divisors Of A Number Using A For, While & Do/While Loop
This program was designed to better understand how to use different loops which are available in Java, as well as more practice using objects with classes.
This program first asks the user to enter a non negative number. After it obtains a non negative integer from the user, the program determines if the user obtained number is a prime number or not, aswell as determining if the user obtained number is a perfect number or not. After it obtains its results, the program will display to the screen if the user inputted number is prime/perfect number or not. The program will also display a list of all the possible divisors of the user obtained number via stdout.
REQUIRED KNOWLEDGE FOR THIS PROGRAM
Class Objects - How TO Use
Constructors - What Are They?
Do/While Loop
While Loop
For Loop
Modulus
Basic Math - Prime Numbers
Basic Math - Perfect Numbers
Basic Math - Divisors
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 |
import java.util.Scanner; public class PrimePerfectNums { // global variable declaration int userInput = 0; static Scanner cin = new Scanner(System.in); public PrimePerfectNums(int input) {// this is the constructor // give the global variable a value userInput = input; }// end of PrimePerfectNums public void CalcPrimePerfect() { // declare variables int divisor = 0; int sumOfDivisors = 0; System.out.print("nInput number: " + userInput); // for loop adds sum of all possible divisors for(int counter=1; counter <= userInput; ++counter) { divisor = (userInput % counter); if(divisor == 0) { // this will repeatedly add the found divisors together sumOfDivisors += counter; } } System.out.println(""); // uses the 'sumOfDivisors' variable from ^ above for loop to // check if 'userInput' is prime if(userInput == (sumOfDivisors - 1)) { System.out.print(userInput + " is a prime number."); } else { System.out.print(userInput + " is not a prime number."); } System.out.println(""); // uses the 'sumOfDivisors' variable from ^ above for loop to // check if 'userInput' is a perfect number if (userInput == (sumOfDivisors - userInput)) { System.out.print(userInput + " is a perfect number."); } else { System.out.print(userInput + " is not a perfect number."); } System.out.print("nDivisors of " + userInput + " are: "); // for loop lists all the possible divisors for the // 'userInput' variable by using the modulus operator for(int counter=1; counter <= userInput; ++counter) { divisor = (userInput % counter); if(divisor == 0 && counter !=userInput) { System.out.print(counter + ", "); } } System.out.print("and " + userInput); }// end of CalcPrimePerfect public static void main(String[] args) { // declare variables int input = 0; char response ='n'; do{ // this is the start of the do/while loop System.out.print("Enter a number: "); input = cin.nextInt(); // if the user inputs a negative number, do this code while(input < 0) { System.out.print("ntSorry, but the number entered is less " + "than the allowable limit.ntPlease try again....."); System.out.print("nnEnter an number: "); input = cin.nextInt(); } // entry point to class declaration PrimePerfectNums myClass = new PrimePerfectNums(input); // function call to obtain data using the number // which was passed from main to the constructor myClass.CalcPrimePerfect(); // asks user if they want to enter new data System.out.print("nntDo you want to input another number?(Y/N): "); response = cin.next().toLowerCase().charAt(0); System.out.println("---------------------------" + "---------------------------------"); }while(response =='y'); // ^ End of the do/while loop. As long as the user chooses // 'Y' the loop will keep going. // It stops when the user chooses the letter 'N' System.out.println("BYE!"); }// end of main }// http://programmingnotes.org/ |
QUICK NOTES:
The highlighted lines are sections of interest to look out for.
The code is heavily commented, so no further insight is necessary. If you have any questions, feel free to leave a comment below.
Once compiled, you should get this as your output:
Enter a number: 41
Input number: 41
41 is a prime number.
41 is not a perfect number.
Divisors of 41 are: 1, and 41Do you want to input another number?(Y/N): y
------------------------------------------------------------
Enter a number: 496Input number: 496
496 is not a prime number.
496 is a perfect number.
Divisors of 496 are: 1, 2, 4, 8, 16, 31, 62, 124, 248, and 496Do you want to input another number?(Y/N): y
------------------------------------------------------------
Enter a number: 1858Input number: 1858
1858 is not a prime number.
1858 is not a perfect number.
Divisors of 1858 are: 1, 2, 929, and 1858Do you want to input another number?(Y/N): y
------------------------------------------------------------
Enter a number: -9Sorry, but the number entered is less than the allowable limit.
Please try again.....Enter an number: 12
Input number: 12
12 is not a prime number.
12 is not a perfect number.
Divisors of 12 are: 1, 2, 3, 4, 6, and 12Do you want to input another number?(Y/N): n
------------------------------------------------------------
BYE!
C++ || Stack – Using A Stack, Determine If A Set Of Parentheses Is Well-Formed
Here is another homework assignment which was presented in a C++ Data Structures course. This assignment was used to introduce the stack ADT, and helped prepare our class for two later assignments which required using a stack. Those assignments can be found here:
(1) Stack Based Infix To Postfix Conversion (Single Digit)
(2) Stack Based Postfix Evaluation (Single Digit)
REQUIRED KNOWLEDGE FOR THIS PROGRAM
Stack Data Structure
Cin.getline
#include "ClassStackListType.h"
A simple exercise for testing a stack is determining whether a set of parenthesis is “well formed” or not. What exactly is meant by that? In the case of a pair of parenthesis, for an expression to be well formed, consider the following table.
1 2 3 4 5 6 |
Well-Formed Expressions | Ill-Formed Expressions ------------------------------------|-------------------------------------- ( a b c [ ] ) | ( a b c [ ) ( ) [ ] { } | ( ( { ( a b c d e ) ( ) } | [ a b c d e ) ( ) } ( a + [ b - c ] / d ) | ( a + [ b - c } / d ) |
Given an expression with characters and parenthesis, ( ), [ ], and { }, our class was asked to determine if an expression was well formed or not by using the following algorithm:
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 |
// An algorithm for a Well Formed expression Set 'balanced' to true Set 'symbol' to the first character in the current expression while(there are more characters AND 'balanced' == true) { if('symbol' is an opening symbol) { Push 'symbol' onto the stack } else if('symbol' is a closing symbol) { if the stack is empty 'balanced' = false else Set the 'openSymbol' to the item at the top of the stack Pop the stack Check to see if 'symbol' matches 'openSymbol' (i.e - if openSymbol == '(' and symbol == ')' then 'balanced' = true) } Set 'symbol' to the next character in the current expression } if('balanced' == true AND stack is empty) { Expression is well formed } else { Expression is NOT well formed }// http://programmingnotes.org/ |
======= WELL-FORMED EXPRESSIONS =======
This program uses a custom template.h class. To obtain the code for that class, click here.
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 |
// ============================================================================ // Author: Kenneth Perkins // Date: May 14, 2012 // Taken From: http://programmingnotes.org/ // File: wellFormed.cpp // Description: Demonstrates how to check if an expression is well formed // ============================================================================ #include <iostream> #include "ClassStackListType.h" using namespace std; // function prototypes bool IsOpen(char symbol); bool IsClosed(char symbol); bool IsWellFormed(char openSymbol, char closeSymbol); int main() { // declare variables char expression[120]; char openSymbol; int index=0; bool balanced = true; StackListType<char> stack; // this is the stack declaration // obtain data from the user using a char array cout <<"Enter an expression and press ENTER. "<<endl; cin.getline(expression,sizeof(expression)); cout << "\nThe expression: " << expression; // loop thru the char array until we reach the 'NULL' character // and while 'balanced' == true while (expression[index]!='\0' && balanced) { // if input is an "open bracket" push onto stack // else, process info if (IsOpen(expression[index])) { stack.Push(expression[index]); } else if (IsClosed(expression[index])) { if(stack.IsEmpty()) { balanced = false; } else { openSymbol = stack.Top(); stack.Pop(); balanced = IsWellFormed(openSymbol, expression[index]); } } ++index; } if (balanced && stack.IsEmpty()) { cout << " is well formed..." << endl; } else { cout << " is NOT well formed!!! " << endl; } }// End of Main bool IsOpen(char symbol) { if ((symbol == '(') || (symbol == '{') || (symbol == '[')) { return true; } else { return false; } }// End of IsOpen bool IsClosed(char symbol) { if ((symbol == ')') || (symbol == '}') || (symbol == ']')) { return true; } else { return false; } }// End of IsClosed bool IsWellFormed(char openSymbol, char closeSymbol) { return (((openSymbol == '(') && closeSymbol == ')') || ((openSymbol == '{') && closeSymbol == '}') || ((openSymbol == '[') && closeSymbol == ']')); }// http://programmingnotes.org/ |
QUICK NOTES:
The highlighted lines are sections of interest to look out for.
The code is heavily commented, so no further insight is necessary. If you have any questions, feel free to leave a comment below.
Once compiled, you should get this as your output
(Note: the code was compile four separate times to display different output)
====== RUN 1 ======
Enter an expression and press ENTER.
((
The expression: (( is NOT well formed!!!====== RUN 2 ======
Enter an expression and press ENTER.
(a{b[]}c)The expression: (a{b[]}c) is well formed...
====== RUN 3 ======
Enter an expression and press ENTER.
[(7 * 28) - 1987]The expression: [(7 * 28) - 1987] is well formed...
====== RUN 4 ======
Enter an expression and press ENTER.
{3 + [2 / 3] - (9 + 18) * 12)The expression: {3 + [2 / 3] - (9 + 18) * 12) is NOT well formed!!!
C++ || FizzBuzz – Tackling The Fizz Buzz Test In C++
What is Fizz Buzz?
Simply put, a “Fizz-Buzz test” is a programming interview question designed to help filter out potential job prospects – those who can’t seem to program if their life depended on it.
An example of a typical Fizz-Buzz question is the following:
Write a program which prints the numbers from 1 to 100. But for multiples of three, print the word “Fizz” instead of the number, and for the multiples of five, print the word “Buzz”. For numbers which are multiples of both three and five, print the word “FizzBuzz”.
This seems easy enough, and many should be able to complete a program which carries out a solution in a few minutes. Though, after doing a little research, apparently that is not the case. This page will present one way to carry out a solution to this Fizz-Buzz problem.
There is a small “catch” that some may encounter when trying to solve this problem, and that is the fact that the conditional statement for the number divisible by 15 should come before each sequential conditional statement. Consider this pseudocode:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// A simple Fizz-Buzz algorithm using a while loop 'currentNumber' = 1 while('currentNumber' is less than or equal to 100) { if('currentNumber' is divisible by 3) AND ('currentNumber' is divisible by 5) print "FizzBuzz" else if('currentNumber' is divisible by 3) print "Fizz" else if('currentNumber' is divisible by 5) print "Buzz" else // 'currentNumber' is not divisible by 3 or 5 print 'currentNumber' increment 'currentNumber' by one }// http://programmingnotes.org/ |
The portion that may make this problem tricky for some is the fact that the conditional statement for the number divisible by 15 must be checked -before- the conditional statements which checks for numbers divisible by 3 and 5. If the conditional statements are placed in any other order, the end result will not be correct, which is what can make the problem difficult for many.
======= THE FIZZ BUZZ TEST =======
So building upon the pseudocode found from above, utilizing the modulus operator, here is a simple solution to the Fizz Buzz Test
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 |
// ============================================================================ // Author: Kenneth Perkins // Date: May 10, 2012 // Taken From: http://programmingnotes.org/ // File: fizzbuzz.cpp // Description: Demonstrates the fizz buzz test // ============================================================================ #include <iostream> using namespace std; int main() { // declare variables int fizz = 3; int buzz = 5; int endNumber = 100; int fizzBuzz = fizz * buzz; // ^ numbers divisible by 3 and 5 are also divisible by 3 * 5 // start the loop, continue until the counter // reaches the 'end' for (int currentNumber = 1; currentNumber <= endNumber; ++currentNumber) { if (currentNumber % fizzBuzz == 0) // divisible by 3 and 5 { cout<<"FIZZ BUZZ!!\n"; } else if (currentNumber % fizz == 0) // divisible by 3 { cout<<"FIZZ\n"; } else if (currentNumber % buzz == 0)// divisible by 5 { cout<<"BUZZ\n"; } else // not divisible by 3 or 5 { cout<<currentNumber<<endl; } } return 0; }// http://programmingnotes.org/ |
QUICK NOTES:
The highlighted lines are sections of interest to look out for.
The code is heavily commented, so no further insight is necessary. If you have any questions, feel free to leave a comment below.
Once compiled, you should get this as your output
1
2
FIZZ
4
BUZZ
FIZZ
7
8
FIZZ
BUZZ
11
FIZZ
13
14
FIZZ BUZZ!!
16
17
FIZZ
19
BUZZ
FIZZ
22
23
FIZZ
BUZZ
26
FIZZ
28
29
FIZZ BUZZ!!
31
32
FIZZ
34
BUZZ
FIZZ
37
38
FIZZ
BUZZ
41
FIZZ
43
44
FIZZ BUZZ!!
46
47
FIZZ
49
BUZZ
FIZZ
52
53
FIZZ
BUZZ
56
FIZZ
58
59
FIZZ BUZZ!!
61
62
FIZZ
64
BUZZ
FIZZ
67
68
FIZZ
BUZZ
71
FIZZ
73
74
FIZZ BUZZ!!
76
77
FIZZ
79
BUZZ
FIZZ
82
83
FIZZ
BUZZ
86
FIZZ
88
89
FIZZ BUZZ!!
91
92
FIZZ
94
BUZZ
FIZZ
97
98
FIZZ
BUZZ
C++ || Snippet – How To Read & Write Data From A User Specified Text File
This page will consist of a demonstration of a simple quadratic formula program, which highlights the use of the input/output mechanisms of manipulating a text file. This program is very similar to an earlier snippet which was presented on this site, but in this example, the user has the option of choosing which file they want to manipulate. This program also demonstrates how to read in data from a file (numbers), manipulate that data, and output new data into a different text file.
REQUIRED KNOWLEDGE FOR THIS SNIPPET
Fstream
Ifstream
Ofstream
Working With Files
C_str() - Convert A String To Char Array Equivalent
Getline - String Version
Note: The data file that is used in this example can be downloaded here.
Also, in order to read in the data .txt file, you need to save the .txt file in the same directory (or folder) as your .cpp file is saved in. If you are using Visual C++, this directory will be located in
Documents > Visual Studio 2010 > Projects > [Your project name] > [Your project name]
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 |
#include <iostream> #include <fstream> #include <string> #include <cmath> #include <cstdlib> using namespace std; int main() { // declare variables // char fileName[80]; string fileName; ifstream infile; ofstream outfile; double a=0,b=0,c=0; double root1=0, root2=0; // get the name of the file from the user cout << "Please enter the name of the file: "; getline(cin, fileName); // ^ you could also use a character array instead // of a string. Your getline declaration would look // like this: // --------------------------------------------- // cin.getline(fileName,80); // this opens the input file // NOTE: you need to convert the string to a // char array using the function "c_str()" infile.open(fileName.c_str()); // ^ if you used a char array as the file name instead // of a string, the declaration to open the file // would look like this: // --------------------------------------------- // infile.open(fileName); // check to see if the file even exists, & if not then EXIT if(infile.fail()) { cout<<"nError, the input file could not be found!n"; exit(1); } // this opens the output file // if the file doesnt already exist, it will be created outfile.open("OUTPUT_Quadratic_programmingnotes_freeweq_com.txt"); // this loop reads in data until there is no more // data contained in the file while(infile.peek() != EOF) { // this assigns the incoming data to the // variables 'a', 'b' and 'c' // NOTE: it is just like a cin >> statement infile>> a >> b>> c; // NOTE: if you want to read data into an array // your declaration would be like this // ------------------------------------ // infile>> a[counter] >> b[counter] >> c[counter]; // ++counter; } // this does the quadratic formula calculations root1 = ((-b) + sqrt(pow(b,2) - (4*a*c)))/(2*a); root2 = ((-b) - sqrt(pow(b,2) - (4*a*c)))/(2*a); // this displays the numbers to screen via cout cout <<"For the numbersna = "<<a<<"nb = "<<b<<"nc = "<<c<<endl; cout <<"nroot 1 = "<<root1<<"nroot 2 = "<<root2<<endl; // this saves the data to the output file // NOTE: its almost exactly the same as the cout statement outfile <<"For the numbersna = "<<a<<"nb = "<<b<<"nc = "<<c<<endl; outfile <<"nroot 1 = "<<root1<<"nroot 2 = "<<root2<<endl; // close the input/output files once you are done using them infile.close(); outfile.close(); // stops the program from automatically closing cout<<"nPress ENTER to continue..."; cin.get(); return 0; }// http://programmingnotes.org/ |
QUICK NOTES:
The highlighted lines are sections of interest to look out for.
The code is heavily commented, so no further insight is necessary. If you have any questions, feel free to leave a comment below.
Once compiled, you should get this as your output
Please enter the name of the file: INPUT_Quadratic_programmingnotes_freeweq_com.txt
For the numbers
a = 2
b = 4
c = -16root 1 = 2
root 2 = -4Press ENTER to continue...
C++ || Class & Input/Output – Display The Contents Of A User Specified Text File To The Screen
The following is another intermediate homework assignment which was presented in a C++ programming course. This program was assigned to introduce more practice using the class data structure, which is very similar to the struct data structure.
REQUIRED KNOWLEDGE FOR THIS PROGRAM
Header Files - How To Use Them
Class - What Is It?
How To Read Data From A File
String - Getline
Array - Cin.Getline
Strcpy - Copy Contents Of An Array
#Define
This program first prompts the user to input a file name. After it obtains a file name from the user, it then attempts to display the contents of the user specified file to the output screen. If the file could not be found, an error message appears. If the file is found, the program continues as normal. After the file contents finishes being displayed, a summary indicating the total number of lines which has been read is also shown to the screen.
This program was implemented into 3 different files (two .cpp files, and one header file .h). So the code for this program will be broken up into 3 sections, the main file (.cpp), the header file (.h), and the implementation of the functions within the header file (.cpp).
Note: The data file that is used in this example can be downloaded here.
Also, in order to read in the data .txt file, you need to save the .txt file in the same directory (or folder) as your .cpp file is saved in. If you are using Visual C++, this directory will be located in
Documents > Visual Studio 2010 > Projects > [Your project name] > [Your project name]
======== FILE #1 – Main.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 |
// ============================================================================ // File: Main.cpp // ============================================================================ // This program tests the "CFileDisp" object. It prompts the user for an input // filename, then attempts to display the contents of that file to stdout. // After the file contents have been displayed, a summary line indicating the // total number of lines that have been displayed is written to stdout. // ============================================================================ #include <iostream> #include <fstream> #include "CFileDisp.h" using namespace std; // ==== main ================================================================== // // ============================================================================ int main() { CFileDisp myFile; char fname[MAX_LENGTH]; int numLines; // get the filename from the user cout << "Enter a filename: "; cin.getline(fname, MAX_LENGTH); // copy the user's filename into the file object myFile.SetFilename(fname); // have the object open the file myFile.OpenFile(); // if all is good and well... if(myFile.IsValid()==true) { numLines = myFile.DisplayFileContents(); // close the file myFile.CloseFile(); // write how many lines were displayed to stdout cout << "nt*** Total lines displayed: " << numLines << endl; } return 0; }// http://programmingnotes.org/ |
======== FILE #2 – CFileDisp.h ========
Remember, you need to name the header file the same as the #include from the Main.cpp file. This file contains the function declarations, but no implementation of those functions takes place here.
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 |
// ============================================================================ // File: CFileDisp.h // ============================================================================ // This is the header file which declares the objects which are used to open // a text file and display its contents to stdout. // ============================================================================ #ifndef CFILE_DISP_HEADER #define CFILE_DISP_HEADER #include <fstream> using namespace std; #define MAX_LENGTH 256 class CFileDisp { public: // constructor CFileDisp(); // member functions void SetFilename(char newFilename[]); /* Purpose: Copy the user's filename into the file object */ void OpenFile(); /* Purpose: Open's the file which is specified by the user */ bool IsValid(); /* Purpose: Checks if the file exists. Post: Returns false if file cannot be found */ int DisplayFileContents(); /* Purpose: Display's the file contents to stdout Post: Returns the total number of lines contained in the file */ void CloseFile(); /* Purpose: Closes the file */ // destructor ~CFileDisp(); private: bool m_bIsValid; char m_filename[MAX_LENGTH]; ifstream m_inFile; }; #endif // CFILE_DISP_HEADER // http://programmingnotes.org/ |
======== FILE #3 – CFileDisp.cpp ========
This is the function implementation file for the CFileDisp.h class. This file can be named anything you wish as long as you #include “CFileDisp.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 |
// ============================================================================ // File: CFileDisp.cpp // ============================================================================ // This file implements the functions which are declared in the CFileDisp // class, which is located in CFileDisp.h // ============================================================================ #include <iostream> #include <cstring> #include <string> #include "CFileDisp.h" using namespace std; CFileDisp::CFileDisp() { m_bIsValid = 0; }// end of CFileDisp void CFileDisp::SetFilename(char newFilename[]) { strcpy(m_filename,newFilename); }// end of SetFilename void CFileDisp::OpenFile() { m_inFile.open(m_filename); }// end of OpenFile bool CFileDisp::IsValid() { if (m_inFile.fail()) { cout << m_filename << " was not found...nn"; return false; } else { return true; } }// end of IsValid int CFileDisp::DisplayFileContents() { int total=0; string inLine; cout << endl; while(getline(m_inFile, inLine)) { cout << inLine << endl; ++total; } return total; }// end of DisplayFileContents void CFileDisp::CloseFile() { m_inFile.close(); }// end of CloseFile // this is the destructor CFileDisp::~CFileDisp() { m_bIsValid = 0; }// http://programmingnotes.org/ |
QUICK NOTES:
The highlighted lines are sections of interest to look out for.
The code is heavily commented, so no further insight is necessary. If you have any questions, feel free to leave a comment below.
Once compiled, you should get this as your output
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Enter a filename: input_file_display_programmingnotes_freeweq_com.txt 346 130 982 90 656 117 595 415 948 126 4 558 571 87 42 360 412 721 463 47 119 441 190 985 214 509 2 571 77 81 681 651 995 93 74 310 9 995 561 92 14 288 466 664 892 8 766 34 639 151 64 98 813 67 834 369 This is a line of text! *** Total lines displayed: 10 |