c++ obect out of scope inside a switch statement - c++

The object derm is out of scope in the switch statement.
I tried to make it a static member function.
Is there anyway I can make this work?
Here is my code:
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include <ctime>
using namespace std;
class Invinq {
int menu_pick;
string db_read_out;
public:
Invinq();
void menu_maker();
int add_record();
int change_record();
int delete_record();
int display_record();
int exit_program();
};
Invinq::Invinq()
{
cout <<"Welcome to Inventory Inquisator.\n********************************\n" << endl;
ifstream db_invinq;
db_invinq.open("Invinq_db.txt");
if(!db_invinq)
{
cout<<"\nNot able to create a file. MAJOR OS ERROR!! \n";
}
for(int i = 0; i < db_invinq.eof(); i++)
{
db_invinq >> db_read_out;
cout << db_read_out;
}
}
//Menu maker
void Invinq::menu_maker()
{
cout << "1. Add Record\n2. Change Record\n3. Delete Record\n4. Display Record\n5. Exit\n\nPick One: ";
cin >> menu_pick;
switch(menu_pick)
{
case 1: derm.add_record(); break;
case 2: derm.change_record(); break;
case 3: derm.delete_record(); break;
case 4: derm.display_record(); break;
default: cout << "Pick a number between 1-5, try again\n";
}
derm.menu_maker();
}
int main() {
Invinq derm;
derm.menu_maker();
return 0;
}

You seem to have completely missed the point. you don't need derm when you are already inside the Invinq class - just call menu_maker().
Having said that: you are using recursion for no good reason. This can have some unexpected side effects. I suggest you refactor menu_maker() - if fact right now there is no way to get out of the recursion, so that is really bad!
You main should have the loop and create a Invinq each time through, otherwise you are just overwriting the same object each time which is probably now what you want.

Inside the definition of your class method, you should refer to yourself using the keyword this.
Replace all the method calls as following:
case 1: derm.add_record(); break; > case 1: this->add_record(); break;
Note: this returns a pointer to your object, this is why we use -> rather than .

Related

I don't know really well how to declare a string, (former pawn programmer learning C++)

years ago i was a programmer in a C++ derivated language that was called Pawn, now i want to try to start in C++, write some things to unrust myself from this beatiful thing that is programming
No, i have never coded with C++ before and with any other language that was not Pawn.
This is the first time i use stackoverflow, sorry if i'm asking a stupid question.
So, this is my code:
I tried to do what the code says like its done in Pawn, almost, and well, i have errors.
#include <stdio.h>
#include <iostream> // I don't know if this is needed
#include <string> // The same for this
using namespace std; // I don't know what this means
int main()
{
int number;
printf("Write the number of croisssants you eat a day\n");
scanf("%d", &number);
printf("The number of croissants that you eat a day is %d", number);
char finalMessage[64]; // This is the way it was made in Pawn, you declare a string and put a max for text
switch(number)
{
// So here i try to use a switch to do this, like i was used to, yes i know how to use if but i'm trying to see if it's this metod is the same thing as it is in Pawn.
case 0: finalMessage = "Oh, so you don't like croissants";
case 1: finalMessage = "Thats okay";
case 2: finalMessage = "Well, if one, why not two?";
default: finalMessage = "Mmmm, i think they are too much.";
}
printf("%s", finalMessage);
return 0;
}
The errors are all this:
error: incompatible types in assignment of 'const char [11]' to 'char [64]'
20 | case 1: finalMessage = "Thats okay";
You can imagine the other ones being the same.
I tried reading a lot of "How to declare a string in C++ but because 2 things...
I don't understand advanced programming terms (i.e. initialization, constant, cout, etc), i'm working in that
English is not my first language (It's Spanish), yes, maybe i should use the Spanish forum but i'm trying to get used to the English one because i'm supposed to work with this one in the future
... i can't resolve this.
Since you had quite a few questions packed into your code, I've made some changes and commented on them:
//#include <cstdio> // this is the correct C++ header, I won't use it though
#include <iostream> // I don't know if this is needed
// it's needed if you are using the C++ i/o streams, like std::cin and std::cout
#include <string> // The same for this
// it's needed to be able to use std::string, which you are not, but you should
// using namespace std; // I don't know what this means
// it means that you can skip writing std:: infront of all
// classes/functions/constants that are placed in the std namespace
// Don't use it for now. It's often causing problems until you know when to use it.
int main() {
int number;
//puts("Write the number of croisssants you eat a day");
std::cout << "Write the number of croisssants you eat a day\n";
/* The C way:
if (scanf("%d", &number) != 1) {
fprintf(stderr, "invalid number, bye bye\n");
return 1;
}
*/
if(!(std::cin >> number)) { // the C++ way:
std::cerr << "invalid number, bye bye\n";
return 1;
}
// printf("The number of croissants that you eat a day is %d", number);
// Using std::cout instead:
std::cout << "The number of croissants that you eat a day is " << number << '\n';
// char finalMessage[64];
std::string finalMessage; // use a std::string instead
switch (number) {
case 0:
finalMessage = "Oh, so you don't like croissants";
break; // needed, or else it'll continue to the next case
case 1:
finalMessage = "Thats okay";
break; // needed, or else it'll continue to the next case
case 2:
finalMessage = "Well, if one, why not two?";
break; // needed, or else it'll continue to the next case
default:
finalMessage = "Mmmm, i think they are too much.";
}
//printf("%s\n", finalMessage.c_str()); // or
//puts(finalMessage.c_str()); // or the c++ way:
std::cout << finalMessage << '\n';
}
Arrays do not have the copy assignment operator.
So such an assignment like this
finalMessage = "Oh, so you don't like croissants";
is invalid.
In these statements
case 0: finalMessage = "Oh, so you don't like croissants";
case 1: finalMessage = "Thats okay";
case 2: finalMessage = "Well, if one, why not two?";
default: finalMessage = "Mmmm, i think they are too much.";
you are using string literals that have static storage duration. To make the code correct just declare the variable finalMessage as having the type const char *:
const char *finalMessage;
In this case in assignments like this
finalMessage = "Oh, so you don't like croissants";
the string literal is implicitly converted to a pointer to its first element and this pointer will be assigned to the pointer finalMessage.
There is no need to use objects of the type std::string in your simple program.
Also you need to use the statement break to pass the control after each labeled statement outside the switch statement
switch(number)
{
// So here i try to use a switch to do this, like i was used to, yes i know how to use if but i'm trying to see if it's this metod is the same thing as it is in Pawn.
case 0: finalMessage = "Oh, so you don't like croissants";
break;
case 1: finalMessage = "Thats okay";
break;
case 2: finalMessage = "Well, if one, why not two?";
break;
default: finalMessage = "Mmmm, i think they are too much.";
break;
}
As for the comment in this line
using namespace std; // I don't know what this means
then in your program it is redundant because neither name from the namespace std is used in your program.
Standard C++ names as for example cout or string are declared in the namespace std. Without the using directive you need to use qualified names as for example
std::string s( "Hello" );
std::cout << s << '\n';
Including the using directive you may write
using namespace std;
//...
string s( "Hello" );
cout << s << '\n';
Also pay attention to that names of headers from C you should prefix with the letter 'c' that is instead for example
#include <stdio.h>
you should write
#include <cstdio>
Well since you are trying to get into C++ I would recommend ditching the pure char arrays and the C style IO (printf and scanf). Instead replace them with the more modern std::string and IO (std::cout and std::cin).
Rewriting this in modern C++ would look like this
#include <iostream>
#include <string>
using namespace std;
int main()
{
int number;
cout << "Write the number of croisssants you eat a day" << endl;
cin >> number;
cout << "The number of croissants that you eat a day is " << number << endl;
string finalMessage;
switch(number)
{
case 0:
finalMessage = "Oh, so you don't like croissants";
break;
case 1:
finalMessage = "Thats okay";
break;
case 2:
finalMessage = "Well, if one, why not two?";
break;
default:
finalMessage = "Mmmm, i think they are too much.";
}
cout << finalMessage << endl;
return 0;
}
I am not familiar with pawn but in C++ in switch statements you have to use break before the next case if you don't want fallthrough.
Also using namespace std; just specifies that you are going to use the standard namespace by default. Allows you to type cout << "Something"; instead of std::cout << "Something". However it is considered bad practice
It seems like you're using mostly C concepts rather than C++.
In C++, we would use string instead of an array of chars. Additionally, we would use cin (C in) and cout (C out) for input and output. Try the following:
#include <iostream> // This is needed for cin/cout
#include <string> // This is needed to use string
using namespace std; // Basically this means you can write cin instead of std::cin, string instead of std::string, etc.
int main()
{
int number;
cout << "Write the number of croisssants you eat a day\n"; //cout instead of printf
cin >> number; //cin instead of scanf. Note that you don't need to specify types
cout << "The number of croissants that you eat a day is " << number;
string finalMessage; // In C++, we use strings instead of char arrays
switch(number)
{
// Switches should work the same way
case 0: finalMessage = "Oh, so you don't like croissants"; break;
case 1: finalMessage = "Thats okay"; break;
case 2: finalMessage = "Well, if one, why not two?"; break;
default: finalMessage = "Mmmm, i think they are too much.";
}
cout << finalMessage;
return 0;
}

Errors because of vector<string>? [duplicate]

This question already has answers here:
why is string not declared in scope
(3 answers)
Closed 2 years ago.
Sorry for the spaghetti code, I don't have much experience with C++ (or coding in general for that matter) but here is my code... Also first time posting on stack overflow so apologies for improper formatting.
I have been scouring the internet for the last 4 hours. Please tell me this is a simple fix.
I have tried using std::vector ingredients.
//Program_2.h
#pragma once
#include <vector>
#include <string>
#include <iostream>
namespace sandwich
{
class SandwichMaker
{
public:
vector<string> ingredients;//<-- causing a few errors
int s = 0;
int Control();
void Menu(int &s, vector<string> &vec);
void PrintSandwich(vector<string> &vec);
private:
};
}
//Program_2.cpp
#include "Program_2.h"
using namespace std;
using namespace sandwich;
int SandwichMaker::Control()
{
SandwichMaker swm;
//vector<string> ingredients;
swm.Menu(swm.s, swm.ingredients);
while (swm.s > 0)
{
swm.Menu(swm.s, swm.ingredients);
}
system("PAUSE");
return 0;
}
void SandwichMaker::Menu(int &s, vector<string>& vec)
{
SandwichMaker swm;
cout << "Please choose what you would like to do and type the ingredient (1 and 2 only)\n (0 quit, 1 add ingredient, 2 remove ingredient, 3 make sandwich): ";
cin >> s;
string tempIngredient = "";
switch (s)
{
case 1://add
//cout << "Enter the ingredient you are going to add.\n";
cin.ignore();
getline(cin, tempIngredient);
vec.push_back(tempIngredient);
cout << " Ingredient has been added\n";
break;
case 2://remove
if (!vec.empty())
vec.pop_back();
else
cout << " Nothing has been added yet\n";
break;
case 3: //make the sandwich
swm.PrintSandwich(vec);
break;
default:
break;
}
}
void SandwichMaker::PrintSandwich(vector<string>& vec)
{
cout << "Your sandwich contains: ";
for (size_t i = 0; i < vec.size(); i++)
{
cout << i << ", " << vec[i] << endl;
}
}
cant post an images soo link? https://imgur.com/a/mK0UrEU of all the errors that are getting spit out because of vector.
Your using namespace std comes after your inclusion of Program_2.h, so the SandwichMaker class is defined without using namespace std being in effect.
You thus need to write std::vector, not vector, and std::string, not string.
Note: Do not try to "fix" this by applying using namespace std earlier - that's a bad idea and poor programming. See:
Why is "using namespace std;" considered bad practice?
PS:
You're repeating the word "Sandwich" a whole lot of times: sandwich::SandwichMaker{}.PrintSandwich() - aren't these too many sandwiches?
I know a guy who's a sandwich maker and he never prints sandwiches.
If you have a class named WhateverMaker - you often don't really need the class at all, and could settle for a nice Whatever class, and some functions which return Whatevers. See also this.

_getch not reading input into variable

I'm having trouble with the _getch() function, I want it so that the user does not need to hit ENTER when selecting things from the menu. However, when I try and use it, it either doesn't input the data into a variable, or it skips over the switch I have. I'm using Windows 7, and the CodeBlocks IDE. What am I doing incorrectly? Thanks in advance.
#include <iostream>
#include <sstream>
#include <conio.h>
using namespace std;
stringstream ss;
int a;
void play()
{
cout << "\nYou wake up on the forest floor. You do not remember where you are, who you are, or anything\nthat has happened before you waking up. You seem to be some type of...\n";
cout << "--CHARACTER SELECTION--\n1. Warrior\n2. Mage\n3. Rouge";
cin.get();
};
int main()
{
// CreateDirectory()
cout << "--SELECTION MENU--\n1. Begin\n2. Delete Game\n3. Instructions" << endl;
a=_getch();
switch(a){
case 1:
play();
break;
case 2:
// delete();
break;
case 3:
// help();
break;
return 0;
}
}
Compare your char against the characters '1', '2' and '3' rather than the integers 1, 2 and 3.
switch(a){
case '1':
play();
break;
case '2':
// delete();
break;
case '3':
// help();
break;
return 0;
}

Vectors, Pointers, Classes and EoF Loops (C++)

I am trying to get a vector to store objects of class 'Complex'.
This is how I have tried to get it to store:
ifstream values;
values.open("h://values.txt");
if(!values)
{
cout<<"Error: cannot open "<<"values.txt"<<endl<<endl;
}
else
{
//Initialise list
vector<Complex> v;
Complex *c1;
double a,b,d=0,e=0;
char c;
int count=0;
while(values)
{
values>>c>>a>>b;
c1=new Complex;
v.push_back(*c1);
cout<<c<<" "<<a<<" "<<b<<endl;
switch (c)
{
case 'r':
case 'R':
case 'p':
case 'P':
{
//Call constructor
v[count].setType(c);
switch (c)
{
case 'r':
case 'R':
{ v[count].setReal(a);
v[count].setImaginary(b);
v[count].topolar(a,b,d,e);
break;
}
case 'p':
case'P':
{ v[count].setLength(a);
v[count].setAngle(b);
v[count].frompolar(d,e,a,b);
break;
}
default:
{ cout<<"Type Error"<<endl;
break;
}
}
count++;
break;
}
default:
{
//error message
cout<<" Failed input type, ensure all of type 'r' or 'p'"<< endl;
cout<<"Programme Closing"<<endl;
break;
}
};
}
While this will read the info in my programme, it insists on reading the last line twice (I put the cout into this loop so it was easier to see what numbers were where). I have tried using a for loop, but because I want it to run till the end of file I think I have to use a while loop, but I might be wrong.
My supervisor said something along the lines of c1 being overwritten on every loop, but I thought this should be OK on the basis the information is passed to the vector before it is overwritten by the next line so I'm a bit confused.
The next problem is that when I then try and print out all the information again, outside of the loop shown above (for example to allow for manipulation before printing) it prints the same thing over and over until the for loop reaches the count...
int y;
int z;
while(y!=3)
{
cout<< " What would you like to do?"<<endl;
cout<< " Type the number of the option you would like"<<endl;
cout<< " 1. Show all numbers in polar form"<<endl;
cout<< " 2. Show all numbers in rectangular form"<<endl;
cout<< " 3. Show all numbers in both forms"<<endl;
cout<< " 4. Convert a number to its conjugate"<<endl;
cout<< " 5. Exit"<<endl;
cin>>y;
switch(y)
{
case 1:
for(z=0; z<count;z++)
{
v[z].getLength();
v[z].getAngle();
cout<< a<<" "<<b<<endl;};
break;
case 2:
for (z=0; z!=count;z++)
{
v[z].getReal();
v[z].getImaginary();
};
break;
case 3:
cout<<" Real Imaginary | Length Angle | Original Type"<<endl;
for(z=0; z!=count;z++)
{ v[z].getLength();
v[z].getAngle();
v[z].getReal();
v[z].getImaginary();
cout<<a<<" "<<b<<" "<<d<<" "<<e<<endl;
In case any of you try to run the programme:
#include "Class definitions.h"
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string.h>
#include <cmath>
#include <vector>
using namespace std;
Any help will be greatly appreciated!!
Thanks muchly!
H
x
Whether input succeeds is only known after the input, not before. After you do
values>>c>>a>>b;
you use the values, even if the input has failed (e.g. because of end of file). Put the test in the condition of the while loop:
while ( values >> c >> a >> b )
and your code should work. (Whether this is the best way to handle the problem is another question. I'd probably use std::getline(), followed by std::istringstream to parse the line I'd read. Much easier error recovery.)

Referenced vector does not pass through functions

The referenced vector to functions does not hold the information in memory. Do I have to use pointers?
Thanks.
#include <iostream>
#include <cstdlib>
#include <vector>
#include <string>
using namespace std;
void menu();
void addvector(vector<string>& vec);
void subvector(vector<string>& vec);
void vectorsize(const vector<string>& vec);
void printvec(const vector<string>& vec);
void printvec_bw(const vector<string>& vec);
int main()
{
vector<string> svector;
menu();
return 0;
}
//functions definitions
void menu()
{
vector<string> svector;
int choice = 0;
cout << "Thanks for using this program! \n"
<< "Enter 1 to add a string to the vector \n"
<< "Enter 2 to remove the last string from the vector \n"
<< "Enter 3 to print the vector size \n"
<< "Enter 4 to print the contents of the vector \n"
<< "Enter 5 ----------------------------------- backwards \n"
<< "Enter 6 to end the program \n";
cin >> choice;
switch(choice)
{
case 1:
addvector(svector);
menu();
break;
case 2:
subvector(svector);
menu();
break;
case 3:
vectorsize(svector);
menu();
break;
case 4:
printvec(svector);
menu();
break;
case 5:
printvec_bw(svector);
menu();
break;
case 6:
exit(1);
default:
cout << "not a valid choice \n";
// menu is structured so that all other functions are called from it.
}
}
void addvector(vector<string>& vec)
{
//string line;
//int i = 0;
//cin.ignore(1, '\n');
//cout << "Enter the string please \n";
//getline(cin, line);
vec.push_back("the police man's beard is half-constructed");
}
void subvector(vector<string>& vec)
{
vec.pop_back();
return;
}
void vectorsize(const vector<string>& vec)
{
if (vec.empty())
{
cout << "vector is empty";
}
else
{
cout << vec.size() << endl;
}
return;
}
void printvec(const vector<string>& vec)
{
for(int i = 0; i < vec.size(); i++)
{
cout << vec[i] << endl;
}
return;
}
void printvec_bw(const vector<string>& vec)
{
for(int i = vec.size(); i > 0; i--)
{
cout << vec[i] << endl;
}
return;
}
Your problem is that each call to menu() creates a new vector that hides the previous one, this is why it seems to you like they're empty. If you really want to be calling menu recursively, pass it the vector reference that you created in main.
All that being said, menu systems are rarely ever recursive. You probably want a loop around your call to menu() in main that loops until the user has chosen to quit.
Your menu function is recursive.
That means that every new call of menu will create it's own vector, and throw it away when it's done.
If you want to reuse the svector, you need to either use a plain loop for the menu, or pass the original svector, created in the main, to the menu using a pass-by-reference argument.
Problem is that you call another menu() which allocates new svector on stack (in some part of memory).
Probably original code was void menu(vector<string>&svector)
You need to either have svector be a global (declared outside any function) or pass it as a parameter to menu. C++ does not have dynamic scope for functions.
EDIT: You can also wrap all this up in a class and repeatedly call menu().
svector is shared (is that what s stands for?), and variables which are shared between different scopes in C++ must be declared extern, or you get two separate local variables.
int main()
{
extern vector<string> svector;
…
void menu()
{
extern vector<string> svector;
…
Just kidding. svector should be an argument. Or a global would suffice. But don't use globals like this.