Im having trouble outputting the data members of a Card object using the overloaded operator<<
I'm getting an error that says
"JS::operator<<(std::__1::basic_ostream >&, JS::Card const&)", referenced from:
linker command failed with exit code 1 (use -v to see invocation)
//
//Main.cpp
#include "Card.h"
#include "Deck.h"
#include <iostream>
using std::cout;
using namespace JasonSteindorf;
int main(int argc, const char * argv[]) {
//Deck d;
//d.shuffle();
Card c(5,3); //5 of Clubs
Card c2; //Ace of Diamonds
cout << c; //not working ???????? should says 5 of Clubs
c.displayCard(); //works
return 0;
}
//
//Deck.h
#ifndef JS_DECK_H
#define JS_DECK_H
#include <iostream>
using std::cout;
#include <vector>
using std::vector;
namespace JS {
//forward declaration
class Card;
class Deck {
public:
Deck();
void shuffle();
private:
vector<Card>cards;
};
}
#endif
//
//Deck.cpp
#include "Deck.h"
#include "Card.h"
#include <algorithm>
using std::random_shuffle;
#include <iostream>
using std::cout;
using namespace JS;
Deck::Deck() {
cout << "A DECK OF CARDS!!!\n\n";
for(int suit = 0; suit < 4; suit++) {
for(int rank = 1; rank < 14; rank++) {
cards.push_back(Card(rank, suit));
}
cout << '\n';
}
}
void
Deck::shuffle() {
random_shuffle(cards.begin(), cards.end());
//for(int s = 0; s < 52; s++)
// cards.at(s)->displayCard();
for(vector<Card>::iterator it = cards.begin(); it < cards.end(); it++) {
Card a = *it;
a.displayCard();
}
}
//
//Card.h
#ifndef JS_CARD_H
#define JS_CARD_H
#include <iostream>
using std::ostream;
#include <string>
using std::string;
#include <vector>
using std::vector;
namespace JS {
class Card {
public:
enum Suit { DIAMONDS, HEARTS, SPADES, CLUBS };
enum Rank { ACE = 1, JACK = 11, QUEEN = 12, KING = 13 };
Card();
Card(int rank, int suit);
string getRank() const;
string getSuit() const;
int getRankValue() const;
int operator+(const Card& rhs);
void displayCard() const;
private:
int rank;
int suit;
};
//ostream &operator<<(ostream &out, const Card &rhs);
ostream& operator << (ostream& out, const Card& c);
}
#endif
//
//Card.cpp
#include "Card.h"
#include <iomanip>
using std::setw;
using std::right;
#include <iostream>
using std::cout;
#include <sstream>
using std::stringstream;
using namespace JS;
Card::Card(): rank(1), suit(0){
displayCard();
}
Card::Card(int rank, int suit) : rank(rank), suit(suit) {
displayCard();
}
string
Card::getSuit() const {
switch (suit) {
case SPADES: return "Spades"; break;
case HEARTS: return "Hearts"; break;
case DIAMONDS: return "Diamonds"; break;
case CLUBS: return "Clubs"; break;
default: return ""; break;
}
}
string
Card::getRank() const {
switch (rank) {
case ACE: return "Ace"; break;
case JACK: return "Jack"; break;
case QUEEN: return "Queen"; break;
case KING: return "King"; break;
default:
stringstream out;
out << rank;
return out.str();
break;
}
}
int
Card::getRankValue() const {
switch (rank) {
case ACE: return 1; break;
case JACK:
case QUEEN:
case KING: return 10; break;
default: return rank; break;
}
}
int
Card::operator+(const Card& rhs) {
return (getRankValue() + rhs.getRankValue());
}
ostream& operator <<(ostream& out, const Card& c)
{
out << c.getRank() << " of " << c.getSuit();
return out;
}
/*ostream
&operator<<(ostream &out, const Card &rhs) {
out << rhs.getRank() << " of " << rhs.getSuit();
return out;
}*/
void
Card::displayCard() const {
cout << right << setw(5) << getRank()
<< setw(3) << " of "
<< getSuit() << '\n';
}
Card.h declares the operator in a namespace:
namespace JS {
ostream& operator << (ostream& out, const Card& c);
}
but Card.cpp defines a different operator in the global namespace:
ostream& operator <<(ostream& out, const Card& c) {...}
Your choices are:
Put the declaration in the global namespace; or
Put the definition in the JS namespace; or
Qualify the name as JS::operator<< in the definition.
Related
So i have this program and i want to implement an insert void function. Basically i want to insert a card into the deck. The output should be a deck of cards and the shuffled version and then insert a card and sort it again. How can i accomplish that?
Deck.cpp
#include "deck.h"
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <random>
#include <chrono>
using namespace std;
/**
* Help function to convert Suit enum to string
*/
const string SuitToString(Suit s) {
switch (s) {
case Suit::Hearts:
return "H";
case Suit::Diamonds:
return "D";
case Suit::Spades:
return "S";
case Suit::Clubs:
return "C";
}
return "";
}
Card::Card(int rank, Suit suit)
{
this->rank = rank;
this->suit = suit;
}
/**
* Overload of << operator for Card class
*/
ostream & operator << (ostream &out, const Card &c)
{
string r;
switch(c.rank) {
case 1:
r = 'A';
break;
case 11:
r = 'J';
break;
case 12:
r = 'Q';
break;
case 13:
r = 'K';
break;
default:
r = to_string(c.rank);
break;
}
out << r << SuitToString(c.suit);
return out;
}
/**
* Create a deck of 52 cards
*/
Deck::Deck() {
for (Suit s = Suit::Hearts; s <= Suit::Clubs; s = Suit(s + 1)) {
for (int r=1; r<14; r++) {
cards.push_back(Card(r, s));
}
}
}
/**
* Overload of << operator for Deck class
*/
ostream & operator << (ostream &out, const Deck &d)
{
string separator;
for (auto i: d.cards) {
out << separator << i;
separator = ", ";
}
return out;
}
/**
* Return number of cards in deck
*
*/
int Deck::size()
{
return this->cards.size();
}
/**
* Shuffle all the cards in deck in ranom order.
*/
void Deck::shuffle()
{
auto rng = std::default_random_engine(std::chrono::system_clock::now().time_since_epoch().count());
std::shuffle(this->cards.begin(),this->cards.end(), rng);
}
/**
* Sort the deck according to card rank. All aces, the all two's, then all threes, ...
*/
void Deck::sort()
{
vector<Card> sorted_cards; // Empty temporary deck
while (this->size() > 0) {
// Go through the deck from left to right, insert the deck in the appropriate spot
Deck::insert(sorted_cards, this->take()); //Take a card from the old deck, insert it into the new one
}
this->cards = sorted_cards;
}
/**
* Take the top card from the deck
*/
Card Deck::take() {
Card c = this->cards.back();
this->cards.pop_back();
return c;
}
/**
* Put a card on top of the deck
*/
void Deck::put(Card card) {
cards.push_back(card);
}
void Deck::insert(vector<Card> &cardlist, Card card) {
/**
* My insert code here!
*/
return;
}
Deck.h
#include <iostream>
#include <vector>
#include <string>
using namespace std;
enum Suit {
Hearts,
Diamonds,
Spades,
Clubs
};
class Card
{
private:
int rank;
Suit suit;
public:
Card(int rank, Suit suit);
bool operator == (Card const &other)
{
return rank == other.rank;
}
bool operator < (Card const &other)
{
return rank < other.rank;
}
bool operator > (Card const &other)
{
return rank > other.rank;
}
friend ostream & operator << (ostream &out, const Card &c);
};
class Deck
{
private:
vector<Card> cards;
public:
Deck();
friend ostream & operator << (ostream &out, const Deck &d);
int size();
void shuffle();
void sort();
Card take();
void put(Card card);
static void insert(vector<Card> &cardlist, Card card);
};
main.cpp
#include "deck.h"
#include <iostream>
using namespace std;
main() {
Deck deck = Deck();
cout << "Fresh deck: " << deck << endl;
deck.shuffle();
cout << "Shuffled deck: " << deck << endl;
deck.sort();
cout << "Sorted deck: " << deck << endl;
}
For now i just have written the function itself.
Since Deck::insert is being called from the Deck::sort method, I think the aim is to insert the new card in order with respect to the previously inserted (and therefore already sorted) cards.
So it seems you need something like this
void Deck::insert(vector<Card> &cardlist, Card card) {
// starting from zero
size_t i = 0;
// find the index of the first card in the list that is >= to the card to insert
for (; i < cardList.size(); ++i)
{
if (card < cardList[i])
break;
}
// insert the new card before that index
cardList.insert(cardList.begin() + i, card);
}
This is bad code, for a couple of reasons (efficiency and design) but the above is my take on what you are being asked to do.
I have created card and deck classes for use in a C++ poker game, however, I'm trying to check that my assignment of vector elements are correct and having issues displaying them on the console. I have an enumerated class for the suits and integer values for the ranks. I see that my deck vector is generating with 52 cards, but I'm not sure how to correctly get this to display on the screen using the card class display() function for each vector element. Any help would be appreciated.
Note: I'm also guessing an alternate method would be to overload the output stream operator to display a vector element that is an object with an enumerated class parameter, but also not sure on what that syntax would look like.
int main(){ Deck deck();}
Card.h
#pragma once
#include <stdlib.h>
#include <iostream>
using namespace std;
enum class Suit { Hearts, Diamonds, Spades, Clubs };
class Card
{
private:
Suit m_suit;
int m_rank;
public:
Card();
Card(int r, Suit s);
void display();
int getRank();
void setRank(int);
Suit getSuit();
void setSuit(Suit);
};
Card.cpp
#include "Card.h"
#include <iostream>
#include <string>
Card::Card(): m_rank(0), m_suit(Suit::Hearts)
{
}
Card::Card(int r, Suit s)
{
m_rank = r;
m_suit = s;
}
void Card::display()
{
if (m_rank == 1) // for number cards, show value
{
std::cout << "Ace";
}
else if ((2 <= m_rank) && (m_rank <= 10))
{
std::cout << m_rank;
}
else
{
switch (m_rank)
{
case 11:
std::cout << "Jack";
break;
case 12:
std::cout << "Queen";
break;
case 13:
std::cout << "King";
break;
default:
std::cout << "INVALID RANK";
}
}
switch (m_suit) // display suit
{
case Suit::Hearts:
std::cout << " of Hearts";
break;
case Suit::Diamonds:
std::cout << " of Diamonds";
break;
case Suit::Spades:
std::cout << " of Spades";
break;
case Suit::Clubs:
std::cout << " of Clubs";
break;
};
}
int Card::getRank()
// return the numeric value of a card
{
return (m_rank);
}
Deck.h
#pragma once
#include <vector>
#include "Card.h"
class Deck
{
private:
Card card;
std::vector<Card> m_deck;
public:
Deck();
void shuffle();
void grabCard();
};
Deck.cpp
#include "Deck.h"
#include "Card.h"
#include <vector>
Deck::Deck()
{
for (int i = 1; i < 14; i++)
{
for (int j = int(Suit::Hearts); j <= int(Suit::Clubs); j++)
{
m_deck.push_back(Card(int(i), Suit(j))); //passing the card constructor to create a card object, then store it as a vector element
int counter = 0; // use to print out each element
std::cout << m_deck[card.display()]; //output each card obect via display method
std::cout << "\t\n";
counter++;
}
}
}
void Deck::shuffle()
{
}
void Deck::grabCard()
{
}
To display vector element, you should call display() of the vector element to display.
std::cout << m_deck[card.display()];
should be
m_deck.back().display();
to have it display the last pushed card.
Also int main(){ Deck deck();} is a main function with only function declaration and Deck::Deck() won't be called.
To call the constructor, it should be int main(){ Deck deck;}.
What I am trying to do is add cards to a vector that is to be a Blackjack hand, but each time I enter the function that uses push_back to add a card to the vector, the vector starts out empty. The problem is in my Hand class in the addCardToHand function, and the same issue is present in the same class in my showHand function. I have whittled the code down as much as I could but still present a full working version with the issue. I cannot figure out why my Hand class treats the hand as brand new every time I call a function in the class. Please advise.
// Card.h
#ifndef CARD_H
#define CARD_H
#include <string>
#include <array>
class Card {
private:
int rank;
int suit;
int hardValue;
int softValue;
static const std::array<std::string,14> ranks;
static const std::array<std::string,5> suits;
public:
Card();
Card(int rank, int suit);
int getHardValue() const;
int getSoftValue() const;
std::string toString() const;
};
#endif
// Card.cpp
#include "Card.h"
const std::array<std::string,14> Card::ranks {"","A","2","3","4","5","6","7","8","9","10","J","Q","K"};
const std::array<std::string,5> Card::suits {"","C","D","H","S"};
Card::Card() : rank(0), suit(0) {
hardValue = 0;
softValue = 0;
}
Card::Card(int rank, int suit) : rank(rank), suit(suit) {
if (rank == 1) {
hardValue = 1;
softValue = 11;
}
else if (rank <= 10) {
hardValue = rank;
softValue = rank;
}
else {
hardValue = 10;
softValue = 10;
}
}
int Card::getHardValue() const {
return hardValue;
}
int Card::getSoftValue() const {
return softValue;
}
std::string Card::toString() const {
return ranks[rank] + suits[suit];
}
// Shoe.h
#ifndef SHOE_H
#define SHOE_H
#include <vector>
#include <random>
#include "Card.h"
class Shoe {
private:
int numDecksInShoe;
std::vector<Card> shoe;
static int currentCard;
static int maxDealCard;
static const unsigned long int seed;
static std::mt19937 randEng;
void renewShoe();
public:
Shoe();
explicit Shoe(int numDecksInShoe);
std::vector<Card> getShoe() const;
int getCurrentCard() const;
int getMaxDealCard() const;
void shuffle();
Card dealCard();
};
#endif
// Shoe.cpp
#include <ctime>
#include "Shoe.h"
const unsigned long int Shoe::seed = static_cast<unsigned long int>(std::time(nullptr));
std::mt19937 Shoe::randEng(seed);
int Shoe::currentCard = 0;
int Shoe::maxDealCard = 51;
Shoe::Shoe() {
}
Shoe::Shoe(int decksInShoe) {
numDecksInShoe = decksInShoe;
int count = 0;
for (int i = 0; i < numDecksInShoe; i++) {
for (int suit = 4; suit >= 1; suit--) {
for (int rank = 1; rank <= 13; rank++) {
Card card(rank,suit);
shoe.push_back(card);
count += 1;
}
}
}
currentCard = 0;
maxDealCard = count - 1;
}
std::vector<Card> Shoe::getShoe() const {
return shoe;
}
int Shoe::getCurrentCard() const {
return currentCard;
}
int Shoe::getMaxDealCard() const {
return maxDealCard;
}
void Shoe::shuffle() {
Card temp;
std::uniform_int_distribution<int> deckDist(0,numDecksInShoe*52-1);
int index;
for (int i = 0; i < numDecksInShoe*52; i++) {
do {
index = deckDist(randEng);
} while (index == i);
temp = shoe[index];
shoe[index] = shoe[i];
shoe[i] = temp;
}
std::uniform_int_distribution<int> maxDeal(10,41);
int tempMax = (numDecksInShoe-1)*52 - 1;
maxDealCard = tempMax + 51 - maxDeal(randEng);
}
Card Shoe::dealCard() {
if (currentCard == maxDealCard) {
renewShoe();
}
Card dealCard = shoe[currentCard];
currentCard += 1;
return dealCard;
}
void Shoe::renewShoe() {
Shoe newShoe(numDecksInShoe);
shoe = newShoe.getShoe();
shuffle();
}
here is my Hand class
// Hand.h
#ifndef HAND_H
#define HAND_H
#include <vector>
#include <string>
#include "Card.h"
class Hand {
private:
std::vector<Card> hand;
public:
Hand();
std::vector<Card> getHand() const;
void addCardToHand(Card card);
void clearHand();
Card revealBottomCard();
std::string showHand() const;
std::string peakHand() const;
};
#endif
// Hand.cpp
#include <iostream>
#include "Hand.h"
Hand::Hand() {
}
std::vector<Card> Hand::getHand() const {
return hand;
}
void Hand::addCardToHand(Card card) {
std::cout << card.toString() << std::endl;
hand.push_back(card);
}
void Hand::clearHand() {
hand.clear();
}
std::string Hand::showHand() const {
std::string returnString = "";
for (int i = hand.size()-1; i >= 1; i--) {
returnString += hand[i].toString() + "\n";
}
returnString += "XX\n";
return returnString;
}
std::string Hand::peakHand() const {
std::string returnString = "";
for (int i = hand.size()-1; i >= 0; i--) {
returnString += hand[i].toString() + "\n";
}
return returnString;
}
here is the Table class that has the code that calls the Hand class functions
// Table.h
#ifndef TABLE_H
#define TABLE_H
#include "Shoe.h"
#include "Player.h"
class Table {
private:
Shoe shoe;
public:
explicit Table(Shoe shoe);
Shoe getShoe() const;
void clearHand(std::vector<Player> players);
void dealHand(std::vector<Player> players);
};
#endif
// Table.cpp
#include <iostream>
#include "Table.h"
Table::Table(Shoe shoe) : shoe(shoe) {
}
Shoe Table::getShoe() const {
return shoe;
}
void Table::clearHand(std::vector<Player> players) {
for (Player &player : players) {
player.getHand().clearHand();
}
}
void Table::dealHand(std::vector<Player> players) {
for (int i = 0; i <= 1; i++) {
for (Player &player : players) {
player.getHand().addCardToHand(shoe.dealCard());
}
}
}
// Player.h
#ifndef PLAYER_H
#define PLAYER_H
#include "Hand.h"
class Player {
private:
std::string name;
Hand hand;
double money;
public:
explicit Player(std::string name, double money = 1000.0);
std::string getName() const;
Hand getHand() const;
double getMoney() const;
};
#endif
// Player.cpp
#include "Player.h"
Player::Player(std::string name, double money) : name(name), money(money) {
}
std::string Player::getName() const {
return name;
}
Hand Player::getHand() const {
return hand;
}
double Player::getMoney() const {
return money;
}
and finally here is a short driver that runs and displays the issue
// blackjack testing
#include <iostream>
#include "Player.h"
#include "Table.h"
int main() {
std::vector<Player> players {Player("Tom",1500.0),Player("Sue"),Player("Dave")};
Shoe shoe1(6);
Table table1(shoe1);
table1.dealHand(players);
for (Player player : players) {
std::cout << player.getName() << "'s hand\n";
std::cout << player.getHand().showHand() << "\n\n";
}
}
The output is below. I printed out the cards that were added to the hand vector (and then 'forgotten') and below that above the XX's, if everything were to work correctly you should see the 4, 5 and 6 of spades since I did not shuffle the deck. The XX's are to simulate face down bottom card.
AS
2S
3S
4S
5S
6S
Tom's hand
XX
Sue's hand
XX
Dave's hand
XX
Sorry for dumping all this code in here, but I wanted to provide a full working solution and this is as small as I could get it. Thanks for any help.
player.getHand().addCardToHand(...);
player.getHand() returns a temporary Hand object that's a copy of player.hand. Then you add a card to that temporary object. Then that temporary object dies, added card and all. player.hand remains unchanged. This line of code is an elaborate no-op.
To add on #Igor's answer, the best way to fix this should probably return a reference instead:
const Hand& Player::getHand() const {
return hand;
}
I made this a const because returning a non-const could (potentially) allow you to break constness of a constant Player object. That is just inviting potential bugs.
Because of this, you may want to add a non-const version too:
Hand& Player::getHand() {
return hand;
}
Now you can't modify a const Player object, yet modify it properly when you need to.
Just started learn to code in school. Our assignment requires us to create a card game with card,deck and hand class. I am having troubles with it now and i keep getting exception: std::bad_alloc at memory location. Here are my codes right now
CardType h:
#ifndef cardType_h
#define cardType_h
#include <string>
using namespace std;
class cardType{
public:
void print();
int getValue() const;
string getSymbol() const;
string getSpecial() const;
string getSuit() const;
int checkSpecial(int gscore) const;
cardType();
cardType(string suit,int value);
private:
int value;
string special;
string symbol;
string suit;
};
#endif
CardType cpp:
#include "cardType.h"
#include <iostream>
#include <string>
using namespace std;
void cardType::print()
{
cout << getSymbol() << " of " << getSuit() << ", having the value of " << getValue() << "."<< endl <<"This card's special is " << getSpecial() << endl;
}
int cardType::getValue() const
{
return value;
}
string cardType::getSymbol() const
{
return symbol;
}
string cardType::getSpecial() const
{
return special;
}
string cardType::getSuit() const
{
return suit;
}
cardType::cardType(){
value=0;
symbol="?";
special='?';
suit='?';
}
cardType::cardType(string s, int v){
suit = s;
value = v;
switch(v){
case 1: // Ace cards have a value of 1 and have no special type
symbol="Ace";
special="None";
break;
case 2: // 2 cards have a value of 2 and have no special type
symbol="2";
special="None";
break;
case 3:
symbol="3"; // 3 cards have a value of 3 and have no special type
special="None";
break;
case 4:
symbol="4"; // 4 cards have a value of 0 and have a special type "Reverse" which reverses the flow of the game
special="Reverse";
value=0;
break;
case 5:
symbol="5"; // 5 cards have a value of 5 and have no special type
special="None";
break;
case 6:
symbol="6"; // 6 cards have a value of 6 and have no special type
special="None";
break;
case 7:
symbol="7"; // 7 cards have a value of 7 and have no special type
special="None";
break;
case 8:
symbol="8"; // 8 cards have a value of 8 and have no special type
special="None";
break;
case 9:
symbol="9"; // 9 cards have a value of 0 and have a special type "Pass" which does not add any value to the game and lets the player skip his turn.
special="Pass";
value=0;
break;
case 10:
symbol="10"; // 10 cards have a value of 10 and have a special type "subtract" which instead of adding the 10 value to the total game it is subtracted instead.
special="Subtract";
value=10;
break;
case 11: // Jack cards have a value of 10 and have no special type
symbol="Jack";
special="None";
value=10;
break;
case 12: // Queens cards have a value of 10 and have no special type
symbol="Queen";
special="None";
value=10;
break;
case 13:
symbol="King"; // King cards have a value of 0 and have a special type "NinetyNine" which changes the total game score to 99 reguardless what number it was previously
special="NinetyNine";
value=0;
break;
}
}
int cardType::checkSpecial(int gscore) const{
if(special=="Pass"){
return gscore;
}
if(special=="Reverse"){
return gscore;
}
if(special=="Subtract"){
return gscore - value;
}
if(special=="NinetyNine"){
return 99;
}
else{
return gscore + value;
}
}
DeckType h:
#ifndef deckType_h
#define deckType_h
#include "cardType.h"
#include <string>
using namespace std;
class deckType
{
public:
void shuffle();
cardType dealCard();
deckType();
private:
cardType *deck;
int current;
};
#endif
DeckType cpp:
#include <iostream>
#include "deckType.h"
using namespace std;
deckType::deckType()
{ int index = 0;
int current=0;
deck = new cardType[52];
string suit[] = {"Hearts","Diamonds","Clubs","Spades"};
int value[] = {1,2,3,4,5,6,7,8,9,10,11,12,13};
for ( int i = 0; i <= 3; i++ ) {
for ( int j = 1; j <= 13; j++ ) {
deck[index] = cardType(suit[i],value[j]);
index++;
}
}
}
cardType deckType::dealCard()
{
return deck[current];
current++;
}
Main cpp :
#include "deckType.h"
#include <iostream>
using namespace std;
int main()
{
deckType gamedeck;
cout << "1" <<endl;
cardType currentCard;
cout << "2" <<endl;
currentCard = gamedeck.dealCard();
cout << "3" <<endl;
return 0;
}
I keep getting bad_alloc at the currentCard = gamedeck.dealCard();
I really do not know what i have done wrong.
In the constructor, you should use string literals for strings:
cardType::cardType(){
value=0;
symbol="?";
special="?";
suit="?";
}
and current which is used in dealCard might not have been initialized.
deckType::deckType()
{ int index = 0;
int current=0;
deck = new cardType[52];
....
here, you initialize a local variable current, this hides the member current.
#drescherjm's comment is very important:
for ( int j = 1; j <= 13; j++ ) { That can't work. Remember c++
indexes start at 0.
in my school assignment i need a small help
this is my header file:
#include <iostream>
#include <cstring>
using namespace std;
#include "ISBNPrefix.h"
class ISBN
{
char str[11];
char area[6];
char publisher[8];
char title[7];
bool registered;
public:
ISBN();
ISBN(const char*,ISBNPrefix &);
void toStr(char*)const;
void toStrWithStyle(char*)const;
bool empty()const;
bool isRegistered() const;
bool read(istream& is, const ISBNPrefix& list);
void display(ostream&) const;
};
int isValid(const char* str);
and this is the implementation of my file:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include <iomanip>
using namespace std;
#include "ISBN.h"
ISBN::ISBN()
{
str[0]='\0';
area[0]='\0';
publisher[0]='\0';
title[0]='\0';
registered=false;
}
ISBN::ISBN(const char* s,ISBNPrefix& p)
{
if(isValid(s)==1)
{
strcpy_s(str,s);
}
else
{
*this=ISBN();
}
}
bool ISBN::empty()const
{
bool chk=false;
if(str[0]=='\0')
chk=true;
return chk;
}
void ISBN::toStrWithStyle(char* s) const
{
if(registered)
{
sprintf(s,"%s-%s-%s-%c",area,publisher,title,str[9]);
}
else
{
toStr(s);
}
}
void ISBN::toStr(char* s) const
{
if (str[0]!='\0')
strcpy(s,str);
else
strcpy(s,"no data");
}
void ISBN::display(ostream & os) const
{
char str[14];
toStrWithStyle(str);
cout<< setw (13) <<str;
}
int isValid(const char* str)
{
int rc=0;
if(str!=0)
{
int sum,i=0;
sum=0;
for(i=0;i<10;i++)
sum+=(str[i]-'0')*(10-i);
if(sum%11==0)
{
rc= 1;
}
}
else
rc=0;
return rc;
}
bool ISBN::read(istream& is, const ISBNPrefix& list)
{
char str[11];
bool quit=false;
bool ok=false;
char lists;
do{
cout<<"ISBN (0 to quit) : ";
is.getline(str,11); //or is.get(str,11)
if(strcmp(str,"0")==0)
quit=true;
else if (isValid(str)==1)
{
*this=ISBN(str,list);
ok=true;
cout<<"isbn is valid"<<endl;
}
else
{
*this=ISBN();
cout<<"invalid ISBN"<<endl;
}
} while(!quit&&!ok);
return !quit;
}
in the ISBN::read where I say
*this=ISBN(str,list);
i want to overload another member but i can't.
can anyone tell me how can i do that?
First I would suggest use std::string in favour of char[]. It will save a lot of trouble. For reading ISBN I would write something like this:
bool ISBN::read(istream& is)
{
ISBN result;
// reading into result
std::swap(*this,result);
return !quit;
}
Or even better (as a non member function):
std::istream& operator>>(istream& is, ISBN& obj)
{
ISBN result;
// reading into result
is(!quit)
is.clear(std::ios_base::failbit);
std::swap(obj,result);
return is;
}
In any way you should RAII classes for your resources. In your special case std::string instead of char[].