Using object when out of scope? - c++

I'm working on a school assignment require to create a char LinkedList from user string input based on a menu of options:
Enter new string and store as linked list character of in an LinkedList class.
Get current length from the LinkedList.
Find index of character in this linked list.
Append another LinkedList to this LinkedList.
I have everything working fine, but now I'm stuck at the menu option part.
So let's say I choose option 1 to enter a string, and then I decide to use that object for case 2 and 3 to get the size and find index. That would not work because the object will be destroyed when out of scope. Is there any proper way that I can use to implement this ?
Simple Code Below
switch(option){
case 1:
LinkedList ls1(getInput());
ls1.printList();
break;
}
case 2:
cout << "Size of LinkedList: " <<ls1.getSize() << endl; //wouldn't work because ls1 got destroyed when out of scope.
}

If you want to expand the scope of an object, you declare it at a higher scope. You probably have a while loop asking for input, and then switching on that input? If you want your LinkedList to survive successive iterations of the loop, you'll need to declare it before the loop starts.
LinkedList ls1; // required default constructor
int option = 3;
do
{
std::cout << "Enter 1 to create new list. 2 to print current list. 3 to quit: ";
std::cin >> option;
switch(option)
{
case 1:
ls1 = getInput(); // requires conversion from getInput()'s return type and copy (or preferably move) assignment operators
ls1.printList();
break;
case 2:
std::cout << "Size of LinkedList: " <<ls1.getSize() << std::endl;
break;
}
} while(option != 3);

Try to initiate the object outside the switch statement and after that you could use that object within any switch case.
Example:
ClassName ObjectName(getInput());
switch(option){
case 1: ObjectName.printList();
break;
case 2: cout << "Size of LinkedList: " <<ObjectName.getSize() << endl;
break;
default: break;
}

Declare the object outside the switch statement.
LinkedList ls1(getInput());
switch(option){
case 1:
ls1.printList();
break;
case 2:
cout << "Size of LinkedList: " <<ls1.getSize() << endl;
break;
default:
break;
}

Related

C++ vector push_back function

So I am pretty new to coding and am having some issues with storing user input into a vector using the push_back function. can some one tell me what I am doing wrong?
vector<int> user_nums;
switch(selection){
case 'P':
case 'p':
if(user_nums.empty()){
cout << "[]- list is empty" << endl;
}else{
for(auto nums: user_nums)
cout <<"[ " << nums << " ]" << endl;
}
break;
case 'A':
case 'a':
int new_num;
cout << "\nEnter a number you would like to add: ";
cin >> new_num;
user_nums.push_back(new_num);
cout << new_num << " was added" << endl;
break;
This is in a do while loop. The code executes just fine, the problem is when I prompt the user to add a new number the value does not store in the vector. So when the user makes the selection to print the numbers, the list still shows empty.
So, you're missing the most relevant sections of your code here. You should really be posting a minimal, reproducible example. Often the process of creating one will cause you to find your problem.
In this case though, it's obvious enough. There's a loop wrapping all this code. The vector is declared inside the loop. That means, at the bottom of the loop the vector will be destroyed, and then as the loop is executed again, a new empty vector will be created.
The solution is to move the declaration of the vector outside the loop.
If I've guessed wrong about the structure of the code you haven't shown us, then please follow the guideline I linked to above.

Is there a way to declare objects within a conditional statement?

I'm having trouble figuring out how to properly create an object depending on the user's choice.
In the program, I ask the user which they class they want to be--Knight or Wizard. I take input '1' or '2' to represent Knight and Wizard.
I made a switch statement, and within case 1, I declared an object Knight, and the same for Wizard.
I need to use these objects outside of the switch statement, but I can't. I tried to make a 'default' object by making 'Player player;' but because the Player class has a pure virtual function, I can't do that either.
How do I do this effectively?
This is what I have so far:
int main()
{
std::string plyrName;
int input;
bool foo = false;
std::cout << "What is your name?\n";
std::cin >> plyrName;
std::cin.ignore(1000, '\n');
std::cout << "\nWelcome, " << plyrName << ". What class would you like to be?\n";
std::cout << "1. Knight.\n2. Wizard.\n";
std::cin >> input;
while (input != 1 && input != 2)
{
if (foo == true)
std::cout << "Please enter 1 for Knight and 2 for Wizard.\n";
if (!(std::cin >> input))
{
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "\n";
std::cout << "Only integers are allowed.\n";
}
else
std::cout << "\n";
foo = true;
}
switch (input)
{
case 1:
{
Wizard player;
break;
}
case 2:
{
Knight player;
break;
}
}
std::cout << "\nHere is your player information summary.\n";
std::cout << player.classType();
system("pause");
return 0;
}
I need to access the player object after is has been created, because I want to output to the user which class they selected. Both Knight and Wizard classes have a function to output this.
EDIT: I have a follow up question. In the diagram, Knight & Wizard have a static variable 'special attack name'. How can I access this variable in the main function? The solution of using unique_ptr means that the pointer will point to the base class Player, thus not allowing access to the derived class members such as the static variable 'special attack name'. Do I have a flaw in my design?
In your case, because you want to accomplish polymorphism, you should go for pointers and references. Why? I would highly recommend this beautiful answer. Why doesn't polymorphism work without pointers/references?
So, should you go for a raw pointer, something like Player *?
In almost all scenarios, you should never ever go for raw pointers and especially, when it points to dynamic memory. Simply because any programming error or an exception might lead to delete getting skipped.
Therefore, I would highly recommend you to go for smart pointers introduced in C++11 like unique_ptr and shared_ptr which follow RAII pattern and guarantee deinitialization.
Here is an example of usage of unique_ptr in your case.
#include <memory>
using PlayerPtr = std::unique_ptr<Player>;
using KnightPtr = std::unique_ptr<Knight>;
using WizardPtr = std::unique_ptr<Wizard>;
int main()
{
...
PlayerPtr playerPtr = nullptr;
switch (input) {
case 1: {
playerPtr = KnightPtr(new Knight);
}
break;
case 2: {
playerPtr = WizardPtr(new Wizard);
}
break;
}
// use playerPtr outside.
}
Edit:
As rightly pointed out by HTNW, you must go for std::make_unique instead of using new. But remember, that is a C++14 concept. You must have compiler support for it.
if you create your variable inside the switch case scope it will get deleted as soon as you leave that scope leading you to UB so you declare it as a pointer so it can outlive the conditional statement ie : you declare it as the base class pointer before & you give it to where it points inside conditional statement
#include<memory>
int main()
{
std::string plyrName;
int input;
bool foo = false;
//create your player ptr
std::unique_ptr<Game_Object> player;
std::cout << "What is your name?\n";
std::cin >> plyrName;
std::cin.ignore(1000, '\n');
std::cout << "\nWelcome, " << plyrName << ". What class would you like to be?\n";
std::cout << "1. Knight.\n2. Wizard.\n";
std::cin >> input;
while (input != 1 && input != 2)
{
if (foo == true)
std::cout << "Please enter 1 for Knight and 2 for Wizard.\n";
if (!(std::cin >> input))
{
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "\n";
std::cout << "Only integers are allowed.\n";
}
else
std::cout << "\n";
foo = true;
}
switch (input)
{
case 1:
{ // initialize it and it would work perfectly as you intend
player = std::make_unique<WIZARD>();
break;
}
case 2:
{ //****
player = std::make_unique<KNIGHT>();
break;
}
}
std::cout << "\nHere is your player information summary.\n";
std::cout << player->classType();
system("pause");
return 0;
}
Someone correct me if I'm wrong, but objects are only valid within the scope they are created so once you are out of that switch statement those objects are not accessible anymore.
You should declare a GAME OBJECT class object outside the switch statement and then create either the wizard or the knight (as both classes inherit GAME OBJECT).

classes and creating multiple objects in C++

I've written a program for my C++ class and I ran into a little problem which I'm not quite sure how to solve. Some of you may be familiar with this textbook exercise as I've seen questions asked about it on the site before, but I was unable to find any simple fix.
I have to create a class which is used to store information about a pizza. I've got the program written and functional, but I need the class call to loop through a series of iterations based on the user's input. I know that this can be achieved using vectors, something we haven't hit yet in the semester, but will get to soon enough I'm sure. Is there a way to do this without vectors?
Here's the class.
class Pizza
{
private:
int type;
int size;
int numCheeseTopping;
int numPepperoniTopping;
bool cheeseTopping;
bool pepperoniTopping;
public:
Pizza();
int getType();
int getSize();
bool getCheese();
bool getPepperoni();
void setType(int t);
void setSize(int s);
void setCheese(bool choice, int temp);
void setPepperoni(bool choice, int temp);
void outputDescription();
double computePrice();
void outputPrice();
};
And the constructor.
Pizza::Pizza()
{
// Set initial class values
type = DEEPDISH;
size = SMALL;
cheeseTopping = false;
numCheeseTopping = 0;
pepperoniTopping = false;
numPepperoniTopping = 0;
}
Main is only two functions.
// Main function
int main()
{
// Call global functions
welcomeMsg();
buildPizza();
return 0;
}
I have a feeling that my problem lies in the buildPizza function, as it calls other functions as well as creating the objects. Here it is...
void buildPizza()
{
char pType, pSize, tempCheese, tempPepperoni;
int type = 0, size = 0, numCheeseTopping = 0, numPepperoniTopping = 0;
// Ask user what size pizza they would like.
cout << "What size pizza would you like?" << endl;
cout << "\tS: Small" << endl;
cout << "\tM: Medium" << endl;
cout << "\tL: Large" << endl;
cout << "Size: ";
cin >> pSize;
// Determine which size the user input and convert the
// result.
switch (pSize)
{
case 'S':
case 's':
size = SMALL;
break;
case 'M':
case 'm':
size = MEDIUM;
break;
case 'L':
case 'l':
size = LARGE;
break;
}
// Ask the user which type of pizza they would like.
cout << endl << "What type pizza would you like?" << endl;
cout << "\tD: Deepdish" << endl;
cout << "\tH: Hand-Tossed" << endl;
cout << "\tP: Pan" << endl;
cout << "Type: ";
cin >> pType;
// Determine which type the user input and convert the
// result.
switch (pType)
{
case 'D':
case 'd':
type = DEEPDISH;
break;
case 'H':
case 'h':
type = HANDTOSSED;
break;
case 'P':
case 'p':
type = PAN;
break;
}
// Call Pizza Class.
Pizza myPizza;
// Call Pizza Class functions.
myPizza.setSize(size);
myPizza.setType(type);
// Ask user whether they want cheese or not.
cout << endl << "Would you like cheese (y/n)? ";
cin >> tempCheese;
// If so call setCheese.
if (tempCheese == 'Y' || tempCheese == 'y')
{
cout << "How many cheese toppings would you like? ";
cin >> numCheeseTopping;
myPizza.setCheese(true, numCheeseTopping);
}
// Ask user whether they want pepperoni or not.
cout << endl << "Would you like pepperoni (y/n)? ";
cin >> tempPepperoni;
// If so call setPepperoni.
if (tempPepperoni == 'Y' || tempPepperoni == 'y')
{
cout << "How many pepperoni toppings would you like? ";
cin >> numPepperoniTopping;
myPizza.setPepperoni(true, numPepperoniTopping);
}
// Call outputDescription to give user an overview
// of their order.
cout << endl << endl;
myPizza.outputDescription();
cout << endl;
// Compute the cost of the pizza and display it.
myPizza.outputPrice();
}
Basically, I'd like the program to ask the user how many pizzas they would like to evaluate, create that many class iterations, then cycle through 'building' or 'ordering' each pizza, then display a total and return 0.
As I look at the code now I can take the last two function calls out of buildPizza and move the calls into main, but this will not solve my problem. Only an oversight I literally just noticed within the program.
Is there an easy way to create, say, 200 new objects all at once at runtime. Each one with a different name? Should I just pick a number to evaluate and force the user to enter information for that many objects? Right now, the program evaluates one pizza and quits.
I'd like something like this to happen:
User asks program to create a 5 pizza order.
Program creates 5 pizza objects.
Program iterates through each object getting and setting information for each one.
Program displays some stuff and returns 0.
Is this possible with my code, or do I need to consider a rewrite? Any guidance the community can give me will be immensely helpful.
Thanks.
Kyle
Since you cnanot use arrays or vectors, a simple for would suffice.
auto nrPizzas = getNumberOfPizzasFromUserInput();
for(int i = 0; i < nrPizzas; i++) {
auto pizza = Pizza{};
// do your stuff here.
output to the screen here();
}
You can prompt for the number of pizzas user want and then create a dynamic array of that much pizzas and then iterate through their build function or else you can make a linked-list with struct type of pizza and then rewrite the main logic. Second approach is advised if you do not want to prompt that how many pizza's the user wants to order.

Need help creating a function and error with switch statement

I'm using a switch statement to process through some code, which I will create a function in my main to call. I'm having trouble with the switch quantity with my switch statement. Also, how would I create a function for these 10 cases? Very confused, any help greatly appreciated! Thanks! Here is my current code:
#include <iostream>
using namespace std;
void constitution(); // the function that will call my amendments in my main function
// how will i create this will 10 possible amendments to choose from?
// There are 4 pirates and they will vote either yes or no,
int main()
{
cout << "Below is a list of the 10 amendments that the two pirates will vote on according to the ships constitution" << endl;
string amendments = 0;
cin >> amendments; // selecting the amendment
switch (amendments)
{
// for outputting the amendment(s) voted on, which will
// be passed on to a function in main to call
case 1: cout << "What does the fox say? Whatever WE tell it to"; //case 1-10 are the 10 amendments to be voted on
break;
case 2: cout << "From now on the annual Cinco de Mayo party will be held on March 8th ";
break;
case 3: cout << "Beginning this year, sharks shall have a week dedicated to us";
break;
case 4: cout << "Pirates are now allowed to talk about fight club";
break;
case 5: cout << "When in Rome, the Romans will do as WE do.";
break;
case 6: cout << "Our mothers will immediately get tattoos that say SON";
break;
case 7: cout << "From now on the President will take our birthdays off.";
break;
case 8: cout << "If we say something costs an arm and a leg, it does";
break;
case 9: cout << "Freemasons are ordered to learn OUR secret handshake.";
break;
case 10: cout << "If a tree falls in the forest and no one is around, it will make a sound only with our permission ";
break;
default: cout << "This won't be used since a amendment will always be voted on, thus never be shown or checked I believe.. (Please correct me) ";
break;
}
return 0;
}
The only thing you need to change is making amendments an integer, as switch expects an int.
int main()
{
cout << "Below is a list of the 10 amendments that the two pirates will vote on according to the ships constitution" << endl;
int amendments = 0;
cin >> amendments; // selecting the amendment
switch (amendments)
{
...
}
If you want to use amendments as a String, I am afraid you are not going to be able to check it via switch. Instead, you should use if/else if statements:
if(amendments == '1') {
...
} else if (amendments == '2') {
...
}

loop not working?

After the call for Back to Main Menu, it returns to the mainMenu but when option or command is typed, the option is not accepted or the loop not working. Wonder where is the mistake? Is it extra call should be added or?
#include <iostream>
using namespace std;
char mainMenu(void);
int factorial(int n);
unsigned long long combination(long nK, long nR);
int main(){
char option;
int shape,function,i,j,k,t,n;
long nK, nR;
unsigned long long COM;
while((option=mainMenu())!='0')
{
switch(option)
{
case '1'://Program 1:
cout<< "*Drawing a shape\n"
<< "(1-Rectangle, 2-Triangle, 3-Inverted Triangle, 4-Letter 'H', 0-Back to Main Menu)\n";
do
{
cout<< "Choose shape >> ";
cin>> shape;
cout<< endl;
switch(shape)
{
case 1: break;
case 2: break;
case 3: break;
case 4: break;
case 0:
//Back to Main Menu
cout<< "Back to main menu\n"
<< endl;
return mainMenu(); //After here, it does back to Main Menu but command or option is not working
}
}while(shape!=0);
case '2': //Program 2
cout<< "*Choose function of calculator\n"
<< "(1-Factorial, 2-Combination, 0-Back to main menu)\n";
do
{
cout<< "Choose function >> ";
cin>> function;
cout<< endl;
switch(function)
{
case 1: break;
case 2: break;
case 0:
cout<< "Back to main menu\n"
<< endl;
return mainMenu();
}
}while(function!=0);
case '0':
cout<< "Program is terminating\n"
<< endl;
return 0;
default:
cout<< "Wrong input. Please choose one of the above options.\n"
<< endl;
return mainMenu();
}
}
}
char mainMenu(void){
char option;
cout<< "##############################\n"
<< "Main Menu\n"
<< "Enter your command!\n"
<< "##############################\n"
<< endl
<< "1. Program1\n"
<< "2. Program2\n"
<< "0. Exit\n"
<< endl
<< "Command >> ";
cin>> option;
cout<< endl;
return option;
}
I'm not sure what your question is, but your code is missing 2 important things. First, you need break statements at the end of each case block, otherwise the program flow will continue on to the next case statement.
Second, the inner menu doesn't ever escape the inner while(1) loop. This is a possible case for a goto use, although in practice it would better to refactor the code to split the top menu and inner menu into two functions, and use a return in the inner menu to return to the outer menu.
I'm not sure what your question is, but your code is missing 2 important things. First, you need break statements at the end of each case block, otherwise the program flow will continue on to the next case statement.
Second, the inner menu doesn't ever escape the inner while(1) loop. This is a possible case for a goto use, although in practice it would better to refactor the code to split the top menu and inner menu into two functions, and use a return in the inner menu to return to the outer menu.
As said, you're code is missing various things. It would be awesome if you distribute the entire code, and additionally the exact error message with line.
void value not ignored as it ought to be?...
...Is not that much of an explanation...
Also, are you sure you included iostream?
#include iostream
That said, you did not declare any of the variables used in the program.
You also missed a space in line 2 of your mainMenu() function.
Also, please tell us what you expected to happen.