Switch statement will NOT print a string - c++

char gamerCentral::getGamerTag( )
{
switch(gamerTag)
{
case '1': return gamerTag = "Diamond";
break;
case '2': return gamerTag = "Silver";
break;
case '3': return gamerTag = "Bronze";
break;
case '4': return gamerTag = "Wood";
break;
default: return gamerTag = "Uninstall";
break;
}
char gamerTag;
GamerClub::GamerClub(
char tag)
{
gamerTag = tag;
}
I'm trying to return the gamerTag, but it says that it cannot convert to a string. Is their a way to convert the char to a string inside the switch statement?

Have your function return a string, it can still operate on the single character as input. Here's an example.
std::string getGamerTag(char t)
{
switch(t)
{
case '1': return "Diamond";
case '2': return "Silver";
// ...
}
return "";
}
// prints "Silver"
cout << getGamerTag('2');

use string variable or use char*
char* getGamerTag(int t)
{
switch(t)
{
case 1: return "Diamond";
case 2: return "Silver";
}
}
int main()
{
cout << getGamerTag(2);
}

I recommend using an array of strings:
std::string getGamerTag(unsigned int t)
{
static const char * tag_names[] =
{
"Diamond", "Silver", "Bronze", "Wood", "Unistall",
};
static const unsigned int name_quantity =
sizeof(tag_names) / sizeof(tag_names[0]);
std::string name;
if ((t > 0) && (t <= name_quantity))
{
name = tag_names[t - 1];
}
return name;
}

Related

The C++ Programming Language 4th edition A desk calculator return ct={Kind::name;} the output is wrong when i input pi

when i copy the code from the book The C++ Programming Language Fourth Edition ,Bjarne Stroustrup
I found out that when i input a pi(which has been defined in the code) the output is wrong
so i spent 1 day to find out the problem. i just share it
#include<iostream>
#include<map>
#include<string>
#include<sstream>
#include<cctype>
enum class Kind:char{
name,number,end,
plus='+',minus='-',mul='*',div='/',print=';',assign='=',lp='(',rp=')'
};
struct Token{
Kind kind;
std::string string_value;
double number_value;
};
int no_of_errors;
double error(const std::string& s)
{
no_of_errors++;
std::cerr<<"error: "<<s<<'\n';
return 1;
}
std::map<std::string,double> table;
double expr(bool get);
double term(bool get);
double prim(bool get);
class Token_stream{
public:
Token_stream(std::istream& s):ip{&s},owns{false}{}
Token_stream(std::istream* p):ip{p},owns{true}{}
~Token_stream(){close();}
Token get();
Token& current(){return ct;}
void set_input(std::istream& s){close();ip=&s;owns=false;}
void set_input(std::istream* p){close();ip=p;owns=true;}
private:
void close(){if(owns) delete ip;}
std::istream* ip;
bool owns;
Token ct{Kind::end};
};
Token_stream ts{std::cin};
//Token& Token_stream::current()
//{
// return ct;
//}
Token Token_stream::get()
{
char ch;
do{
if(!ip->get(ch)){
return ct={Kind::end};
}
}while(ch!='\n' && std::isspace(ch));
switch(ch){
case ';':
case '\n':
return ct={Kind::print};
case '*':
case '/':
case '+':
case '-':
case '(':
case ')':
case '=':
return ct={static_cast<Kind>(ch)};
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '.':{
ip->putback(ch);
*ip>>ct.number_value;
ct.kind=Kind::number;
return ct;
}
default:
if(std::isalpha(ch)){
ct.string_value = ch;
while(ip->get(ch) && std::isalnum(ch)){
ct.string_value +=ch;
}
//test
//std::cout<<ts.current().string_value<<'\n';
//std::cout<<table[ct.string_value]<<'\n';
ip->putback(ch);
return ct={Kind::name,ct.string_value};
}
error("bad token");
return ct={Kind::print};
}
}
double expr(bool get)
{
//test
// std::cout<<ts.current().string_value<<'\n';
// std::cout<<table[ts.current().string_value]<<'\n';
double left=term(get);
for(;;){
switch(ts.current().kind){
case Kind::plus:
left += term(true);
break;
case Kind::minus:
left-= term(true);
break;
default:
return left;
}
}
}
double term(bool get)
{
double left = prim(get);
for(;;){
switch(ts.current().kind){
case Kind::mul:
left *= prim(true);
break;
case Kind::div:
if(auto d = prim(true)){
left /= d;
break;
}
return error("divide by 0");
default:
return left;
}
}
}
double prim(bool get)
{
if(get){
ts.get();
}
switch(ts.current().kind){
case Kind::number:
{
double v=ts.current().number_value;
ts.get();
return v;
}
case Kind::name:
{
//test
//std::cout<<ts.current().string_value<<'\n';
double& v=table[ts.current().string_value];
//std::cout<<table[ts.current().string_value]<<'\n';
if(ts.get().kind == Kind::assign){
v=expr(true);
}
//std::cout<<ts.current().string_value<<'\n';
//std::cout<<v<<'\n';
//std::cout<<table[ts.current().string_value]<<'\n';
return v;
}
case Kind::lp:
{
auto e = expr(true);
if(ts.current().kind!=Kind::rp){
return error("')' expected");
}
void(ts.get());
return e;
}
default:
return error("primary expected");
}
}
void calculate()
{
for(;;){
ts.get();
//test
//if(ts.current().kind != Kind::number){
// std::cout<<"number"<<'\n';
//}
if(ts.current().kind == Kind::end)break;
if(ts.current().kind == Kind::print)continue;
std::cout<<expr(false)<<'\n';
}
}
int main(int arg,char* argv[])
{
switch(arg){
case 1:
break;
case 2:
ts.set_input(new std::istringstream{argv[1]});
break;
default:
error("too many arguments");
return 1;
}
table["pi"] = 3.1415926535897932385;
table["e"] = 2.7182818284590452354;
calculate();
return no_of_errors;
}
233,1 Bot
the most important for correct the error is as follows:
//in member function Token Token_stream::get()
//old code:
return ct={Kind::name;}
we should change the code like this:
//in member function Token Token_stream::get()
//new code:
return ct={Kind::name,ct.string_value}

Parsing a file to assign variables to strucuture. C++

Here is my code, I'm genuinely interested how far off I am.
bool characterGetCFG(char typeOverLoad, string var_name, string full_text)
{
int pos = full_text.find(var_name) + 1;
if (full_text.at(pos) == *"t") {
cout << "returned " << full_text.at(pos) << "\n";
return true;
}
else
{
return false;
}
}
int characterGetCFG(int typeOverLoad, string var_name, string full_text)
{
int pos = full_text.find(var_name) + var_name.length() + 1;
cout << "returned " << full_text.at(pos) << "\n";
return full_text.at(pos);
}
features setconfig(features featstruct)
{
features config; //BOOL/BOOL/BOOL/BOOL/INT[2]/BOOL/INT
ifstream file;
file.open("config.cfg");
if (!file.is_open()) {
exit(-1);
}
string raw;
while (file.good()) {
file >> raw;
}
for (int x = 0; x < 11; x++) {
switch (x) {
case 1:
config.var1 = characterGetCFG('t', "var1", raw);
case 2:
config.var2 = characterGetCFG('t', "var2", raw);
case 3:
config.var3 = characterGetCFG('t', "var3", raw);
case 4:
config.var4 = characterGetCFG('t', "var4", raw);
case 5:
config.var5[1] = characterGetCFG(136, "var51", raw); //min
case 6:
config.var6[2] = characterGetCFG(542, "var62", raw); //max
case 7:
config.var7 = characterGetCFG('t', "var7", raw);
case 8:
config.var8 = characterGetCFG('t', "var8", raw);
case 9:
config.var9 = characterGetCFG('t', "var9", raw);
case 10:
config.var10 = characterGetCFG('t', "var10", raw);
case 11:
config.var11 = characterGetCFG('t', "var11", raw);
}
}
file.close();
return config;
}
And here is my text/cfg file I am using
var1=false
var2=false
var3=true
var4=false
var51=2
var62=7
var7=true
var8=t
var9=true
var10=true
var11=true
Here is what I am getting returned when I print what I am returning to console
As you can see it does not reflect how many times I iterate through the loop, so at the end of the day I'm stumped.

Why does my check not work in checking for duplicated results( pointers)

int main()
{ srand(time(NULL));
Card c;
Card *Pc;
Pc = new Card [52];
Card ** someHands;
// typedef Card * Hand;
// Hand *someHands;
CardtoArray(c,Pc);
printDeckofCards(Pc,c);
}
Card GenerateCards(Card c)
{
int CardNum;
CardNum=rand() % 13 + 1;
int colour =rand() % 4 + 1;
switch(CardNum)
{
case 1: c.rank= Ace;
break;
case 2: c.rank= Two;
break;
case 3: c.rank= Three;
break;
case 4: c.rank= Four;
break;
case 5: c.rank= Five;
break;
case 6: c.rank= Six;
break;
case 7: c.rank= Seven;
break;
case 8: c.rank= Eight;
break;
case 9: c.rank= Nine;
break;
case 10: c.rank= Ten;
break;
case 11: c.rank= Jack;
break;
case 12: c.rank= Queen;
break;
case 13: c.rank= King;
break;
}
switch(colour)
{
case 1:c.color="Diamond";
break;
case 2:c.color="Club";
break;
case 3:c.color="Heart";
break;
case 4:c.color="Spade";
break;
}
return c;
}
//prints a single card this function is to be call into the function //printsdeckofcards
void printCard(Card c)
{
cout<<*c.color;
if(c.rank==Ace)
cout<<"A";
else if(c.rank==Two)
cout<<"2";
else if(c.rank==Three)
cout<<"3";
else if(c.rank==Four)
cout<<"4";
else if(c.rank==Five)
cout<<"5";
else if(c.rank==Six)
cout<<"6";
else if(c.rank==Seven)
cout<<"7";
else if(c.rank==Eight)
cout<<"8";
else if(c.rank==Nine)
cout<<"9";
else if(c.rank==Ten)
cout<<"10";
else if(c.rank==Jack)
cout<<"J";
else if(c.rank==Queen)
cout<<"Q";
else if(c.rank==King)
cout<<"K";
}
//generate and inserts 52 cards it also calls the function samecard to check if
//duplicated cards have been generated and if so regenerates a new one before //inserting into the array
void CardtoArray(Card &c,Card *Pc)
{
Card *origin;
origin=Pc;
for( int i=0;i<52;i++)
{
c=GenerateCards(c);
if(SameCard(c,origin)==false)
{
*Pc=c;
Pc++;
}
else
i--;
}
}
void printDeckofCards(Card *Pc,Card c)
{
for( int i=0;i<52;i++)
{
printCard(*Pc);
cout<<" ";
Pc++;
}
}
bool SameCard(Card c,Card *Pc)
{ bool check;
for(int i=0; i<52; i++)
{
if(Pc->color==c.color && Pc->rank==c.rank)
{
check = true;
}
else
{
check = false;
}
Pc++;
}
return check;
}
Blockquote
Because you are checking ALL cards, your boolean must be set to false before the loop and is set to true in the loop; it should not be set to false again in the loop:
bool SameCard(Card c,Card *Pc)
{ bool check= false;
for(int i=0; i<52; i++)
{
if(Pc->color==c.color && Pc->rank==c.rank)
{
check = true;
}
//else
///{
// check = false;
//}
Pc++;
}
return check;
}
or even:
bool SameCard(Card c,Card *Pc)
{
for(int i=0; i<52; i++, pc++)
if(Pc->color==c.color && Pc->rank==c.rank)
return true;
return false;
}

C++ ERROR: C2280- compiler error that references deleted function?

I am very new to C++ and am attempting to create a simple calculator which follows mathematical conventions (BODMAS or PEMDAS). I made a function calculator, but then decided to go further and accept variables, at which point I kept receiving C2280 error.
The error is:
token_stream::token_stream(void): attempting to reference a deleted function
I simply dont understand what this means and have no idea what to do to fix it.
Here is the token_stream class:
class token_stream { //creates a stream of tokens
public:
Token get(); //call to get token function
void putback(Token t); //call to token putback function
void ignore(char a); // call to ignore bad tokens function
private:
bool full{ false }; //is there a token in the buffer?
Token buffer; //this is where putback token is stored
};
Here is the entire calculator code:
#include "../../std_lib_facilities.h"
//---------------------------------------------------------------------------------------------------
class Token //user defined type with two member functions
{
public:
char kind;
double value;
string name;
Token(char ch) : kind{ ch } {} //initialize kind with ch
Token(char ch, double val) : kind{ ch }, value{ val } {} //initialize kind and value
Token(char ch, string name) : kind{ ch }, name{ name } {} //initialize kind and name
};
class token_stream { //creates a stream of tokens
public:
Token get(); //call to get token function
void putback(Token t); //call to token putback function
void ignore(char a); // call to ignore bad tokens function
private:
bool full{ false }; //is there a token in the buffer?
Token buffer; //this is where putback token is stored
};
class Variable {
public:
string name;
double val;
};
//---------------------------------------------------------------------------------------------------
const char number = '8'; //t.kind==number means that t is a number token
const char quit = 'q'; //t.kind==quit means that t is a quit token
const char print = ';'; //t.kind==print means that t is a print token
const char name = 'a';
const char let = 'L';
const string declr_key = "let";
vector<Variable> var_table;
token_stream ts;
//---------------------------------------------------------------------------------------------------
void token_stream::putback(Token t) {
if (full) error("putback() is full"); //tests precondition to see if buffer is full
buffer = t;
full = true;
}
void token_stream::ignore(char c) {
if (full && c == buffer.kind) {
full = false;
return;
}
char ch{ 0 };
while (cin >> ch) {
if (c == ch)
return;
}
}
Token token_stream::get() { //creates a token from inputs
if (full) { //checks if we have a token ready
full = false;
return buffer;
}
char ch;
cin >> ch;
switch (ch) {
case print:
case quit:
case '(':
case ')':
case '+':
case '-':
case '*':
case '/':
case '%':
return Token{ ch }; break; //let each character represent itself
case '.': // floatng point literal can start with a dot
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
{
cin.putback(ch); //putback the digit into input stream
double val;
cin >> val; //read a floating point number
Token t{ number,val };
return t;
break;
}
default:
if (isalpha(ch)) {
string s;
s += ch;
while (cin.get(ch) && (isalpha(ch) || isdigit(ch))) s += ch;
cin.putback(ch);
if (s == declr_key) return Token{ let };
return Token{ name, s };
}
error("Error in Input: Token Invalid"); break;
}
}
double get_value(string s) { //gets the value for a given variable
for (int i = 0; i < var_table.size(); i++)
if (s == var_table[i].name) return var_table[i].val;
error("Undefined variable: ", s);
}
void set_value(string s,double d) { // sets the value for a pre-defined variable
for (int i = 0; i < var_table.size(); i++)
if (s == var_table[i].name) {
var_table[i].val = d;
return;
}
error("Undefined variable: ", s);
}
//---------------------------------------------------------------------------------------------------
double primary(); //declaration so that term can call primary()
double term() { //does multiplication, division, and modulo
double left = primary();
Token t = ts.get();
while (true)
{
switch (t.kind) {
case '*':
{
left *= primary();
t = ts.get();
break;
}
case '/': {
double d = primary();
if (d == 0) error("Divide by 0!"); //non-zero denom check
else {
left /= d;
t = ts.get();
}
break;
}
case '%': {
double d = primary();
if (d == 0)error("Divide by 0!"); //non-zero denom check
else {
left = fmod(left, d);
t = ts.get();
}
break;
}
default: ts.putback(t); //put back in token strem if none of the other options
return left; break;
}
}
}
double expression() { //handles +, -
double left = term();
Token t = ts.get();
while (true) {
switch (t.kind) {
case '+':
{
left += term();
t = ts.get();
break; }
case '-': {
left -= term();
t = ts.get();
break; }
default: ts.putback(t); //put back into token stream if none of the options above
return left;
break;
}
}
}
double primary() {
Token t = ts.get();
switch (t.kind) {
case '(':
{
double d = expression();
t = ts.get();
if (t.kind != ')') error("Expected a ')'");
return d;
break;
}
case number:
return t.value;
break;
case '-': //handles negative numbers
return - primary();
break;
case '+': //handles positive numbers which are preceded by '+'
return primary();
break;
default: error("primary expected: no value after operator given. check input");
}
}
void check_var(string name) {
for (int i = 0; i < var_table.size(); i++)
if (name == var_table[i].name)
error("Variable name already exists");
}
double define_name(string name, double num) {
check_var(name);
var_table.push_back(Variable{ name, num });
return num;
}
double declaration() {
// assume we have seen a 'let'
// handles: name=expression
// declare a variable called 'name' with value 'val'
Token t = ts.get();
if (t.kind != name) error("Expected a variable name"); //throws an error if no variable name given
string var_name = t.name;
t = ts.get();
if (t.kind != '=')error("No '=' sign present in declaration of ", var_name);
double d = expression();
define_name(var_name, d);
return d;
}
double statement() {
Token t = ts.get();
switch (t.kind) {
case let:
return declaration();
default:
ts.putback(t);
return expression();
}
}
void clean_up_mess() {
ts.ignore(print);
}
void calculate() { //expression evaluation loop
while (cin)
{
try {
Token t = ts.get();
if (t.kind == print) t = ts.get(); //first discard all 'prints'
if (t.kind == quit) {
return;
}
ts.putback(t);
cout << "Answer: " << statement() << "\n";
}
catch (exception&e) {
cout << "Error: " << e.what() << "\n";
clean_up_mess();
}
}
}
//---------------------------------------------------------------------------------------------------
int main()
{
try {
cout << "Enter an expression to solve: \n"; //user prompt
calculate();
keep_window_open();
}
catch(...) {
cout << "Error of Unknown origin.\n";
}
}
Any help is really appreciated!
As Token doesn't have a default constructor (a constructor which can be called without any parameters), and token_stream contains Token, the compiler cannot generate default constructor for token_stream.
Two possible solutions:
Add a default constructor to Token
Add a default constructor to token_stream, which initializes buffer to some value

C++ program parser

We are required to parse out a given program code. Example of code:
procedure example1 {
x = 0;
z = y + x;
a =1;
while a{
x = z + x;
while x {
c = a + b;
}
}
}
What I have tried:
The example code is in a text file, so i open it and then i pass the info to a vector, after which, i get the tokens from the vector one by one and analyse it looking for the keyword. Currently, my code keeps displaying the error message in the Error method, and i can't see to understand why. This is a school assignment. My code is given below. Any and all help is appreciated.
vector<string> tokens;
SimpleParser::SimpleParser()
{
cout << "Please enter a file name: ";
cin >> userInput;
cout << "fILENAME: " + userInput;
openFile(userInput);
}
SimpleParser::~SimpleParser()
{
}
void SimpleParser::openFile(string fileName) {
ifstream myfile(fileName);
if (myfile.is_open())
{
while (getline(myfile, currLine))
{
size_t comments = currLine.find("//");
if (comments != string::npos)
{
currLine = currLine.erase(comments);
allLines += " " + currLine;
}
else {
allLines += " " + currLine;
}
}
myfile.close();
fillVector(allLines);
}
else
{
cout << "Unable to open file";
}
}
//check if line is proc, while,assign
void SimpleParser::fillVector(string line) {
istringstream iss(line);
copy(istream_iterator<string>(iss),
istream_iterator<string>(),
back_inserter(tokens));
next_token = getToken();
procedure();
}
void SimpleParser::procedure() {
Match("procedure");
//string proc_name = next_token;
//Match(proc_name);
Match("{");
stmtLst();
Match("}");
}
void SimpleParser::stmtLst() {
cout << "All lines : "+ allLines;
}
void SimpleParser::Match(string token) {
if (next_token.compare(token) == 0) {
next_token = getToken();
}
else {
Error();
}
}
string SimpleParser::getToken() {
string t = "";
if (countOfVecs < tokens.size()) {
t = tokens[countOfVecs];
}
countOfVecs++;
return t;
}
void SimpleParser::Error() {
cout << "Error parsing!";
//exit(0);
}
void SimpleParser::Stmt() {
string var_name = next_token;
Match(var_name);
Match("=");
Match(next_token);
}
As I can see, the problem is related either to your get or your:
void SimpleParser::Match(string token) {
// compare token with next_token
if (next_token.compare(token) == 0){
// if they match assign next_token to the next token
next_token = getToken();
}else{
// if they don't compare equal throw an error
Error();
}
}
What exactly is the purpose of the above function?
In general there is no need to waste so much memory and read all the file, you can parse it word by word till you get the needed key word. Thus, here is a slightly different implementation of class that will actually parse without copying all the file contents.
class Token{
public:
// data members for the three types of tokens:
// algebraic operator, number, and user defined variable(name, value)
char kind;
double value;
string name;
// constructors for each of the three tokens
Token(char ch): kind(ch), value(0) { }
Token(char ch, double val) :kind(ch), value(val) { }
Token(char ch, string n) :kind(ch), name(n) { }
};
// class used as an input stream for tokens
class Token_stream {
public:
// constructor
Token_stream() :full(false), buffer(0) { }
// member functions
Token get();
private:
// data members defining the Token_stream buffer
bool full;
Token buffer;
};
const string firstKeyword = "key1";
// get function implementation
Token Token_stream::get(){
if (full) {
full=false;
return buffer;
}
char ch;
// to read from file change cin to the relevant input stream object
cin.get(ch);
switch (ch){
// if the token some of the above symbols: return it
case '(': case ')': case '+': case '-': case ',': case '!':
case '*': case '/': case '%': case 'Q': case '=':
return Token(ch);
// if the token a number int of float: return it as "number token"
case '.':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
{
cin.putback(ch);
double val;
cin >> val;
return Token(number,val);
}
case '\n': case '\r':
return Token(print);
default:
{
if (isspace(ch)) // skips whitespaces; taking up this funciton from the replaced 'cin'
{
while(isspace(ch)) cin.get(ch);
}
if (isalpha(ch) || ch == '_' || ch == '#') {
string s;
s += ch;
while(cin.get(ch) && (isalpha(ch) || isdigit(ch) || ch == '_' || ch == '#')) s += ch;
cin.putback(ch);
// if the token is some of the predefined "Keywords": return it as the respective token
if (s == firstKeyword) return Token(keyToken);
if (s == secondKeyword) return Token(sekondKeyToken);
if (s == thirdKeyword) return Token(thirdKeyToken);
return Token(name,s);
}
error("bad input token!", ch);
}
}
}