67 Replies - 22832 Views - Last Post: 13 October 2010 - 08:11 AM
#46
Re: Week #14 Challenge: C++
Posted 07 April 2010 - 01:26 PM
As for my previous post, I just checked and it doesn't work on images/ compressed files (it is trying to use signed chars, which allows for negative characters (and breaks it) andwhen I fixed that (using unsigned chars) it stops reading the input file at the first null character (I am looking for a fix).
#47
Re: Week #14 Challenge: C++
Posted 08 April 2010 - 03:50 PM
BetaWar, on 07 April 2010 - 02:26 PM, said:
Did you read my post? I just illustrated that using std::string works even without the include in G++.
Edit: Oh wait sorry. Reply was to pre-edit post, which didn't work because of a mistake I made. I fixed it and it now shows that std::string works without the include.
This post has been edited by programble: 08 April 2010 - 03:51 PM
#48
Re: Week #14 Challenge: C++
Posted 08 April 2010 - 08:24 PM
#49
Re: Week #14 Challenge: C++
Posted 09 April 2010 - 08:52 PM
#include <iostream>
#include <string>
using namespace std;
string xorEncrypt(string str, string key, int sPos, int kPos)
{
// recursively loop through each char in the string
if (sPos < str.length())
{
// repeat through the key if needed
if (kPos >= key.length())
{
kPos = 0;
}
// xor sucks, but it works for simple things
str[sPos] = str[sPos] ^ key[kPos];
return xorEncrypt(str, key, ++sPos, ++kPos);
}
else
{
return str;
}
}
int main(int argc, char* argv[])
{
string str = "skaggles is more awesome than gabehabe";
string key = "boobies!";
cout << "original string: " << str << endl;
// the zeros signify the starting position for the string and key
string eStr = xorEncrypt(str, key, 0, 0);
cout << "encrypted string: " << eStr << endl;
// to decrypt, pass the encrypted string with the same key
string dStr = xorEncrypt(eStr, key, 0, 0);
cout << "decrypted string: " << dStr << endl;
system("PAUSE");
return 0;
}
This post has been edited by Skaggles: 09 April 2010 - 08:58 PM
#50
Re: Week #14 Challenge: C++
Posted 10 April 2010 - 07:52 AM
The idea is a simple drawing application that has lines, rectangles, and ellipses using pens and brushes.
Screenshot

Application(not the code)
SimpleDrawingApp.zip (19.82K)
Number of downloads: 165
#51
Re: Week #14 Challenge: C++
Posted 10 April 2010 - 08:33 AM
I settled on encrypting/decrypting/cracking Vigenere Ciphers, and have been researching the how-tos as I figure out what I want the program to do.
I used a C program by guy named Paul Johnson as a guide and figured out how his program worked, then made mine do what i wanted it to. I must admit I used his encrypt/decrypt algorithms.
Oh, and it's still a work in progress, I'm just learning about pointers, so as I have time I am cleaning it up with helper functions, it's still mostly inline and there are lots and lots of strange things in it that are in the category of "I wonder what happens if I....?"
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <cctype>
#include <cstdlib>
#include <cmath>
using namespace std;
int load_data(int *send_mode, string *send_str);
int prep_data(int *send_mode, string *send_str, string *data);
int encrypt(string *data_pass);
int decrypt(string *data_pass);
int crack(string *data_pass);
int main (){
bool quit = false;
while(quit == false) {
int *send_mode;
int get_mode;
send_mode=&get_mode;
string *send_str;
string get_str;
send_str=&get_str;
cout << "\n\n"
"(e)ncrypt \n"
"(d)ecrypt \n"
"(c)rack\n"
"(q) Quit\n"
"\nSelect a Menu Option :> ";
char selection;
cin >> selection;
switch(selection){
case 'e': get_mode=1; get_str= "encrypt"; load_data(send_mode, send_str);
break;
case 'd': get_mode=2; get_str= "decrypt"; load_data(send_mode, send_str);
break;
case 'c': get_mode=3; get_str= "crack"; load_data(send_mode, send_str);
break;
case 'q': quit = true; break;
default : cout << "\n" << "try again" << "\n";
}
}
return 0;
}
int load_data(int *send_mode, string *send_str){
int i = 0;
char filename[20];
ifstream data_in;
vector<string> words;
string word, data_conc, *data;
data=&data_conc;
cout << "Filename of the text file you wish to " << *send_str << ":> " ;
cin.ignore();
cin.getline (filename,20); // get the filename from the user
data_in.open (filename); //open the file
if(!data_in.is_open()){ // check to make sure it's open
cout << "\n" << "Error opening file." << "\n" << endl;
return(0); // if not open, exit
}
else{
cout << "\n" << "File read success." << "\n" << endl;
}
while(data_in >> word) // until we reach the end
words.push_back(word); // push the file into memory word by word
for(i = 0; i < words.size(); i++){ // until we reach the end
data_conc += words[i]; // clear out the whitespace
}
prep_data(send_mode, send_str, data);
return 0;
}
int prep_data(int *send_mode, string *send_str, string *data){
int error=0;
int mode=*send_mode;
string data_alpha;
string temp_str=*data;
string *data_pass;
data_pass=&data_alpha;
int i = 0;
for (i = 0; temp_str[i]; i++){ // until we reach the end
if(isalpha(temp_str[i])){ // check to see if char is alpha
temp_str[i] = toupper(temp_str[i]); // if it is convert to upper
data_alpha += temp_str[i]; // and put it in a new string
}
else{error=1;}
}
if(*send_mode!=1 && (error==1)){cout << "\nFile contains non-alpha "
"characters, cannot " << *send_str << ".";
return 1;}
if(mode==1){encrypt(data_pass);}
else if(mode==2){decrypt(data_pass);}
else if(mode==3){crack(data_pass);}
else{cout << "An error may have occured, returning to menu." << endl;}
return 0;
}
int encrypt(string *data_pass){
int i,j=0;
string plaintext=*data_pass;
string ciphertext="";
string key;
int key_len;
cout << "Enter a key for encryption:> ";
cin >> key;
key_len=key.size();
for(i=0;i<key_len;i++){key[i] = toupper(key[i]);}
for (i=0,j=0;i<plaintext.size();i++,j++){
ciphertext+=tolower('A' + (((plaintext[i]) - 'A') + ((key[j]) - 'A'))%26);
if(j==key_len-1){j=-1;}
}
cout << "\nHere are samples of the file before and after processing.\n"
"Ciphertext shown in lower case for clarity." << endl;
cout << "\nPlaintext :> ";
for(i=0;i<65;i++){cout << plaintext[i];}
cout << "\nCiphertext:> ";
for(i=0;i<65;i++){cout << ciphertext[i];}
return 0;
}
int decrypt(string *data_pass){
int i,j=0;
string ciphertext=*data_pass;
string plaintext="";
string key;
int key_len;
cout << "Enter a key for decryption:> ";
cin >> key;
key_len=key.size();
for(i=0;i<key_len;i++){key[i] = toupper(key[i]);}
for (i=0,j=0;i<ciphertext.size();i++,j++){
plaintext+=tolower('A' + (26 + ((ciphertext[i]) - 'A') - ((key[j]) - 'A'))%26);
if(j==key_len-1){j=-1;}
}
cout << "\nHere are samples of the file before and after processing.\n"
"Plaintext shown in lower case for clarity." << endl;
cout << "\nCiphertext:> ";
for(i=0;i<65;i++){cout << ciphertext[i];}
cout << "\nPlaintext :> ";
for(i=0;i<65;i++){cout << plaintext[i];}
return 0;
}
//some serious cleanup needed here
int crack(string *data_pass){
string ciphertext=*data_pass;
int k=1;
int num_shifts=100;// determines max key length to check
float index=0;
int key_len=0;
string crack_key;
for(k = 1; k < num_shifts; k++){
int l = 0;
int shift=k;
float matches=0;
for(l = 0; ciphertext[l + shift]; l++){
if(ciphertext[l] == ciphertext[l + shift]){matches++;}
}
index=(100 * matches / l);
if (index >= 5.5) {break;}/*set this up to be a sensitivity that the
user can adjust, minimum value of 5, max
value of 7, default of 6. */
}
key_len=k;
/*---Make this a helper function (break down the message into (k) temp
strings and generate frequency analysis for each string)---*/
int key_pos=0;
int m,n= 0;
string temp_str;
int temp_str_len;
if(ciphertext.size()/key_len < 256){//grab a short string to speed things up
temp_str_len=ciphertext.size()/key_len;
}
else {temp_str_len=256;}
char ch = 'A';
char ch_cmp;
float ch_num = 0;
int lowest_dev=0;
for (n=0; n<key_len;n++){ //here we step through the key
int offset=0;
float freq[26];
temp_str="";
offset=0;
temp_str += ciphertext[n];
for(m=0;m<temp_str_len;m++){
offset += (key_len); //define an offset
temp_str += ciphertext[offset+n]; //and give the letters to a string
int x,y=0;
for(x =0; x < 26; x++){
ch_cmp=(ch+x); //which character are we checking?
ch_num=0;
for(y = 0; y < temp_str.size(); y++){
if (temp_str[y] == ch_cmp){ch_num++;} //count the characters
}
freq[x] = (ch_num/(temp_str.size()))*100; //build frequency table
}
}
/*---Make this a helper function (crack the key using std deviation from
known distributions, SUM of SQUARES sort of thing)--------------------*/
// This frequency table comes from the Math Explorers Club at Cornell
float dist[] ={8.12, 1.49, 2.71, 4.32, 12.02, 2.30, 2.03,
5.92, 7.31, 0.10, 0.69, 3.98, 2.61, 6.95,
7.68, 1.82, 0.11, 6.02, 6.28, 9.10, 2.88,
1.11, 2.09, 0.17, 2.11, 0.07};
float cand[26];
float dev;
int s,t=0;
for(s=0;s<26;s++){
cand[s]=0;
for(t=0;t<26;t++){
dev=pow((dist[(26 + t - s) % 26]-freq[t]),2); //get sq of deviation
cand[s]+=dev; //and sum the values
}
}
for (t=0;t<26;t++){ //step through the squares
if (cand[t] < cand[lowest_dev]){lowest_dev=t;} //find the lowest of sums
}
cout << ".";
char candidate = ('A'+lowest_dev); //get corresponding letter
crack_key+=candidate; //assemble the key
}
cout << "\n\nAnalysis suggests the key is:> "
<< crack_key << endl;
cout << "\nHere are samples of the file before and after processing.\n"
"Plaintext shown in lower case for clarity." << endl;
/*---Make this a helper function (decrypt the data now that we know the key).
Many thanks to Paul Johnston for the decrypt algorithm.---------------------*/
string plaintext="";
int ss,rr=0;
for (ss=0,rr=0;ss<ciphertext.size();ss++,rr++){
plaintext+=tolower
('A' + (26 + ((ciphertext[ss]) - 'A') - ((crack_key[rr]) - 'A'))%26);
if(rr==key_len-1){rr=-1;}
}
// Display samples of the ciphertext and plaintext.
cout << "\nCiphertext:> ";
int zz=0;
for(zz=0;zz<65;zz++){
cout << (ciphertext[zz]);
}
cout << "\nPlaintext :> ";
for(zz=0;zz<65;zz++){
cout << plaintext[zz];
}
}
#52
Re: Week #14 Challenge: C++
Posted 10 April 2010 - 02:17 PM
#53
Re: Week #14 Challenge: C++
Posted 10 April 2010 - 05:13 PM
I usually implement Warnsdorff's algorithm as it is by far the fastest. The idea behind his algorithm is that there is no need for backtracking, although I do use recursion (might actually be faster iteratively). For each possible move location, move to the one with the least number of following moves. That will always work, no matter where you start.
I used to do a lot of C++, but this is the first time in nearly a year. Let me know if there are better ways to do this algorithm.
Oh yah, and this takes less than a second to solve...
#include <iostream>
#include <vector>
// For setw() method
#include <iomanip>
using namespace std;
class Point {
public:
int row, col;
Point() {}
Point(int x, int y) { row = x; col = y; }
};
int board[8][8];
// Is the point actually on the board?
bool isOnBoard(Point p) {
if (p.row < 8 && p.row >=0 && p.col < 8 && p.col >= 0)
return true;
else
return false;
}
// Gets all the possible moves (empty locations accessible by knight.
// This is really bad coding, but it works...
vector<Point> getPossibleMoves(Point p) {
vector<Point> moves;
int row = p.row - 2;
int col = p.col;
// Try y-2
if (isOnBoard(Point(row, p.col))) {
col = p.col - 1;
if (isOnBoard(Point(row, col)) && board[row][col] == 0) {
moves.push_back(Point(row, col));
}
col = p.col + 1;
if (isOnBoard(Point(row, col)) && board[row][col] == 0) {
moves.push_back(Point(row, col));
}
}
// Try y -1
row = p.row - 1;
if (isOnBoard(Point(row, p.col))) {
col = p.col - 2;
if (isOnBoard(Point(row, col)) && board[row][col] == 0) {
moves.push_back(Point(row, col));
}
col = p.col + 2;
if (isOnBoard(Point(row, col)) && board[row][col] == 0) {
moves.push_back(Point(row, col));
}
}
// Try y+1
row = p.row + 1;
if (isOnBoard(Point(row, p.col))) {
col = p.col - 2;
if (isOnBoard(Point(row, col)) && board[row][col] == 0) {
moves.push_back(Point(row, col));
}
col = p.col + 2;
if (isOnBoard(Point(row, col)) && board[row][col] == 0) {
moves.push_back(Point(row, col));
}
}
// Try y+2
row = p.row + 2;
if (isOnBoard(Point(row, p.col))) {
col = p.col - 1;
if (isOnBoard(Point(row, col)) && board[row][col] == 0) {
moves.push_back(Point(row, col));
}
col = p.col + 1;
if (isOnBoard(Point(row, col)) && board[row][col] == 0) {
moves.push_back(Point(row, col));
}
}
return moves;
}
int getNumMoves(Point p) {
return getPossibleMoves(p).size();
}
void tour(Point starter, int currentNumber) {
// End of recursion
if (currentNumber == 65)
return;
// If not done
else {
// Get all the potential moves
vector<Point> moves = getPossibleMoves(starter);
vector<int> numOfMoves;
for (int i = 0; i < moves.size(); i++)
numOfMoves.push_back(getNumMoves(moves[i]));
// Find the move with least number of potential moves
int smallestIndex = 0;
int smallest = numOfMoves[0];
for (int i = 1; i < numOfMoves.size(); i++) {
if (numOfMoves[i] < smallest) {
smallest = numOfMoves[i];
smallestIndex = i;
}
}
Point destPoint = moves[smallestIndex];
board[destPoint.row][destPoint.col] = currentNumber;
return tour(destPoint, currentNumber+1);
}
}
int main(int argc, char* args[]) {
// This is the starting location.
Point start (3,7);
board[start.row][start.col] = 1;
// Start the tour on move #2
tour(start, 2);
// Print results.
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
cout << setw(2) << board[i][j] << " ";
}
cout << endl;
}
}
This post has been edited by Dogstopper: 10 April 2010 - 05:14 PM
#54
Re: Week #14 Challenge: C++
Posted 10 April 2010 - 06:53 PM
We see a ton of card games C++ land. That means lots of Card classes. Some good, some not so good. Every time do one, I try it a little different, so I guess it's a good choice.
#include <iostream>
struct CardSuit {
enum Type { spades, diamonds, clubs, hearts, EMPTY };
static const int Count = 4;
static const char *getName(const CardSuit::Type &type) {
static const char *names[] = { "Spades","Diamonds","Clubs","Hearts", "" };
return names[(int)type];
}
static char getShortName(const CardSuit::Type &type) { return "SDCH-"[(int)type]; }
};
struct CardFace {
enum Type { ace, two, three, four, five, six, seven, eight, nine, ten, jack, queen, king, EMPTY };
static const int Count = 13;
static const char *getName(const CardFace::Type &type) {
static const char *names[] = {
"Ace","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten","Jack","Queen","King", ""
};
return names[(int)type];
}
static char getShortName(const CardFace::Type &type) { return "A23456789TJQK-"[(int)type]; }
};
class Card {
public:
Card();
Card(CardFace::Type, CardSuit::Type);
void print(std::ostream &, bool useShort = false) const;
bool isEmpty() const;
CardSuit::Type getSuit() const;
CardFace::Type getFace() const;
bool operator==(const Card &) const;
private:
CardSuit::Type suit;
CardFace::Type face;
};
Card::Card() : face(CardFace::EMPTY), suit(CardSuit::EMPTY) { }
Card::Card(CardFace::Type f, CardSuit::Type s) : face(f), suit(s) { }
bool Card::isEmpty() const { return face==CardFace::EMPTY || suit==CardSuit::EMPTY; }
CardSuit::Type Card::getSuit() const { return suit; }
CardFace::Type Card::getFace() const { return face; }
bool Card::operator==(const Card &other) const {
return (isEmpty()||other.isEmpty()) ? false : (face==other.face && suit==other.suit);
}
void Card::print(std::ostream &out, bool useShort) const {
if (isEmpty()) {
out << "NOCARD";
} else if (useShort) {
out << CardFace::getShortName(face) << CardSuit::getShortName(suit);
} else {
out << CardFace::getName(face) << " of " << CardSuit::getName(suit);
}
}
// don't need a friend for this kind of thing
// as long as the class exposes a const method
std::ostream &operator<<(std::ostream &out, const Card &card) {
card.print(out);
return out;
}
Guess we need a Deck class... this one is stupid simple. It has no logic, just 52 cards, shuffled or not.
#include <cstdlib>
#include <ctime>
struct Deck {
static const int Size = 52;
Card cards[Size];
Deck(bool shuffleDeck = true);
void init();
void shuffle();
};
Deck::Deck(bool shuffleDeck) {
init();
if (shuffleDeck) { shuffle(); }
}
void Deck::init() {
int size = 0;
for(int i=0; i<CardSuit::Count; i++) {
CardSuit::Type suit = (CardSuit::Type)i;
for(int j=0; j<CardFace::Count; j++) {
cards[size++] = Card((CardFace::Type)j, suit);
}
}
}
void Deck::shuffle() {
for(int i=Size-1; i>0; i--) {
int pos = rand() % (i+1);
if (pos!=i) {
Card t = cards[i];
cards[i] = cards[pos];
cards[pos] = t;
}
}
}
Guess we should play a game. Surprising annoying thing to do, actually. All the cool card games have odd ball exceptions. And then there's any kind of computer player logic...
War seemed like a good choice. It's dumb, but shows a fun use for queues. Can also be played to completion with not user intervention or even decision.
#include <iostream>
#include <queue>
typedef std::queue<Card> WarPlayer;
class War {
private:
static const int PlayerCount = 2;
WarPlayer player[PlayerCount], table[PlayerCount];
void init();
bool isDone() const;
void putTable();
void playHand();
int getCardValue(const Card &) const;
int compareCards(const Card &, const Card &) const;
std::string cardsToStr(const Card &c1, const Card &c2) const;
void printCard(const Card &c1, const Card &c2) const;
void printLine(const Card &c1, const Card &c2) const;
void printLine(const Card &c1, const Card &c2, int winner, int amountWon) const;
public:
void play();
};
void War::play() {
init();
int rounds = 0;
while(!isDone()) {
rounds++;
playHand();
}
std::cout << "Rounds: " << rounds << std::endl;
int winner = (player[1].size()==0) ? 0 : 1;
std::cout << "Player " << winner << " wins." << std::endl;
}
void War::init() {
Deck deck(true);
for(int i=0; i<Deck::Size; i++) {
player[i%2].push(deck.cards[i]);
}
}
bool War::isDone() const { return player[0].size()==0 || player[1].size()==0; }
int War::getCardValue(const Card &card) const {
CardFace::Type face = card.getFace();
return (face==CardFace::ace) ? 20 : (int)face;
}
int War::compareCards(const Card &c1, const Card &c2) const {
int cmp = getCardValue(c2) - getCardValue(c1);
return cmp;
}
void War::putTable() {
for(int i=0; i<PlayerCount; i++) {
if (player[i].size()>0) {
Card c = player[i].front();
player[i].pop();
table[i].push(c);
}
}
}
void War::printLine(const Card &c1, const Card &c2) const {
std::cout << CardFace::getShortName(c1.getFace()) << '\t' << CardFace::getShortName(c2.getFace());
std::cout << "\tTie" << std::endl;
}
void War::printLine(const Card &c1, const Card &c2, int winner, int amountWon) const {
std::cout << CardFace::getShortName(c1.getFace()) << '\t' << CardFace::getShortName(c2.getFace());
std::cout << "\tP" << winner << '\t' << amountWon;
std::cout << '\t' << player[0].size() << '\t' << player[1].size() << '\t';
std::cout << std::endl;
}
void War::playHand() {
putTable();
Card c1, c2;
int cmp;
while(true) {
c1 = table[0].back();
c2 = table[1].back();
cmp = compareCards(c1, c2);
if (cmp!=0) { break; }
printLine(c1, c2);
for(int i=0; i<4; i++) { putTable(); }
}
int winner = (cmp<0) ? 0 : 1;
int looser = (winner==1) ? 0 : 1;
int amountWon = table[looser].size();
for(int i=0; i<2; i++) {
WarPlayer &t = table[(i==0) ? winner : looser];
while (!t.empty()) {
player[winner].push(t.front());
t.pop();
}
}
printLine(c1, c2, winner, amountWon);
}
int main(){
srand((unsigned)time(0));
War war;
war.play();
return 0;
}
#55
Re: Week #14 Challenge: C++
Posted 11 April 2010 - 08:25 PM
//**********************************************************************
// Program: Calculator *
// Purpose: This is a simple calculator that can add, subtract, *
// multiply, divide, do factorials, as well as put x^y power. *
// It inputs a double, a task char, and another double. *
// Example Input: "4.5*8" or "8!10" (8! * 10) (without quotes) *
// Enter "0Q0" (zero-Q-zero) to quit *
// Date Completed: Sunday, 4/11/10 *
//**********************************************************************
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
double a;
double b;
double c; // Answer
double answers[50]; // Answers that go with each entry
int entryNum = 1; // Number of current entry
int cont = 1; // 0 to quit, 1 to continue program
int i; // Loop control variable
char task; // Task char
string currEntry; // Current entry
string entries[50]; // List of entries (to output "=(answer)" after each entry)
int Interpreter(); // Returns 0 to quit (if "0Q0" is entered) or 1 to continue program
void Addition();
void Subtraction();
void Multiplication();
void Division();
void Exponents();
void Factorial();
int _tmain(int argc, _TCHAR* argv[])
{
while(1)
{
cin >> a >> task >> b;
getline(cin, currEntry);
entries[entryNum] = currEntry;
cont = Interpreter();
if(cont==0)
break;
else
entryNum++;
}
return 0;
}
int Interpreter()
{
if(currEntry=="0Q0")
return 0; // If entry is "0Q0", then return 0 to quit the program
if(task=='+')
Addition();
if(task=='-')
Subtraction();
if(task=='*')
Multiplication();
if(task=='/')
Division();
if(task=='!')
Factorial();
system("cls");
for(i=0;i<entryNum;i++)
{
cout << entries[i] << "=" << answers[i] << endl;
i++;
}
if(currEntry!="0Q0")
return 1;
}
void Addition()
{
c = a + b;
answers[entryNum] = c;
return;
}
void Subtraction()
{
c = a - b;
answers[entryNum] = c;
return;
}
void Multiplication()
{
c = a * b;
answers[entryNum] = c;
return;
}
void Division()
{
c = a / b;
answers[entryNum] = c;
return;
}
void Factorial()
{
c = 1;
for(int count = 2;count<=a;count++)
c = c * count;
c = c * b;
answers[entryNum] = c;
return;
}
It only displays "=" and some number like 0, 2, or 20. I'm not sure why it does this. It didn't even quit when I entered "0Q0"!
I entered "48/6" and it displayed only "=20". Why does it do that? I could not attach the Windows executable, unfortunately.
MacClassicNerd
#56
Re: Week #14 Challenge: C++
Posted 12 April 2010 - 12:01 PM
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;
#ifdef WIN32
#include <windows.h>
int getCursorX() //Gets text cursor's X coordinate
{
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO ccinfo;
GetConsoleScreenBufferInfo(hOut,&ccinfo);
return ccinfo.dwCursorPosition.X+1;
}
int getCursorY() //Gets text cursor's Y coordinate
{
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO ccinfo;
GetConsoleScreenBufferInfo(hOut,&ccinfo);
return ccinfo.dwCursorPosition.Y+1;
}
void moveCursor(int x,int y)
{
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
COORD coord;
coord.X=x-1,coord.Y=y-1;
SetConsoleCursorPosition(hOut,coord);
}
#endif
struct _point
{
int x,y;
};
class Maze
{
string *grid;
int m,n; //m X n rectangular grid (rows X colums)
char path;
_point start;
static unsigned int sol;
public:
Maze() : m(0),n(0),path('.'){}
bool load(char* filename)
{
ifstream fi(filename);
if(!fi)
{
cout<<"Cannot find file\nPress enter to exit...";
cin.get();
return false;
}
int count=0;
string temp;
while(getline(fi,temp)) count++;
grid=new string[count];
fi.clear();
fi.seekg(0);
while(getline(fi,temp))
{
for(int i=0;i<temp.length();i++)
{
if(temp[i]=='.')
temp[i]=' ';
else
if(temp[i]=='S')
start.x=i,start.y=m;
}
grid[m++]=temp;
if(temp.length()>n) n=temp.length();
}
}
char& get(int x,int y)
{
x=x%m,y=y%n;
return grid[y][x];
}
#ifndef WIN32
void display()
{
for(int y=0;y<m;y++)
cout<<grid[y]<<endl;
cout<<endl;
}
#else
void displayWin32(int x,int y,const int& startX,const int& startY)
{
if(get(x,y)==path)
{
moveCursor(x%m + startX,y%n + startY);
cout<<path;
get(x,y)='x';
Sleep(10);
}
if(get(x,y-1)==path)
displayWin32(x,y-1,startX,startY);
if(get(x-1,y)==path)
displayWin32(x-1,y,startX,startY);
if(get(x,y+1)==path)
displayWin32(x,y+1,startX,startY);
if(get(x+1,y)==path)
displayWin32(x+1,y,startX,startY);
if(get(x,y)=='x')
get(x,y)=path;
}
void display()
{
HANDLE hout=GetStdHandle(STD_OUTPUT_HANDLE);
const int startPosCursorX=getCursorX(),startPosCursorY=getCursorY();
bool result=false;
//Display walls
for(int y=0;y<m;y++)
{
for(int x=0;x<n;x++)
if(grid[y][x]==path)
cout<<' ',result=true;
else
if(grid[y][x]=='S')
{
SetConsoleTextAttribute(hout,FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY);
cout<<'S';
SetConsoleTextAttribute(hout,FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
}
else
if(grid[y][x]=='D')
{
SetConsoleTextAttribute(hout,FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
cout<<'D';
SetConsoleTextAttribute(hout,FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
}
else
cout<<grid[y][x];
cout<<endl;
}
cout<<endl;
if(result) //Display path
{
int cursorx=getCursorX(),cursory=getCursorY();
moveCursor(startPosCursorX,startPosCursorY);
SetConsoleTextAttribute(hout,FOREGROUND_GREEN | FOREGROUND_INTENSITY);
displayWin32(start.x,start.y,startPosCursorX,startPosCursorY);
SetConsoleTextAttribute(hout,FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
moveCursor(cursorx,cursory);
}
}
#endif
void _solve(int x,int y) //Recursive
{
if(get(x,y)==' ')
get(x,y)=path;
if(get(x,y)=='D')
{
cout<<"Solution number "<<++sol<<endl;
display();
cout<<"Press enter...";
cin.get();
return;
}
//Check all four directions
if(get(x,y-1)!='#' && get(x,y-1)!=path)
_solve(x,y-1);
if(get(x-1,y)!='#' && get(x-1,y)!=path)
_solve(x-1,y);
if(get(x,y+1)!='#' && get(x,y+1)!=path)
_solve(x,y+1);
if(get(x+1,y)!='#' && get(x+1,y)!=path)
_solve(x+1,y);
if(get(x,y)==path)
get(x,y)=' ';
}
void solve()
{
sol=0;
_solve(start.x,start.y);
}
~Maze()
{
delete grid;
}
};
unsigned int Maze::sol=0;
int main()
{
Maze maze;
if(!maze.load("maze.txt"))
return 1;
cout<<"Try to solve the maze, starting position is S and destination(s) is/are D\n\n";
maze.display();
cout<<"Press enter to continue";
cin.get();
maze.solve();
return 0;
}
I have put the maze in maze.txt (find attachment).
Attached File(s)
-
maze.txt (1.72K)
Number of downloads: 162
#57
Re: Week #14 Challenge: C++
Posted 13 April 2010 - 03:37 PM
The fastest way to search through a list is randomly, not linearly. If you search linearly, items near the end of the list will always take the longest, a random search would require the same amount of time no matter where in the list the item is. This principal can be applied to brute forcing as well. However, randomly generating passwords is too slow, and trying aaaaaa, aaaaab, aaaaac, aaaaad.. (linear search) isn't very effective. What my code does is "randomly" create passwords to try in a brute force attack. It's not actually random, but random enough to be more effective then a linear search. It is just as fast as a linear search, and better then a random search, because it actually guarantees that no password will be given twice.
The output looks like this:
bchheaww fnmyayce jysoxvhm ojyfusmu svdwrpsc xgjnomxk brpelkcs gcuvihia koamfeni ozgdcbsq tkltyyxy xvrkvwdg cgxbstio gscspqnw ldijmnte
/* passgen.h
The definitive password generator for brute force attacks. This code is in the public domain.
Created by FireXware. Mar. 21, 2010, contact: firexware@hotmail.com
Although just as efficient at brute forcing as the linear (aaaa, aaab, aaac..) approach, this class takes a different approach which is statistically much faster.
This class takes a character set, and a password length and will generate passwords in a psudorandom order, without repititions.
It's based on the math:
i = i + P mod n
Where P is a prime number greater then n. n is any positive integer.
If you loop over that equation, it will produce every value from 1 to n in a non-linear order (not 1,2,3,4,5..)
I've never seen this theory proven anywhere, but it makes sense because P will not be divisible by n
The randomness is very low quality, and should not be used for cryptographic applications.
To implement this with high quality randomization, use a key to make a lookup table:
password[i] = next[password[i]] //next[] contains the character set in a random order (from a key or /dev/random)
To find the next password, an attacker would only have to brute force the next[] table, (set length - 1)! possible combinations
Credits:
- The idea isn't new, so credits to whoever thought of it first :P/>
Usage:
unsigned char set[] = "abcdefghijklmnopqrstuvwxyz"; //define the character set
int setlen = 26; //ignore the \0
int passlen = 4; //length of password to try
PassGen p(set,setlen,passlen); //create a password generator
unsigned char* password = new unsigned char[passlen]; //create the container to hold the passwords made by p
while(p.GetNext(password)) //fill password with the next password
{
for(int j = 0; j < passlen; j++) //output the password (it is not null terminated)
cout << password[j];
cout << endl;
}
To use it with parallel processing, the job can be split into multiple peices.
Use GetThreadStates to get a an array of state strings, each representing its own section of the job
For example, this is the same as the code above, but split into two parts that can be run at the same time:
unsigned char set[] = "abcdefghijklmnopqrstuvwxyz";
int setlen = 26; //ignore the \0
int passlen = 4;
char** states = PassGen::GetThreadStates(set,setlen,passlen,2);
PassGen p(states[0]);
PassGen g(states[1]);
unsigned char* password = new unsigned char[passlen];
while(p.GetNext(password))
{
for(int j = 0; j < passlen; j++)
cout << password[j];
cout << endl;
}
while(g.GetNext(password))
{
for(int j = 0; j < passlen; j++)
cout << password[j];
cout << endl;
}
*/
#include <math.h>
#include <stdlib.h>
#include <time.h>
//For debugging:
/*#include <iostream>
using namespace std;*/
class PassGen
{
protected: //disable copying cuz we use stuff on the heap.
PassGen(PassGen& c);
PassGen operator=(PassGen& c);
public:
/*
Starts a new password generator from a character set, and a password length.
charSet is the character set to use, for example, to brute force alphanumerc passwords, pass in "abcdefghijklmnopqrstuvwxyz1234567890"
setLen is the length of your character set (ignore the \0 at the end if there is one)
passLen is the length of password you are brute forcing, for example 4 would obviously create passwords like 'abaf'
*/
PassGen(unsigned char* charSet, int setLen, int passLen);
/*
Starts a password generator from a previously saved state, also used for dividing the job into peices.
state is a null terminated state string returned by GetState or GetThreadStates
*/
PassGen(char* state);
/*
Gets the next password to try
container is a unsigned char array, the same length as the passwords you want (specified when constructing the object)
container will be filled with the next password.
returns true if there are more passwords to be generated, false if it is the last password
*/
bool GetNext(unsigned char* container);
/*
Returns the current state of the password generator, so it can be saved and restored
*/
char* GetState();
/*
Generates an array of state strings, so you can use them with the 2nd constructor for parallel processing.
charSet is the character set
setLen is the length of the character set
passLen is the length of the passwords to generate
numThreads is the number of threads (or jobs) to generate
*/
static char** GetThreadStates(unsigned char* charSet, int setLen, int passLen, int numThreads);
/*
Returns an estimate of how far complete the process is in percent format
*/
double GetProgressPercent();
/*
Returns the password length
*/
int PasswordLength()
{
return passwordLength_;
}
/*
Makes GetNext start to return true again, until it finishes once more
*/
void Reset()
{
repeating = false;
}
//deconstructor
~PassGen()
{
//deleting set_ is the user's responsibility, they only gave us a pointer to it.
delete prime_; delete pass_;
}
protected:
bool repeating;
unsigned char* prime_; //large prime number that gets added modulo setLength_^passwordLength_
unsigned char* pass_; //array indexes
unsigned char* set_; //the character set as defined by the user
int setLength_; //length of the character set
int passwordLength_; //length of the passwords to generate
unsigned char* counter_; //counter for checking % complete and if done or not
int numThreads_; //number of threads, gets added to the counter
//gets the state string for a set of data
static char* getStateFromData(int passwordLength, unsigned char* primeNumber, unsigned char* password, int setLength, unsigned char* charset, int numThreads);
//finds the next prime after or equal to min
static long nextPrime(long min);
//returns true if a number is prime.
static bool isprime(long p);
};
PassGen::PassGen(unsigned char* charSet, int setLen, int passLen) : set_(charSet), setLength_(setLen), passwordLength_(passLen)
{
repeating = false;
//to implement a linear search feature, just make prime
srand(time(NULL));
pass_ = new unsigned char[passLen];
prime_ = new unsigned char[passwordLength_];
counter_ = new unsigned char[passwordLength_];
numThreads_ = 1;
long p = passLen;
for(int i = 0; i < passwordLength_; i++)
{
p = nextPrime(p + 1 + (rand() % 314159265)); // a random prime number greater than the last (so we dont get the same number)
prime_[i] = p % setLen;
pass_[i] = rand() % setLen; //start the password off in a random position
}
//init pass to some random value
for(int i = 0; i < passwordLength_; i++)
pass_[i] = rand() % setLength_;
}
PassGen::PassGen(char* state)
{
repeating = false;
//passwordlength|prime_|password|charsetlength|charset|numThreads|NULL
passwordLength_ = (int)(*(state + 3) << 24 | *(state + 2) << 16 | *(state + 1) << 8 | *state);
prime_ = new unsigned char[passwordLength_];
pass_ = new unsigned char[passwordLength_];
counter_ = new unsigned char[passwordLength_];
for(int i = 0;i < passwordLength_; i++)
{
prime_[i] = state[4 + i];
pass_[i] = state[4 + passwordLength_ + i];
}
int curpos = 4 + passwordLength_ + passwordLength_;
setLength_ = (int)(*(state + 3 + curpos) << 24 | *(state + 2 + curpos) << 16 | *(state + 1 + curpos) << 8 | *(state + curpos));
set_ = new unsigned char[setLength_];
for(int i = 0; i < setLength_; i++)
{
set_[i] = state[curpos + 4 + i];
}
curpos = curpos + setLength_ + 4;
numThreads_ = (int)(*(state + 3 + curpos) << 24 | *(state + 2 + curpos) << 16 | *(state + 1 + curpos) << 8 | *(state + curpos));
}
bool PassGen::GetNext(unsigned char* container)
{
//i = i + P mod n will produce a random sequence from 1 to n
//basically add the prime numbers modulo setLength_, as if the prime_ array was a big number of base setLength_
int carry = 0;
int sum = 0;
int ctrcarry = numThreads_, ctrsum = 0; //adding numThreads_ every time because if the process is split, you want it to account for the other ones too
bool complete = true; //if all digits in the counter are 0, it has reached it's max
for(int i = passwordLength_ - 1; i >= 0; i--)//loop from the last index of the password and counter to 0
{
//add the prime numbers to the password
sum = carry + pass_[i] + prime_[i];
pass_[i] = sum % setLength_;
carry = sum / setLength_;
container[i] = set_[pass_[i]]; //pass_[i] won't be changed after this, so it's safe to put this here
// add one to the counter
ctrsum = ctrcarry + counter_[i];
counter_[i] = ctrsum % setLength_;
ctrcarry = ctrsum / setLength_;
complete &= (i == passwordLength_ - 1 ? counter_[i] < numThreads_: counter_[i] == 0); //because adding a pair number mod an odd number will return to 1
}
if(!repeating)
{
repeating = complete;
return true;
}
else
{
return false;
}
}
char* PassGen::GetState()
{
return getStateFromData(passwordLength_, prime_, pass_, setLength_, set_, numThreads_); //we dont need to worry about numthreads, because prime already = numThreads * prime
}
double PassGen::GetProgressPercent()
{
//estimate the large math: 2342348 / 3141592 = approx. 234/314
//take the most significant 8 bits of the counter, divide them by the 0 most signifigant bits of the maximum {passlen, passlen, passlen...
//divide that by numThreads_
//multiply by 100 to get percent
int n = log(0xFFFFFFFF)/log(setLength_); //calculate how many digits of the counter will fit inside an integer
double done = 0, max = 0;
int offset = 0;
//find the first "digit" of the number
while(counter_[offset] <= 0)
{
offset++;
}
//find the denominator of our fraction (numerator is a n or passwordLength_ digit numer)
max = pow(setLength_, (passwordLength_ < n ? passwordLength_ : n ));
//calculate the integer value for the numerator
for(int i = 0; i < n && i + offset < passwordLength_ ; i++)
{
done += counter_[i + offset] * pow(setLength_, passwordLength_ - offset - 1 - i);
}
return done / max * 100.0; //should return an approximative percent.
}
char** PassGen::GetThreadStates(unsigned char* charSet, int setLen, int passLen, int numThreads)
{
char** states = new char*[numThreads];
unsigned char newprime[passLen]; //the prime number
unsigned char randomstart[passLen]; //the starting point of the threads
long p = passLen;
for(int i = 0; i < passLen; i++)
{
p = nextPrime(p + 1 + (rand() % 314159265)); // a random prime number greater than the last (so we dont get the same number)
newprime[i] = p % setLen;
randomstart[i] = (rand() % setLen);
}
unsigned char mulPrime[passLen];
for(int i = 0; i < passLen; i++)
mulPrime[i] = newprime[i];
//mulPrime = newprime * numThreads, so that the thread doesnt need to multply the prime numbers by the number of threads, we can do it in advance to speed things up
for(int i = 0; i < numThreads - 1; i++)//loop numThreads - 1 times, -1 because the prime number has already been added once
{
int sum = 0, carry = 0;
for(int d = passLen - 1; d >= 0; d--)
{
sum = carry + mulPrime[d] + newprime[d];
mulPrime[d] = sum % setLen;
carry = sum / setLen;
}
}
for(int i = 0; i < numThreads; i++) //create each state string and add it to the array
{
states[i] = getStateFromData(passLen, mulPrime, randomstart, setLen, charSet, numThreads);
//increment the starting point, so the threds can do the mod numThreads passwords
int sum = 0, carry = 0;
for(int d = passLen - 1; d >= 0; d--)
{
sum = carry + randomstart[d] + newprime[d];
randomstart[d] = sum % setLen;
carry = sum / setLen;
}
}
return states;
}
//--------------PRIVATE METHODS------------------------
char* PassGen::getStateFromData(int passwordLength, unsigned char* primeNumber, unsigned char* password, int setLength, unsigned char* charset, int numThreads)
{
//passwordlength|prime_|password|charsetlength|charset|numthreads|NULL
int size = 4 + passwordLength + passwordLength + 4 + setLength + 4 + 1;
char* state = new char[size];
state[0] = passwordLength % 256;
state[1] = (passwordLength >> 8) % 256;
state[2] = (passwordLength >> 16) % 256;
state[3] = (passwordLength >> 24) % 256;
for(int i = 0; i < passwordLength; i++)
{
state[4 + i] = primeNumber[i];
state[4 + i + passwordLength] = password[i];
}
int curpos = 4 + passwordLength + passwordLength;
state[curpos + 0] = setLength % 256;
state[curpos + 1] = (setLength >> 8) % 256;
state[curpos + 2] = (setLength >> 16) % 256;
state[curpos + 3] = (setLength >> 24) % 256;
curpos = curpos + 4;
for(int i = 0; i < setLength; i++)
{
state[curpos + i] = charset[i];
}
curpos = curpos + setLength;
state[curpos + 0] = numThreads % 256;
state[curpos + 1] = (numThreads >> 8) % 256;
state[curpos + 2] = (numThreads >> 16) % 256;
state[curpos + 3] = (numThreads >> 24) % 256;
state[curpos + 4] = '\0';
return state;
}
long PassGen::nextPrime(long min)
{
long i = min;
while(!isprime(i))
{
i++;
}
return i;
}
bool PassGen::isprime(long p)
{
if( p % 2 == 0) //save half the work
return false;
for(long i = 3; i <= sqrt(p); i+=2)
{
if( p % i == 0) //number is divisible by i
{
return false;
}
}
return true;
}
#58
Re: Week #14 Challenge: C++
Posted 13 April 2010 - 06:23 PM
This is a CD, movie, book, media database using STL and inheritance..
I hope its not too big to post.
header files first, then cpp files..
#pragma once
#include <ostream>
#include <map>
#include <set>
#include <string>
#include "Item.h"
using namespace std;
typedef set<Item*> ItemSet;
typedef map<string,Item*> ItemMap;
typedef map<string,ItemSet*> ItemSetMap;
class Library
{
public:
// general functions
void addKeywordForItem(const Item* const item, const string& keyword);
const ItemSet* itemsForKeyword(const string& keyword) const;
void printItem(ostream& out, const Item* const item) const;
// book-related functions
const Item* addBook(const string& title, const string& author, int const nPages);
const ItemSet* booksByAuthor(const string& author) const;
const ItemSet* books() const;
// music-related functions
const Item* addMusicCD(const string& title, const string& band, const int nSongs);
void addBandMember(const Item* const musicCD, const string& member);
const ItemSet* musicByBand(const string& band) const;
const ItemSet* musicByMusician(const string& musician) const;
const ItemSet* musicCDs() const;
// movie-related functions
const Item* addMovieDVD(const string& title, const string& director, const int nScenes);
void addCastMember(const Item* const movie, const string& member);
const ItemSet* moviesByDirector(const string& director) const;
const ItemSet* moviesByActor(const string& actor) const;
const ItemSet* movies() const;
Library();
~Library();
void Purge(ItemSet &set); // destructor function
private:
ItemSet allBooks; // holds all the information
ItemSet allCDS;
ItemSet allDVDs;
ItemSet* allKeywords; // these hold information for each find
ItemSet* allMusicByBand;
ItemSet* allMusicByMusician;
ItemSet* allmoviesByDirector;
ItemSet* allmoviesByActor;
ItemSet* allBooksByAuthor;
};
item.h
#pragma once
#include <ostream>
#include <set>
#include <string>
using namespace std;
typedef set<string> StringSet;
class Item
{
protected:
Item(const string& title);
public:
void addKeyword(const string& keyword)const;
const string getTitle() const;
const StringSet* getKeywords() const;
virtual void print(ostream& out) const;
string printKeywords(const StringSet* keywords) const;
virtual ~Item();
private:
string Title;
StringSet* Keys; // holds keywords
};
ostream& operator<<(ostream& out, const Item* const item);
book.h
#ifndef BOOK_H
#define BOOK_H
#pragma once
#include "item.h"
using namespace std;
class Book : public Item
{
public:
Book(const string& title, const string& author, const int nPages);
~Book();
const int getPages() const;
const string getAuthor() const;
virtual void print(ostream& out) const;
private:
int numPages;
string Author;
};
ostream& operator<<(ostream& out, const Book* book);
#endif
cd.h
#ifndef CD_H
#define CD_H
#pragma once
#include "item.h"
#include <set>
typedef set<string> StringSet;
class CD : public Item
{
public:
CD(const string& theTitle, const string& theBand, const int snumber);
void addBandMember(const string& member);
const int getNumber() const;
const StringSet* getMusician() const;
const string getBand() const;
virtual void print(ostream& out) const;
string printmusicians(const StringSet* musicians) const;
~CD();
private:
string band;
StringSet* music; // hold musicians
string title;
int number;
};
ostream& operator<<(ostream& out, const CD* cd);
#endif
dvd.h
#ifndef DVD_H
#define DVD_H
#pragma once
#include "item.h"
#include <set>
typedef set<string> StringSet;
class DVD : public Item
{
public:
DVD(const string title, const string director, int nScenes);
const string getDirector() const;
void addCast(const string& cast);
const int getScenes() const;
const StringSet* getCast() const;
virtual void print(ostream& out) const;
string printCast(const StringSet* cast) const;
~DVD();
private:
string Director;
StringSet* Moviecast; // hold cast members
int Scenes;
};
ostream& operator<<(ostream& out, const DVD* dvd);
#endif
here is the Driver
#ifdef _WIN32
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#endif
#include <iostream>
#include "Library.h"
using namespace std;
static Library *library;
static void printItemSet(ostream& out, const ItemSet *itemSet)
{
if (itemSet != NULL && itemSet->size() > 0)
for (ItemSet::const_iterator i = itemSet->begin(); i != itemSet->end(); i++)
library->printItem(out, (Item *) *i);
else
out << "none" << endl << endl;
}
int main(int argc, char **argv)
{
ostream& out(cout);
const Item *item;
cout << "CS261 - Assignment 4xc - Corey Mattis\n" << endl;
// create library instance
library = new Library();
// add items to library
cout << ">>> adding items to library:\n\n";
item = library->addBook("The Curious Incident of the Dog in the Night-Time", "Mark Haddon", 240);
if (item != NULL) {
library->addKeywordForItem(item, "autism");
library->addKeywordForItem(item, "Asperger's Syndrome");
library->printItem(cout, item);
}
item = library->addBook("Starship Troopers", "Robert A. Heinlein", 325);
if (item != NULL) {
library->addKeywordForItem(item, "science fiction");
library->addKeywordForItem(item, "war");
library->addKeywordForItem(item, "weapons");
library->printItem(cout, item);
}
item = library->addBook("The Moon Is A Harsh Mistress", "Robert A. Heinlein", 389);
if (item != NULL) {
library->addKeywordForItem(item, "science fiction");
library->addKeywordForItem(item, "moon");
library->addKeywordForItem(item, "social structures");
library->printItem(cout, item);
}
item = library->addMusicCD("Europe In '72", "Grateful Dead", 12);
if (item != NULL) {
library->addKeywordForItem(item, "acid rock");
library->addKeywordForItem(item, "sixties");
library->addKeywordForItem(item, "jam bands");
library->addBandMember(item, "Jerry Garcia");
library->addBandMember(item, "Bill Kreutzman");
library->addBandMember(item, "Keith Godcheaux");
library->printItem(cout, item);
}
item = library->addMusicCD("Don't Let Go", "Jerry Garcia Band", 15);
if (item != NULL) {
library->addKeywordForItem(item, "acid rock");
library->addKeywordForItem(item, "jam bands");
library->addBandMember(item, "Jerry Garcia");
library->addBandMember(item, "Keith Godcheaux");
library->printItem(cout, item);
}
item = library->addMusicCD("Sergeant Pepper's Lonely Hearts Club Band", "Beatles", 10);
if (item != NULL) {
library->addKeywordForItem(item, "acid rock");
library->addKeywordForItem(item, "sixties");
library->addBandMember(item, "John Lennon");
library->addBandMember(item, "George Harrison");
library->addBandMember(item, "Ringo Starr");
library->printItem(cout, item);
}
item = library->addMovieDVD("Lost In Translation", "Sofia Coppola", 14);
if (item != NULL) {
library->addKeywordForItem(item, "Japan");
library->addKeywordForItem(item, "loneliness");
library->addCastMember(item, "Bill Murray");
library->addCastMember(item, "Sofia Coppola");
library->printItem(cout, item);
}
item = library->addMovieDVD("Groundhog Day", "Harold Ramis", 14);
if (item != NULL) {
library->addKeywordForItem(item, "newscaster");
library->addKeywordForItem(item, "groundhog");
library->addKeywordForItem(item, "time");
library->addCastMember(item, "Bill Murray");
library->addCastMember(item, "Andie MacDowell");
library->printItem(cout, item);
}
// print books, musicCDs, movies
cout << ">>> books:\n\n";
printItemSet(out, library->books());
cout << ">>> music CDs:\n\n";
printItemSet(out, library->musicCDs());
cout << ">>> movies:\n\n";
printItemSet(out, library->movies());
// print items for keyword
cout << ">>> items for keyword \"science fiction\"\n\n";
printItemSet(out, library->itemsForKeyword("science fiction"));
cout << ">>> items for keyword \"jam bands\"\n\n";
printItemSet(out, library->itemsForKeyword("jam bands"));
cout << ">>> items for keyword \"xxx\"\n\n";
printItemSet(out, library->itemsForKeyword("xxx"));
// items for artist
cout << ">>> books by Robert A. Heinlein:\n\n";
printItemSet(cout, library->booksByAuthor("Robert A. Heinlein"));
cout << ">>> music by the Grateful Dead:\n\n";
printItemSet(out, library->musicByBand("Grateful Dead"));
cout << ">>> music by the Rolling Stones:\n\n";
printItemSet(out, library->musicByBand("Rolling Stones"));
cout << ">>> movies by Sofia Coppola:\n\n";
printItemSet(out, library->moviesByDirector("Sofia Coppola"));
cout << ">>> music by Jerry Garcia:\n\n";
printItemSet(out, library->musicByMusician("Jerry Garcia"));
cout << ">>> movies with Bill Murray:\n\n";
printItemSet(out, library->moviesByActor("Bill Murray"));
delete library;
// in Visual Studio, reports on memory leaks in the Output window
#ifdef _WIN32
_CrtDumpMemoryLeaks();
#endif
}
Here is library.cpp
#include "Library.h"
#include "book.h"
#include "cd.h"
#include "dvd.h"
#include <iostream>
/**
* Library: Constructor
* in: none
* out: none
* return: none
**/
Library::Library()
: allKeywords(new ItemSet),allMusicByBand(new ItemSet),allMusicByMusician(new ItemSet),
allmoviesByDirector(new ItemSet),allmoviesByActor(new ItemSet), allBooksByAuthor(new ItemSet)
{
}
/**
* Library: add keyword
* in: item, keyword
* out: none
* return: none
**/
void Library::addKeywordForItem(const Item* item, const string& keyword)
{
item->addKeyword(keyword); // call addkeyword function and add keyword to item
}
/**
* Library: Search allkeywords for a given keyword
* in: keyword
* out: none
* return: allkeywords
**/
const ItemSet* Library::itemsForKeyword(const string& keyword) const
{
const StringSet* kw;
if(allKeywords->size() > 0) // clear keyword
{
allKeywords->clear();
}
/* search books */
for(ItemSet::const_iterator itr = this->allBooks.begin(); itr != this->allBooks.end(); itr++)
{
kw = ((*itr)->getKeywords());
if((kw->find(keyword)) != kw->end())
{
allKeywords->insert(*itr); // add the found keyword
}
}
/* search cd */
for(ItemSet::const_iterator itr = this->allCDS.begin();itr != this->allCDS.end();itr++)
{
kw = ((*itr)->getKeywords());
if((kw->find(keyword)) != kw->end())
{
allKeywords->insert(*itr);
}
}
/* search Movie */
for(ItemSet::const_iterator itr = this->allDVDs.begin();itr != this->allDVDs.end();itr++)
{
kw = ((*itr)->getKeywords());
if((kw->find(keyword)) != kw->end())
{
allKeywords->insert(*itr);
}
}
return allKeywords; // return the find
}
/**
* Library: print
* in: out, item
* out: none
* return: out
**/
void Library::printItem(ostream& out, const Item* const item) const
{
out << item;
}
/**
* Library: addBook
* in: title, author, pages
* out: none
* return: item
**/
const Item* Library::addBook(const string& title, const string& author, const int nPages)
{
Book* item = new Book(title,author,nPages);
allBooks.insert(item); // add to set of all books
return item;
}
/**
* Library: add all books by a particular author
* in: author
* out: none
* return: none
**/
const ItemSet* Library::booksByAuthor(const string& author) const
{
/* search allbooks for an author */
for (ItemSet::const_iterator i = this->allBooks.begin(); i != this->allBooks.end(); ++i)
{
if(((Book*) *i)->getAuthor() == author)
{
allBooksByAuthor->insert(*i);
}
}
return allBooksByAuthor;
}
/**
* Library: Return all books that were added
* in: none
* out: none
* return: none
**/
const ItemSet* Library::books() const
{
return &allBooks;
}
// music-related functions
/**
* Library: add music cd information
* in: title, band, songs
* out: none
* return: item
**/
const Item* Library::addMusicCD(const string& title, const string& band, const int nSongs)
{
CD* item = new CD(title,band,nSongs);
allCDS.insert(item);
return item;
}
/**
* Library: add band members to the allCDS
* in: musicCD, member
* out: none
* return: none
**/
void Library::addBandMember(const Item* musicCD, const string& member)
{
(((CD*) musicCD)->addBandMember(member));
}
const ItemSet* Library::musicByBand(const string& band) const
{
if(allMusicByBand->size() > 0) // this is just incase there is not a find
{ // and it dont return the last found item.
allMusicByBand->clear();
}
/* search allCDS for a particular band */
for (ItemSet::const_iterator i = this->allCDS.begin(); i != this->allCDS.end(); ++i)
{
if(((CD*) *i)->getBand() == band)
{
allMusicByBand->insert(*i);
}
}
return allMusicByBand;
}
/**
* Library: Search and add all instances of a certian musician
* in: musician
* out: none
* return: allMusicByMusician
**/
const ItemSet* Library::musicByMusician(const string& musician) const
{
const StringSet* search_m;
for (ItemSet::const_iterator i = this->allCDS.begin(); i != this->allCDS.end(); ++i)
{
search_m = (((CD*) *i)->getMusician());
if((search_m->find(musician)) != search_m->end())
{
allMusicByMusician->insert(*i);
}
}
return allMusicByMusician;
}
/**
* Library: return all music CD
* in: none
* out: none
* return: allCDS
**/
const ItemSet* Library::musicCDs() const
{
return &allCDS;
}
// movie-related functions
/**
* Library: add all movies
* in: title, director, scenes
* out: none
* return: item
**/
const Item* Library::addMovieDVD(const string& title, const string& director, const int nScenes)
{
DVD* item = new DVD(title, director, nScenes);
allDVDs.insert(item);
return item;
}
/**
* Library: add cast members to movies
* in: movie, member
* out: none
* return: none
**/
void Library::addCastMember(const Item* const movie, const string& member)
{
((DVD*) movie)->addCast(member);
}
/**
* Library: add and return all movies by a certain director
* in: director
* out: none
* return: allmoviesbydirector
**/
const ItemSet* Library::moviesByDirector(const string& director) const
{
for (ItemSet::const_iterator i = this->allDVDs.begin(); i != this->allDVDs.end(); ++i)
{
if(((DVD*) *i)->getDirector() == director)
{
allmoviesByDirector->insert(*i);
}
}
return allmoviesByDirector;
}
/**
* Library: search and add all movies by a certain actor
* in: actor
* out: none
* return: allmoviesbyactor
**/
const ItemSet* Library::moviesByActor(const string& actor) const
{
const StringSet* search_a;
for (ItemSet::const_iterator i = this->allDVDs.begin(); i != this->allDVDs.end(); ++i)
{
search_a = (((DVD*) *i)->getCast());
if((search_a->find(actor)) != search_a->end())
{
allmoviesByActor->insert(*i);
}
}
return allmoviesByActor;
}
/**
* Library: retuen all movies
* in: none
* out: none
* return: alldvds
**/
const ItemSet* Library::movies() const
{
return &allDVDs;
}
/**
* Library: Destructor
* in: none
* out: none
* return: none
**/
Library::~Library()
{
delete allKeywords;
delete allMusicByBand;
delete allMusicByMusician;
delete allmoviesByDirector;
delete allmoviesByActor;
delete allBooksByAuthor;
Purge(allBooks);
Purge(allCDS);
Purge(allDVDs);
}
/**
* Library: destructor function for removing memory in the sets
* in: itemset
* out: none
* return: item
**/
void Library::Purge(ItemSet &set)
{
for (ItemSet::iterator it = set.begin(); it != set.end(); ++it)
delete *it;
set.clear();
}
Here is item.cpp
#include "Item.h"
#include "library.h"
#include <iostream>
/**
* Item: constructor - initializer list
* in: title
* out: Keys
* return: none
**/
Item::Item(const string& title): Title(title), Keys(new StringSet)
{
}
/**
* Item: destructor
* in: none
* out: none
* return: none
**/
Item::~Item()
{
delete Keys;
}
/**
* Item: add keywords to item
* in: keyword
* out: Keys
* return: none
**/
void Item::addKeyword(const string& keyword) const
{
Keys->insert(keyword);
}
/**
* Item: get title
* in: none
* out: none
* return: title
**/
const string Item::getTitle() const
{
return Title;
}
/**
* Item: get keywords
* in: none
* out: none
* return: keys
**/
const StringSet* Item::getKeywords() const
{
return Keys;
}
/**
* Item: print keywords
* in: stringset keywords
* out: none
* return: string
**/
string Item::printKeywords(const StringSet* keywords) const
{
string keyString;
StringSet::const_iterator itr;
for(itr = keywords->begin();itr != keywords->end();itr++)
keyString.append(*itr + ", ");
keyString.erase(keyString.end() - 2, keyString.end());
return keyString;
}
/**
* Item: overload operator
* in: item
* out: out
* return: out
**/
ostream& operator<<(ostream& out, const Item* item)
{
item->print(out);
return out;
}
/**
* Item: print
* in: out
* out: none
* return: none
**/
void Item::print(ostream &out) const
{
out << "title: " << this->getTitle() << endl;
out << endl;
}
here is book.cpp
#include "Book.h"
using namespace std;
/**
* Book: constructor
* in: title, author, pages
* out: item,pages, author
* return: none
**/
Book::Book(const string &title, const string &author, const int nPages)
:Item(title),numPages(nPages),Author(author)
{
}
/**
* Book: get author
* in: none
* out: none
* return: author
**/
const string Book::getAuthor() const
{
return Author;
}
/**
* Book: get pages
* in: none
* out: none
* return: pages
**/
const int Book::getPages() const
{
return numPages;
}
/**
* Book: print book information
* in: out
* out: none
* return: none
**/
void Book::print(ostream &out) const
{
out << "-Book-" << endl;
out << "author: " << this->getAuthor() << endl;
out << "pages: " << this->getPages() << endl;
out << "title: " << this->getTitle() << endl;
out << "keywords: " << this->printKeywords(this->getKeywords()) << endl;
out << endl;
}
/**
* Book: overloaded operator
* in: out, book
* out: out
* return: out
**/
ostream& operator<<(ostream& out, const Book* book)
{
book->print(out);
return out;
}
/**
* Book: destructor
* in: none
* out: none
* return: author
**/
Book::~Book()
{
}
here is DVD.cpp
#include "DVD.h"
using namespace std;
/**
* DVD: Constructor
* in: title, director, scenes
* out: title, director,scenese, moviecast
* return: none
**/
DVD::DVD(const string title, const string director, int nScenes)
:Item(title),Director(director),Scenes(nScenes), Moviecast(new StringSet)
{
}
/**
* DVD: Destructor
* in: none
* out: none
* return: none
**/
DVD::~DVD()
{
delete Moviecast;
}
/**
* DVD: add cast to dvd
* in: cast
* out: none
* return: none
**/
void DVD::addCast(const string& cast)
{
Moviecast->insert(cast);
}
/**
* DVD: get cast
* in: none
* out: none
* return: moviecast
**/
const StringSet* DVD::getCast() const
{
return Moviecast;
}
/**
* DVD: get director
* in: none
* out: none
* return: director
**/
const string DVD::getDirector() const
{
return Director;
}
/**
* DVD: get scenes
* in: none
* out: none
* return: scenes
**/
const int DVD::getScenes() const
{
return Scenes;
}
/**
* DVD: print - movie
* in: out
* out: none
* return: none
**/
void DVD::print(ostream &out) const
{
out << "-MovieDVD-" << endl;
out << "director: " << this->getDirector() << endl;
out << "cast: " << this->printCast(this->getCast()) << endl;
out << "scenes: " << this->getScenes() << endl;
out << "title: " << this->getTitle() << endl;
out << "keywords: " << this->printKeywords(this->getKeywords()) << endl;
out << endl;
}
/**
* DVD: overloaded operator
* in: DVD, out
* out: none
* return: out
**/
ostream& operator<<(ostream& out, const DVD* dvd)
{
dvd->print(out);
return out;
}
/**
* DVD: print cast members
* in: cast
* out: none
* return: cast string
**/
string DVD::printCast(const StringSet *cast) const
{
string castString;
StringSet::const_iterator itr;
for(itr = cast->begin(); itr != cast->end(); itr++)
castString.append(*itr + ", ");
castString.erase(castString.end() - 2, castString.end());
return castString;
}
her is cd.cpp
#include "CD.h"
using namespace std;
/**
* CD: constructor
* in: none
* out: none
* return: none
**/
CD::CD(const string& theTitle, const string& theBand, const int snumber)
: Item(theTitle), band(theBand),number(snumber), music(new StringSet)
{
}
/**
* CD: Destructor
* in: none
* out: none
* return: none
**/
CD::~CD()
{
delete music;
}
/**
* CD: get band
* in: none
* out: none
* return: band
**/
const string CD::getBand() const
{
return band;
}
/**
* CD: get musician
* in: none
* out: none
* return: music
**/
const StringSet* CD::getMusician() const
{
return music;
}
/**
* CD: get number
* in: none
* out: none
* return: number
**/
const int CD::getNumber() const
{
return number;
}
/**
* CD: add band members to the set
* in: member
* out: none
* return: none
**/
void CD::addBandMember(const string &member)
{
music->insert(member);
}
/**
* CD: print - music information
* in: out
* out: none
* return: none
**/
void CD::print(ostream &out) const
{
out << "-MusicCD-" << endl;
out << "band: " << this->getBand() << endl;
out << "musicians: " << this->printmusicians(this->getMusician()) << endl;
out << "songs: " << this->getNumber() << endl;
out << "title: " << this->getTitle() << endl;
out << "keywords: " << this->printKeywords(this->getKeywords()) << endl;
out << endl;
}
/**
* CD: overloaded operator
* in: out,cd
* out: none
* return: out
**/
ostream& operator<<(ostream& out, const CD* cd)
{
cd->print(out);
return out;
}
/**
* CD: print musicians
* in: stringset musicians
* out: none
* return: music string
**/
string CD::printmusicians(const StringSet *musicians) const
{
string musicString;
StringSet::const_iterator itr;
for(itr = musicians->begin(); itr != musicians->end(); itr++)
musicString.append(*itr + ", ");
musicString.erase(musicString.end() - 2, musicString.end());
return musicString;
}
Sample output:
CS261 - Assignment 4xc - Corey Mattis >>> adding items to library: -Book- author: Mark Haddon pages: 240 title: The Curious Incident of the Dog in the Night-Time keywords: Asperger's Syndrome, autism -Book- author: Robert A. Heinlein pages: 325 title: Starship Troopers keywords: science fiction, war, weapons -Book- author: Robert A. Heinlein pages: 389 title: The Moon Is A Harsh Mistress keywords: moon, science fiction, social structures -MusicCD- band: Grateful Dead musicians: Bill Kreutzman, Jerry Garcia, Keith Godcheaux songs: 12 title: Europe In '72 keywords: acid rock, jam bands, sixties -MusicCD- band: Jerry Garcia Band musicians: Jerry Garcia, Keith Godcheaux songs: 15 title: Don't Let Go keywords: acid rock, jam bands -MusicCD- band: Beatles musicians: George Harrison, John Lennon, Ringo Starr songs: 10 title: Sergeant Pepper's Lonely Hearts Club Band keywords: acid rock, sixties -MovieDVD- director: Sofia Coppola cast: Bill Murray, Sofia Coppola scenes: 14 title: Lost In Translation keywords: Japan, loneliness -MovieDVD- director: Harold Ramis cast: Andie MacDowell, Bill Murray scenes: 14 title: Groundhog Day keywords: groundhog, newscaster, time >>> books: -Book- author: Mark Haddon pages: 240 title: The Curious Incident of the Dog in the Night-Time keywords: Asperger's Syndrome, autism -Book- author: Robert A. Heinlein pages: 325 title: Starship Troopers keywords: science fiction, war, weapons -Book- author: Robert A. Heinlein pages: 389 title: The Moon Is A Harsh Mistress keywords: moon, science fiction, social structures >>> music CDs: -MusicCD- band: Grateful Dead musicians: Bill Kreutzman, Jerry Garcia, Keith Godcheaux songs: 12 title: Europe In '72 keywords: acid rock, jam bands, sixties -MusicCD- band: Jerry Garcia Band musicians: Jerry Garcia, Keith Godcheaux songs: 15 title: Don't Let Go keywords: acid rock, jam bands -MusicCD- band: Beatles musicians: George Harrison, John Lennon, Ringo Starr songs: 10 title: Sergeant Pepper's Lonely Hearts Club Band keywords: acid rock, sixties >>> movies: -MovieDVD- director: Sofia Coppola cast: Bill Murray, Sofia Coppola scenes: 14 title: Lost In Translation keywords: Japan, loneliness -MovieDVD- director: Harold Ramis cast: Andie MacDowell, Bill Murray scenes: 14 title: Groundhog Day keywords: groundhog, newscaster, time >>> items for keyword "science fiction" -Book- author: Robert A. Heinlein pages: 325 title: Starship Troopers keywords: science fiction, war, weapons -Book- author: Robert A. Heinlein pages: 389 title: The Moon Is A Harsh Mistress keywords: moon, science fiction, social structures >>> items for keyword "jam bands" -MusicCD- band: Grateful Dead musicians: Bill Kreutzman, Jerry Garcia, Keith Godcheaux songs: 12 title: Europe In '72 keywords: acid rock, jam bands, sixties -MusicCD- band: Jerry Garcia Band musicians: Jerry Garcia, Keith Godcheaux songs: 15 title: Don't Let Go keywords: acid rock, jam bands >>> items for keyword "xxx" none >>> books by Robert A. Heinlein: -Book- author: Robert A. Heinlein pages: 325 title: Starship Troopers keywords: science fiction, war, weapons -Book- author: Robert A. Heinlein pages: 389 title: The Moon Is A Harsh Mistress keywords: moon, science fiction, social structures >>> music by the Grateful Dead: -MusicCD- band: Grateful Dead musicians: Bill Kreutzman, Jerry Garcia, Keith Godcheaux songs: 12 title: Europe In '72 keywords: acid rock, jam bands, sixties >>> music by the Rolling Stones: none >>> movies by Sofia Coppola: -MovieDVD- director: Sofia Coppola cast: Bill Murray, Sofia Coppola scenes: 14 title: Lost In Translation keywords: Japan, loneliness >>> music by Jerry Garcia: -MusicCD- band: Grateful Dead musicians: Bill Kreutzman, Jerry Garcia, Keith Godcheaux songs: 12 title: Europe In '72 keywords: acid rock, jam bands, sixties -MusicCD- band: Jerry Garcia Band musicians: Jerry Garcia, Keith Godcheaux songs: 15 title: Don't Let Go keywords: acid rock, jam bands >>> movies with Bill Murray: -MovieDVD- director: Sofia Coppola cast: Bill Murray, Sofia Coppola scenes: 14 title: Lost In Translation keywords: Japan, loneliness -MovieDVD- director: Harold Ramis cast: Andie MacDowell, Bill Murray scenes: 14 title: Groundhog Day keywords: groundhog, newscaster, time
This post has been edited by icelated: 13 April 2010 - 06:27 PM
#59
Re: Week #14 Challenge: C++
Posted 19 April 2010 - 01:58 AM
|
|

New Topic/Question
Reply




MultiQuote

















|