So, I'm doing a homework where we have to test our class. We were forbidden to use stl.:) The problem is that at the test_2 the program crashes. It works all until it gets beck to the main try statement. When it should jump to the exception it just crashes. Any idea why is this happening? Thanks in advance! :)
void test_2() //
{
int tomb[400];
for(unsigned int j=0;j<400;j++){
tomb[j]=j;
}
cout <<"array loaded \n";
Buffer<int> test2(40,"test2.txt","w");
Buffer<int> test21(40,"test21.txt","w"); // 40 meretu buffer
cout << "bufferek letrehozva \n";
for(unsigned int j=0;j<400;j++){
test2[j]=tomb[j];
}
cout << "buff loaded \n";
/* for(unsigned int j=0;j<400;j++){
cout << test2[j] << endl;
} */
test21=test2;
cout << "copy constr ran \n";
unsigned int i=0;
for(unsigned int j=0;j<400;j++){
if(i==39){for(i=0;i<40;i++){ //40 size buff
test21.printfile(test21[i]);}
i=0;}
else i++;
}
throw "gets here";
}
int main()
{
try
{
int number;
cin >> number; // nr of the test
switch (number)
{
case 1:
test_1(); // file_test
break;
case 2:
test_2(); // copyconst_test
break; // crashes here
case 3:
test_3();
break;
}
}
catch (exception& e)
{
cerr << e.what() << endl;
}
catch (int i)
{
cerr << i << endl;
}
catch (const char* s)
{
cerr << s << endl;
}
catch (...)
{
cerr << "*** Nagy baj van! ****" << endl;
}
return 0;
}
SOLVED
I made an obj with the size of 40 and loaded it with 400 int. This procedure made the size of the test2 object 720(becuse at overloading it doubles its size) so I made 2 different sized objects equal.
Buffer<int> test2(40,"test2.txt","w");
// first buffer
cout << "bufferek made\n";
for(unsigned int j=0;j<400;j++){
test2[j]=tomb[j]; //load buffer
}
Buffer<int> test21(test2.getSize(),"test21.txt","w"); //make the second buffer
Related
I asked this question a couple of hours ago; I want to see if someone can now explain the problem.
One code is about separating items in a grocery; in the end you'll have two(2) bags; a fragileBag and a normalBag.
Other code separates passengers depending on the office they go for pickup; in the end you'll have three(3) types of passengers; ones that go to rio, ones that go to maya, and ones that request elsewhere.
Both codes use the same logic but the passenger code gives an error on a line that works perfectly on the grocery code.
Just to be clear, BOTH CODES RETURN VALUES OF STRING.
ERROR FROM THE PASSENGER CODE:
Error (active) E0304 no instance of overloaded function "std::vector<_Ty,_Alloc>::push_back [with _Ty=trans, _Alloc=std::allocator<trans>]" matches the argument list dataPractice2 C:\Users\javye\source\repos\dataPractice2\dataPractice2\main.cpp 82
and also:
Error C2664 'void std::vector<trans,std::allocator<_Ty>>::push_back(_Ty &&)': cannot convert argument 1 from 'std::string' to 'const _Ty &' dataPractice2 c:\users\javye\source\repos\datapractice2\datapractice2\main.cpp 82
//GROCERY FUNCTION
//separate function
void separateItems(vector<myBag>& newMyVector) {
for (int x = newMyVector.size() - 1; x >= 0; --x) {
if (newMyVector[x].getItem() == "eggs" || newMyVector[x].getItem() == "bread") {
fragileBag.push_back(newMyVector[x].getItem()); //NO PROBLEM HERE
newMyVector.pop_back();
}
else {
normalBag.push_back(newMyVector[x].getItem()); //OR HERE
newMyVector.pop_back();
}
}
}
//PASSENGER FUNCTION
//separate function
void separateP(vector<trans>& newMyVector) {
for (int x = newMyVector.size() - 1; x >= 0; --x) {
if (newMyVector[x].getXoLoc() == "rio") {
rioLoc.push_back(newMyVector[x].getXoLoc()); //PROBLEM HERE
newMyVector.pop_back();
}
else
if (newMyVector[x].getXoLoc() == "maya") {
mayaLoc.push_back(newMyVector[x].getXoLoc()); //HERE
newMyVector.pop_back();
}
else
elseLoc.push_back(newMyVector[x].getXoLoc()); //HERE
newMyVector.pop_back();
}
}
//GROCERY FULL CODE
//HEADER
#pragma once
#include<iostream>
#include<vector>
#include<string>
using namespace std;
#ifndef BAG_H
#define BAG_H
class myBag {
public:
myBag(); //default constructor
myBag(string anItemName); //overload constructor
void addItem(string anItemName); //mutator
string getItem();//accessor
private:
string itemName;
};
#endif
//SOURCE
#include"bag.h"
myBag::myBag() {
addItem("");
}
myBag::myBag(string anItemName) {
addItem(anItemName);
}
void myBag::addItem(string anItemName) {
itemName = anItemName;
}
string myBag::getItem() {
return itemName;
}
//MAIN
#include"bag.h"
void inputItems(vector<myBag>&); //input data function prototype
void displayQuantity(vector<myBag>&); //display data function prototype
void separateItems(vector<myBag>&); //function that separates items; func prototype
void fragBag(vector<myBag>&); //fragile bag function prototype
void norBag(vector<myBag>&); //normal bag function prototype
vector<myBag> myVector; //main vector
vector<myBag> fragileBag, normalBag; //seconday vectors
string item; //global item variable
int main() {
int option;
try {
do {
cout << "\tMENU"
<< endl << "1) Input Items"
<< endl << "2) Display Quantity"
<< endl << "3) Separate (IMPORTANT)"
<< endl << "4) Display Items in Fragile Bag"
<< endl << "5) Display Items in Normal Bag"
<< endl << "6) Exit Program"
<< endl << endl << "Choose: ";
cin >> option;
if (option > 6) {
throw 404;
}
switch (option) {
case 1: //input
system("cls");
inputItems(myVector);
system("pause");
system("cls");
break;
case 2://display
system("cls");
displayQuantity(myVector);
system("pause");
system("cls");
break;
case 3: //separate
system("cls");
separateItems(myVector);
system("pause");
system("cls");
break;
case 4: //fragile
system("cls");
fragBag(myVector);
system("pause");
system("cls");
break;
case 5: //normal
system("cls");
norBag(myVector);
system("pause");
system("cls");
break;
case 6: //exit
exit(0);
}
} while (option != 6);
}
catch(int x){
cout << "ERROR, OPTION DOESN'T EXITS" << endl;
system("pause");
}
}
//input function
void inputItems(vector<myBag>& newMyVector) {
do {
cout << "Enter grocery items || enter letter X to stop: ";
cin >> item;
if (item != "x")
newMyVector.push_back(myBag(item));
} while (item != "x");
}
//display function
void displayQuantity(vector<myBag>& newMyVector) {
try {
for (int x = 0; x < newMyVector.size(); ++x) {
if (x == 0) {
cout << "Store bag has " << newMyVector.size() << " items in it. These are: " << endl;
}
cout << newMyVector[x].getItem() << endl;
}
if (newMyVector.empty())
throw 404;
}
catch (int x) {
cout << "ERROR " << x << " ,QUANTITY NOT FOUND" << endl;
}
}
//separate function
void separateItems(vector<myBag>& newMyVector) {
for (int x = newMyVector.size() - 1; x >= 0; --x) {
if (newMyVector[x].getItem() == "eggs" || newMyVector[x].getItem() == "bread") {
fragileBag.push_back(newMyVector[x].getItem()); //PROBLEM WOULD APPEAR HERE, BUT DOESN'T, UNLIKE THE OTHER CODE
newMyVector.pop_back();
}
else {
normalBag.push_back(newMyVector[x].getItem());
newMyVector.pop_back();
}
}
}
//fragile bag function
void fragBag(vector<myBag>& newMyVector) {
try {
for (int x = 0; x < fragileBag.size(); ++x) {
if (x == 0) {
cout << "The fragile bag has " << fragileBag.size() << " items in it. These are: " << endl;
}
cout << fragileBag[x].getItem() << endl;
}
if (fragileBag.empty()) {
throw 404;
}
}
catch (int x) {
cout << "ERROR " << x << " ,FRAGILE BAG EMPTY" << endl;
}
}
//normal bag function
void norBag(vector<myBag>& newMyVector) {
try {
for (int x = 0; x < normalBag.size(); ++x) {
if (x == 0) {
cout << "The normal bag has " << normalBag.size() << " items in it. These are: " << endl;
}
cout << normalBag[x].getItem() << endl;
}
if (normalBag.empty()) {
throw 404;
}
}
catch (int x) {
cout << "ERROR " << x <<" , NORMAL BAG EMPTY" << endl;
}
}
//PASSENGER FULL CODE
//HEADER
#pragma once
#include<iostream>
#include<vector>
#include<string>
using namespace std;
#ifndef TRANSPORT_H
#define TRANSPORT_H
class trans {
public:
trans();
trans(string aName, string anXoLoc, string anXfLoc, string aTime, string aCellNum);
void setName(string aName);
void setXoLoc(string anXoLoc);
void setXfLoc(string anXfLoc);
void setTime(string aTime);
void setCellNum(string aCellNum);
string getName();
string getXoLoc();
string getXfLoc();
string getTime();
string getCellNum();
private:
string name;
string xoLoc; //offices
string xfLoc; //destination
string time;
string cellNum;
};
//SOURCE
#include"transport.h"
trans::trans() {
setName("");
setXoLoc("");
setXfLoc("");
setTime("");
setCellNum("");
}
trans::trans(string aName, string anXoLoc, string anXfLoc, string aTime, string aCellNum) {
setName(aName);
setXoLoc(anXoLoc);
setXfLoc(anXfLoc);
setTime(aTime);
setCellNum(aCellNum);
}
void trans::setName(string aName) {
name = aName;
}
void trans::setXoLoc(string anXoLoc) {
xoLoc = anXoLoc;
}
void trans::setXfLoc(string anXfLoc) {
xfLoc = anXfLoc;
}
void trans::setTime(string aTime) {
time = aTime;
}
void trans::setCellNum(string aCellNum) {
cellNum = aCellNum;
}
string trans::getName() {
return name;
}
string trans::getXoLoc() {
return xoLoc;
}
string trans::getXfLoc() {
return xfLoc;
}
string trans::getTime() {
return time;
}
string trans::getCellNum() {
return cellNum;
}
#endif
//MAIN
#include"transport.h"
void inputInfo(vector<trans> &);
void displayInput(vector<trans>&);
void separateP(vector<trans>&);
void rio(vector<trans>&);
void maya(vector<trans>&);
void elsewhere(vector<trans>&);
vector<trans> myVector;
vector<trans> rioLoc, mayaLoc, elseLoc;
string newName;
string newXoLoc; //offices
string newXfLoc; //destination
string newTime;
string newCellNum;
//main not ready. Creating each function one by one to them make it look nice
int main() {
int option;
do {
cout << "MENU"
<< endl << "1) input "
<< endl << "2) output "
<< endl << "3) separate"
<< endl << "4) rio passengers"
<< endl << "5) maya passengers"
<< endl << "6) elsewhere passengers";
cin >> option;
switch(option){
case 1:
inputInfo(myVector);
break;
case 2:
displayInput(myVector);
break;
case 3:
separateP(myVector);
break;
case 4:
rio(myVector);
break;
case 5:
maya(myVector);
break;
case 6:
elsewhere(myVector);
break;
case 7:
exit(0);
}
} while (option != 7);
system("pause");
}
void inputInfo(vector<trans> &newMyVector) {
int charSize;
cout << "How many passangers to register: ";
cin >> charSize;
for (int x = 0; x < charSize; ++x) {
cout << "Name of passanger: ";
cin >> newName;
cout << "Office: ";
cin >> newXoLoc;
cout << "Destination: ";
cin >> newXfLoc;
cout << "Time of pickup: ";
cin >> newTime;
cout << "Cellphone: ";
cin >> newCellNum;
if (charSize != 0)
newMyVector.push_back(trans(newName, newXoLoc, newXfLoc, newTime, newCellNum));
}
}
void displayInput(vector<trans>& newMyVector) {
for (int x = 0; x < newMyVector.size(); ++x) {
if (x == 0) {
cout << "There are " << newMyVector.size() << " passengers. These are: " << endl;
}
cout << "-----------------------------Passenger #" << x + 1 << endl;
cout << newMyVector[x].getName() << endl;
cout << newMyVector[x].getXoLoc() << endl;
cout << newMyVector[x].getXfLoc() << endl;
cout << newMyVector[x].getTime() << endl;
cout << newMyVector[x].getCellNum() << endl;
}
}
void separateP(vector<trans>& newMyVector) {
for (int x = newMyVector.size() - 1; x >= 0; --x) {
if (newMyVector[x].getXoLoc() == "rio") {
rioLoc.push_back(newMyVector[x]);
newMyVector.pop_back();
}
else
if (newMyVector[x].getXoLoc() == "maya") {
mayaLoc.push_back(newMyVector[x]);
newMyVector.pop_back();
}
else
elseLoc.push_back(newMyVector[x]);
newMyVector.pop_back();
}
}
void rio(vector<trans>& newMyVector) {
for (int x = 0; x < rioLoc.size(); ++x) {
if (x == 0) {
cout << "Num. of passangers to pickup in Rio Piedras is " << rioLoc.size() << " , these are: " << endl;
}
cout << rioLoc[x].getName() << endl;
cout << rioLoc[x].getXoLoc() << endl;
cout << rioLoc[x].getXfLoc() << endl;
cout << rioLoc[x].getTime() << endl;
cout << rioLoc[x].getCellNum() << endl;
}
}
void maya(vector<trans>& newMyVector) {
for (int x = 0; x < mayaLoc.size(); ++x) {
if (x == 0) {
cout << "Num. of passangers to pickup in Mayaguez is " << mayaLoc.size() << " , these are: " << endl;
}
cout << mayaLoc[x].getName() << endl;
cout << mayaLoc[x].getXoLoc() << endl;
cout << mayaLoc[x].getXfLoc() << endl;
cout << mayaLoc[x].getTime() << endl;
cout << mayaLoc[x].getCellNum() << endl;
}
}
void elsewhere(vector<trans>& newMyVector) {
for (int x = 0; x < elseLoc.size(); ++x) {
if (x == 0) {
cout << "Num. of passangers to pickup in elsewhere is " << elseLoc.size() << " , these are: " << endl;
}
cout << elseLoc[x].getName() << endl;
cout << elseLoc[x].getXoLoc() << endl;
cout << elseLoc[x].getXfLoc() << endl;
cout << elseLoc[x].getTime() << endl;
cout << elseLoc[x].getCellNum() << endl;
}
}
To explain why the second code does not work I first have to explain why the first code appears to work.
myBag::myBag(string anItemName)
can make a bag out of a string. It is a Conversion Constructor. So when
fragileBag.push_back(newMyVector[x].getItem());
is compiled, the compiler quietly inserts a call to the myBag(string) constructor and you get something more like
fragileBag.push_back(myBag(newMyVector[x].getItem()));
which makes no sense logically. It says turn an item in a bag into a bag with one item and insert this new bag into still another bag, fragileBag.
When you look more closely at myBag, you see that it isn't a bag at all. It is a single item and should be renamed to myItem or discarded all together in favour of an all-new all-different myBag that is a wrapper around a vector of string where the strings represent items. This makes
myBag fragileBag;
the real bag.
In other words, the only reason the working code works is it doesn't actually do what the naming implies it does. The code compiles and produces the expected result, but is semantically troubled.
This leads to the confusion with
rioLoc.push_back(newMyVector[x].getXoLoc());
rioLoc is a vector<trans> and can only hold trans. There is no trans::trans(string) to convert a string to a trans so the faulty logic of the grocery code is exposed. As bag and item have been intertwined in grocery, passenger and transport are combined here.
The fix for grocery described above is relatively straight forward. Passenger will need a slightly different solution with both a passenger class to describe the passengers and a transport class to describe the means of transport. transport will have a vector<passenger> member to contain its passengers as well as methods to add and remove the passengers and possibly book-keeping to track the location of the transport, details incompletely specified by the question.
Both codes are pushing string values into a vector that does not hold string values.
Your grocery code uses a vector of myBag objects. The code works because myBag has a non-explicit constructor that takes a single string as input, so the compiler is able to implicitly construct a temporary myBag object to push into the vector.
Your passenger code uses a vector of trans objects. The code fails because trans does not have a constructor that takes a single string as input, so the compiler cannot construct a temporary trans to push into the vector.
While working on this project for my younger cousin, I encountered many difficulties. I was wondering if someone could help me use char to output complete sentences (or help me fix these bugs.) I'm a relatively new programmer (about 8 months). Here's my code/ what I have attempted. Most of the bugs cause the program to freeze once a sentence is imputed, or the files not responding when opened.
#include<iostream>
#include<fstream>
#include<cctype>
#include<iomanip>
class legoset
{
char setcatname[25];
char name[50];
char legoinclude[25];
char legotype[25];
public:
void create_category();
void show_category() const;
void modify();
void report() const;
int retacno() const;
};
void legoset::create_category()
{
std::cout << "Please enter a category name : \n";
std::cin >> setcatname;
//std::cin.getline(setcatname, 25);
std::cout << "Please enter your username! \n";
std::cin >> name;
std::cin.ignore();
std::cin.getline(name, 50);
std::cout << name << " , is it a vehicle or building (V/B)?\n";
std::cin >> legotype;
legotype[25] = toupper(legotype[25]);
std::cin.getline(legotype, 25);
std::cout << "\n Please enter the name of the lego set. \n";
std::cin >> legoinclude;
//std::cin.getline(legoinclude, 25);
std::cout << "\n\n Category Created Successfully!!!";
return;
}
void legoset::show_category() const
{
std::cout << "Category : \n" << setcatname;
std::cout << "Username Of Holder \n: " << name;
std::cout << " Lego type (B/V) : " << legotype;
std::cout << " Lego set (with details) : " << legoinclude;
return;
}
void legoset::modify()
{
std::cout << "Category : \n" << setcatname[25];
std::cout << "\nModify Holder's name : ";
std::cin.ignore();
std::cin.getline(name, 50);
std::cout << "\nModify A Building or vehicle class ( B/V ) : ";
std::cin >> legotype[25];
legotype[25] = toupper(legotype[25]);
std::cout << "\nModify Lego set (with details) : ";
std::cin >> legoinclude[25];
}
void legoset::report() const
{
std::cout << setcatname[25] << std::setw(10) << " " << name << std::setw(10) << " " << legotype[25] << std::setw(6) << legoinclude[25] << std::endl;
}
int legoset::retacno() const
{
return setcatname[25];
}
void write_legoset(); //function to write record in binary file
void display_sp(int); //function to display account details given by user
void modify_set(int); //function to modify record of file
void delete_set(int); //function to delete record of file
void display_all(); //function to display all account details
void intro(); //introductory screen function
int main()
{
char choice;
int num;
intro();
do
{
system("cls");
std::cout << "\n\n\n\tMAIN MENU";
std::cout << "\n\n\t01. New Category";
std::cout << "\n\n\t02. ADD A NEW SET";
std::cout << "\n\n\t03. ALL USERS HOLDER LIST";
std::cout << "\n\n\t04. DELETE A CATEGORY";
std::cout << "\n\n\t05. MODIFY A CATEGORY";
std::cout << "\n\n\t06. EXIT";
std::cout << "\n\n\tSelect Your Option (1-6) ";
std::cin >> choice;
system("cls");
switch (choice)
{
case '1':
write_legoset();
break;
case '2':
std::cout << "\n\n\tEnter The category Name : "; std::cin >> num;
display_sp(num);
break;
case '3':
display_all();
break;
case '4':
std::cout << "\n\n\tEnter The Category Name : "; std::cin >> num;
delete_set(num);
break;
case '5':
std::cout << "\n\n\tEnter The Category Name : "; std::cin >> num;
modify_set(num);
break;
case '6':
std::cout << "\n\n\tThanks for using lego managemnt system!";
std::exit;
break;
default: std::cout << "\a";
}
std::cin.ignore();
std::cin.get();
} while (choice != '6');
return 0;
}
//***************************************************************
// function to write in file
//****************************************************************
void write_legoset()
{
legoset lego;
std::ofstream outFile;
outFile.open("legoset.dat", std::ios::binary | std::ios::app);
lego.create_category();
outFile.write(reinterpret_cast<char *> (&lego), sizeof(legoset));
outFile.close();
}
//***************************************************************
// function to read specific record from file
//****************************************************************
void display_sp(int n)
{
legoset lego;
bool flag = false;
std::ifstream inFile;
inFile.open("legoset.dat", std::ios::binary);
if (!inFile)
{
std::cout << "File could not be open !! Press any Key...";
return;
}
std::cout << "\nLEGOSET DETAILS\n";
while (inFile.read(reinterpret_cast<char *> (&lego), sizeof(legoset)))
{
if (lego.retacno() == n)
{
lego.show_category();
flag = true;
}
}
inFile.close();
if (flag == false)
std::cout << "\n\nLego set does not exist in this file";
}
//***************************************************************
// function to modify record of file
//****************************************************************
void modify_set(int n)
{
bool found = false;
legoset lego;
std::fstream File;
File.open("legoset.dat", std::ios::binary | std::ios::in | std::ios::out);
if (!File)
{
std::cout << "File could not be open !! Press any Key...";
return;
}
while (!File.eof() && found == false)
{
File.read(reinterpret_cast<char *> (&lego), sizeof(legoset));
if (lego.retacno() == n)
{
lego.show_category();
std::cout << "\n\nPlease Enter The New Details For This Category." << std::endl;
lego.modify();
int pos = (-1)*static_cast<int>(sizeof(legoset));
File.seekp(pos, std::ios::cur);
File.write(reinterpret_cast<char *> (&lego), sizeof(legoset));
std::cout << "\n\n\t Category Updated!";
found = true;
}
}
File.close();
if (found == false)
std::cout << "\n\n Category Not Found ";
}
//***************************************************************
// function to delete record of file
//****************************************************************
void delete_set(int n)
{
legoset lego;
std::ifstream inFile;
std::ofstream outFile;
inFile.open("legoset.dat", std::ios::binary);
if (!inFile)
{
std::cout << "File could not be open !! Press any Key...";
return;
}
outFile.open("Temp.dat", std::ios::binary);
inFile.seekg(0, std::ios::beg);
while (inFile.read(reinterpret_cast<char *> (&lego), sizeof(legoset)))
{
if (lego.retacno() != n)
{
outFile.write(reinterpret_cast<char *> (&lego), sizeof(legoset));
}
}
inFile.close();
outFile.close();
remove("legoset.dat");
rename("Temp.dat", "legoset.dat");
std::cout << "\n\n\tCategory Deleted ..";
}
//***************************************************************
// function to display all accounts deposit list
//****************************************************************
void display_all()
{
legoset lego;
std::ifstream inFile;
inFile.open("legoset.dat", std::ios::binary);
if (!inFile)
{
std::cout << "File could not be open !! Press any Key...";
return;
}
std::cout << "\n\n\t\tUSER HOLDER LIST\n\n";
std::cout << "====================================================\n";
std::cout << "A/c no. NAME Type Balance\n";
std::cout << "====================================================\n";
while (inFile.read(reinterpret_cast<char *> (&lego), sizeof(legoset)))
{
lego.report();
}
inFile.close();
}
void intro()
{
std::cout << "\n\n\n\t LEGOSET";
std::cout << "\n\n\tMANAGEMENT";
std::cout << "\n\n\t SYSTEM";
std::cout << "\n\n\n\nMADE BY : Philippe Barry";
std::cin.get();
}
//***************************************************************
// END OF PROJECT
//***************************************************************
Note that array indices in C++ go from 0 to one less than the array size. Thus index 0 is the first element, index 1 is the second, etc. Thus if you declare a char array to be size 25, then accessing index 25 is past the end of the array and results in undefined behavior — your program may crash, freeze up, or literally anything else. Additionally, accessing index 24 would just give you the “null character” that comes after every string. If you’re sure that the input will be 24 characters long (and you shouldn’t be), then index 23 would contain the last character.
You really shouldn’t be using static-length char arrays in C++, anyway. Your current code, even if it worked most of the time with the char arrays, would fail when the input string was larger than the size of the array. Replace the types of all the char arrays with std::string, and the input function should work.
Furthermore, as Sam Varsavchik nicely put, don’t write an entire program at once. That makes it a nightmare to debug. Write your code in chunks — first write the input function, and a debug function that prints out the values of all the member variables. Debug that bit first, then go on to the rest.
I'm creating a board game (stratego) in c++ and was wondering if it considered a poor practice to return an integer from a class method in order to determine which case in a switch statement to show to the user.
Example:
In stratego, you can't attack board pieces that are part of your own army so I have a message "You cannot attack your own army" when the user tries to do so.
Same thing if a movement is performed that would result in the player jumping off the board, moving too many spaces, etc.
Each of these invalid movements has it's own unique message, but to avoid printing them from the Class.cpp file, which is where the player's moves are validated, I have the Class.cpp file returning an integer to a switch statement in the main() that it was called from.
What is the most recommended way to handle how the messages get called?
class Test
{
public:
Test()
{
}
int Validate_Move(int valid)
{
if (valid > 0 && valid < 5)
{
return 1;
}
else if (valid > 5)
{
return 2;
}
}
};
int main()
{
int entry;
std::cout << "Enter move: ";
std::cin >> entry;
Test obj;
switch (obj.Validate_Move(entry))
{
case 1:
std::cout << "Move is valid" << std::endl;
case 2:
std::cout << "Move is invalid" << std::endl;
default:
std::cout << "Error occured" << std::endl;
}
return 0;
}
There's nothing wrong with that technique. If you want to be more explicit, you could always make an enum
class Test
{
public:
Test() = default;
enum EValidity {eError, eValid, eInvalid};
EValidity Validate_Move(int valid)
{
if (valid > 0 && valid < 5)
{
return eValid;
}
else if (valid > 5)
{
return eInvalid;
}
else
{
return eError;
}
}
};
int main()
{
int entry;
std::cout << "Enter move: ";
std::cin >> entry;
Test obj;
switch (obj.Validate_Move(entry))
{
case Test::eValid:
std::cout << "Move is valid" << std::endl;
break;
case Test::eInvalid:
std::cout << "Move is invalid" << std::endl;
break;
case Test::eError:
std::cout << "Error occured" << std::endl;
break;
default:
assert(false);
}
return 0;
}
Below is the code for STACK with no overflow since I am using vector concept. Program seems to be working fine as long as I push integers, but as soon as I push float value (for testing) the output screen goes to infinite loop and debugger doesn't even stop at cin statement and it simply crosses it without giving the control to the console window.
#include"iostream"
class Mystack
{
private:
int *input;
int top;
int capacity;
public:
Mystack();
~Mystack();
void push(int x);
int pop();
int topElement() const;
bool isEmpty() const;
void print();
};
Mystack::Mystack()
{
top = -1;
capacity = 5;
input = new int[capacity];
}
Mystack::~Mystack()
{
delete[]input;
}
void Mystack::push(int x)
{
if (top + 1 == capacity)
{
int *vec = new int[capacity+capacity];
for (int i = 0; i <=top; i++)
{
vec[i] = input[i];
}
input = vec;
capacity = capacity * 2;
top++;
input[top] = x;
}
else
{
top++;
input[top] = x;
}
}
int Mystack::pop()
{
if (isEmpty())
{
throw std::out_of_range("Stack Underflow");
}
else
{
std::cout << "The popped element is" << input[top];
return input[top--];
}
}
bool Mystack::isEmpty() const
{
if (top == -1)
{
std::cout << "Is Empty" << std::endl;
return true;
}
else
{
std::cout << "Not Empty" << std::endl;
return false;
}
}
int Mystack::topElement() const
{
if (top == -1)
{
throw std::out_of_range("No Element to Display");
}
else
{
std::cout << "The top element is : " << input[top];
return input[top];
}
}
void Mystack::print()
{
for (int i = 0; i <= top; i++)
{
std::cout << input[i] << " ";
}
}
int main()
{
Mystack s1;
int num, ch = 1;
while (ch >0)
{
std::cout << "\n1. PUSH" << std::endl;
std::cout << "2. TOP" << std::endl;
std::cout << "3. IsEmpty" << std::endl;
std::cout << "4. POP" << std::endl;
std::cout << "5. EXIT" << std::endl;
std::cout << "6. Print" << std::endl;
std::cout << "Enter the choice" << std::endl;
std::cin >> ch; // DEBUGGER DOES NOT GIVE CONTROL TO CONSOLE WINDOW AND ASK FOR INPUT ONCE I PUT FLOAT VALUES, IT SIMPLE CROSSES IT
switch (ch)
{
case 1:
std::cout << "Enter the number to be pushed" << std::endl;
std::cin >> num;
s1.push(num);
break;
case 2:
std::cout << "Get the TOP Element" << std::endl;
try
{
s1.topElement();
}
catch (std::out_of_range &oor)
{
std::cerr << "Out of Range error:" << oor.what() << std::endl;
}
break;
case 3:
std::cout << "Check Empty" << std::endl;
s1.isEmpty();
break;
case 4:
std::cout << "POP the element" << std::endl;
try
{
s1.pop();
}
catch (const std::out_of_range &oor)
{
std::cerr << "Out of Range error: " << oor.what() << '\n';
}
break;
case 5: exit(0);
case 6:
s1.print();
break;
default:
std::cout << "Enter a valid input";
break;
}
}
std::cin.get();
}
Once you input the int value for example as 1.1 (invalid int value). Input conversion error occurs and the input stream because of invalid data ignores the rest of the operation even the cin. Make your code more generic in order for it to handle float or double or char.
I have this vector class, and I was provided with a driver to test the class. Most of it seems to work fine but I think there is something wrong with the exceptions part (which I haven't quite fully understood)
Here is the code for the class .cpp file
int myVector::at(int i)
{
if(i<vsize)
return array[i];
throw 10;
}
and here is the driver code
#include "myVector.h"
#include <iostream>
using namespace std;
int main()
{
// Create a default vector (cap = 2)
myVector sam;
// push some data into sam
cout << "\nPushing three values into sam";
sam.push_back(21);
sam.push_back(31);
sam.push_back(41);
cout << "\nThe values in sam are: ";
// test for out of bounds condition here
for (int i = 0; i < sam.size( ) + 1; i++)
{
try
{
cout << sam.at(i) << " ";
}
catch(int badIndex)
{
cout << "\nOut of bounds at index " << badIndex << endl;
}
}
cout << "\n--------------\n";
// clear sam and display its size and capacity
sam.clear( );
cout << "\nsam has been cleared.";
cout << "\nSam's size is now " << sam.size( );
cout << "\nSam's capacity is now " << sam.capacity( ) << endl;
cout << "---------------\n";
// Push 12 values into the vector - it should grow
cout << "\nPush 12 values into sam.";
for (int i = 0; i < 12; i++)
sam.push_back(i);
cout << "\nSam's size is now " << sam.size( );
cout << "\nSam's capcacity is now " << sam.capacity( ) << endl;
cout << "---------------\n";
cout << "\nTest to see if contents are correct...";
// display the values in the vector
for (int i = 0; i < sam.size( ); i++)
{
cout << sam.at(i) << " ";
}
cout << "\n--------------\n";
cout << "\n\nTest Complete...";
cout << endl;
system("PAUSE");
return 0;
}
Any help is appreciated. Thanks
The driver that you have provided:
try {
cout << sam.at(i) << " ";
}
catch(int badIndex) {
cout << "\nOut of bounds at index " << badIndex << endl;
}
expects that int will be thrown (a bit weird design, but well... this is the code that will use your class...). Your implementation of at() might look like this:
int& myVector::at(int i) throw(int) {
if (i < vsize)
return array[i];
throw i;
}
just try to follow one simple rule: throw by value, catch by reference.
Also note that you have a pointer:
private:
int* array;
which points to dynamically allocated memory allocated in constructor and copy constructor and freed in destructor :
myVector::myVector(int i)
{
...
array = new int[maxsize];
}
myVector::myVector(const myVector& v)//copy constructor
{
...
array =new int[maxsize];
}
myVector::~myVector()
{
delete[] array;
}
But how about the assignment operator ? See What is The Rule of Three?
Your stop condition of for loop ends it one element after the last one (i.e. you cannot access 4th element of sam vector because there are only three elements).
std::vector::at throws std::out_of_range exception in such situation (see: http://en.cppreference.com/w/cpp/container/vector/at), not int one. So you should change your exception handling part to something like this:
#include <exception>
try
{
cout << sam.at(i) << " ";
}
catch(std::out_of_range exc)
{
cout << "\nOut of bounds at index " << exc.what() << endl;
}