Access reading violation when trying to use existing struct array - c++

I am writing a program for my class. My program is supposed to create a passenger list. obviously, the list has to be created first, and that option in my program works fine. However when trying to access the second function(pressing B) gives me the following error in the debugger:
Exception thrown at 0x00CD4A76 in ConsoleApplication13.exe: 0xC0000005: Access violation reading location 0x00000000.
I guess that means I am trying to read into an unallocated area in the memory, therefore, the struct array I am using was not created. I am confused since the first option does work, and I am passing the same pointer to both functions therefore the pointer points to the array created in function A.
#include <iostream>
#include <string>
#define _CRT_SECURE_NO_WARNINGS
using namespace std;
struct date
{
int year;
int day;
int month;
};
struct seat
{
int row;
char place;
};
struct pass
{
char * passname;
date bookdate;
seat location;
};
int lastindex;
int initList(pass *p, int x);
int addPass(pass *p, date *D, pass *newpass, int length);
void main()
{
pass *p = {};
int length = 0;
char choice;
do {
cout << "Welcome to FlightDesigner2017.\nEnter one of the following keys to continue:\nA: Create a list of passengers.\nB: Add a passenger to the flight.\n";
cin >> choice;
switch (choice)
{
case 'A':
{
int x;
cout << "How many passengers are on your flight? \n";
cin >> x;
length = initList(p, x);
break;
}
case 'B':
{
pass *newpass=0;
date *D = 0;
switch (addPass(p, D, newpass, length))
{
case '1':
cout << "Passenger successfully added."; break;
case '-3':
cout << "No seats available."; break;
case '-1':
cout << "Seat taken. Try again."; break;
case '-2':
cout << "Passenger is already on the flight."; break;
}
break;
}
}
}
while (choice=!0);
}
int addPass(pass *p, date *D, pass *newpass, int length)
{
#define TAKEN -1
#define SAMENAME -2
#define NOSEATS -3
#define SUCCESS 1
for (int init = 0; init < length; init++)
{
int counter=0;
for (int j = 0; j < length; j++) //empty seats check
{
if (strcmp(p[j].passname , NULL)!=0)
counter++;
}
if (counter == length)
return NOSEATS;
cout << "Enter a seat and row (seat A to F, row 1 to 50): \n"; //taken check
cin >> newpass->location.place >> newpass->location.row;
cout << "\nWhat is the flight date (DD/MM/YYYY)? \n";
cin >> D->day >> D->month >> D->year;
for (int k = 0; k < length; k++)
{
if (D->day == p[k].bookdate.day && D->month == p[k].bookdate.month && D->year == p[k].bookdate.year
&& p[k].location.place == newpass->location.place && p[k].location.row == newpass->location.row)
return TAKEN;
}
cout << "What is the passenger name? \n"; // name check
cin >> newpass->passname;
for (int i = 0; i < length; i++)
{
if (strcmp(newpass->passname,p[i].passname)==0)
return SAMENAME;
}
strcpy(newpass->passname, p[init].passname);
p[init].location.place = newpass->location.place;
p[init].location.row = newpass->location.row;
p[init].bookdate.year = D->year;
p[init].bookdate.month = D->month;
p[init].bookdate.day = D->day;
char ans;
cout << "Enter another passenger? (Y/N)\n";
cin >> ans;
if (ans == 'N')
return SUCCESS;
}
return SUCCESS;
}
int initList(pass *p, int length)
{
p = new pass[length];
for (int i = 0; i < length; i++)
p[i].passname = NULL;
return length;
}
Any explanation on how can I fix this error will help. thanks in advance.

Related

Multiple file project & Function in C++

I am trying to practice the multiple file project (creating .cpp files and also .h files) and functions together.I have some functions for different kinds of shapes which is in different .cpp files and a .h file (my Functions.h) with the prototypes of those functions. I created another .cpp file (tools.cpp) where I have all bunch of functions (such as- getInt, getFloat, getBool, getBoundedInt, getWidth etc) so that I can also use that one in my other projects as well and also for that tools.cpp file. I have tools.h file with the prototypes.
Now, I want to make another function (allFunctionController) which will handle all these different kinds of function (like- taking user input, checking input valid or invalid, help function for user, call the shape functions etc). And, there would be another function to allow user to repeat all these things and my main function will only call this one. The screenshot that I provided would be more clear to understand.
[screenshot]
tools.cpp :-
// Tools.cpp
#include"Tools.h"
#include<string>
#include<iostream>
using namespace std;
namespace tools
{
int width( int value )
{
bool isNegative = value < 0;
int spaceForSign;
if ( isNegative )
{
spaceForSign = 1;
value = -value;
}
else
spaceForSign = 0;
int digitCount = 0;
int digits = value;
do
{
// pull one digit off and count it;
++digitCount;
// if I wanted to look at the digit before throwing away:
int digit = digits % 10;
digits = digits / 10; // remove one digit
} while ( digits > 0 );
return digitCount;
}
char getChar(string prompt)
{
while (true)
{
char userInput;
cout << prompt;
cin >> userInput;
cin.ignore(999,'\n');
if ( !cin.fail() ) return userInput;
cin.clear();
cin.ignore(999,'\n');
cout << "try again" << endl;
}
}
int getInt(string prompt)
{
while (true)
{
int userInput;
cout << prompt;
cin >> userInput;
cin.ignore(999,'\n');
if ( !cin.fail() ) return userInput;
cout << "input failure, try again";
cin.clear();
cin.ignore(999,'\n');
}
}
int getBoundedInt( string prompt, int lowBound, int highBound )
{
while (true)
{
int userInput = getInt(prompt);
if ( lowBound <= userInput && userInput <= highBound )
return userInput;
cout << "must be in range " << lowBound << " to "
<< highBound << ", try again" << endl;
}
}
float getFloat(string prompt)
{
while (true)
{
float userInput;
cout << prompt;
cin >> userInput;
cin.ignore(999,'\n');
if ( !cin.fail() ) return userInput;
cout << "input failure, try again";
cin.clear();
cin.ignore(999,'\n');
}
}
string getString(string prompt)
{
while (true)
{
string userInput;
cout << prompt;
cin >> userInput;
cin.ignore(999,'\n');
if ( !cin.fail() ) return userInput;
cout << "input failure, try again";
cin.clear();
cin.ignore(999,'\n');
}
}
string getLine(string prompt)
{
while (true)
{
string userInput;
cout << prompt;
getline(cin, userInput);
if ( !cin.fail() ) return userInput;
cout << "input failure, try again";
cin.clear();
cin.ignore(999,'\n'); // whatever caused fail
}
}
bool isLowerCase( char c )
{
return 'a' <= c && c <= 'z';
}
bool isUpperCase( char c )
{
return 'A' <= c && c <= 'Z';
}
bool isLetter( char c )
{
return isLowerCase(c) || isUpperCase(c);
}
char getLetter(string prompt)
{
while (true)
{
char userInput = getChar(prompt);
if ( isLetter(userInput) )
return userInput;
cout << "letters only, please" << endl;
}
}
bool getBool(string prompt)
{
while (true)
{
switch ( getChar(prompt) )
{
case 'y': case 'Y': return true;
case 'n': case 'N': return false;
}
cout << "y or n please" << endl;
}
}
}
tools.h:-
// Tools.h
#ifndef TOOLS_LOCK
#define TOOLS_LOCK
#include<string>
namespace tools
{
int getInt(std::string prompt);
int width( int value );
char getChar(std::string prompt);
int getInt(std::string prompt);
int getBoundedInt( std::string prompt, int lowBound, int highBound );
float getFloat(std::string prompt);
std::string getString(std::string prompt);
std::string getLine(std::string prompt);
bool isLowerCase( char c );
bool isUpperCase( char c );
bool isLetter( char c );
char getLetter(std::string prompt);
bool getBool(std::string prompt);
}
#endif
My functions.h:-
// My functions.h
namespace myFunctions
{
void allFunctionController ();
void solidRectangle (int size);
void hollowRectangle (int userChoiceOfSize);
void solidTriangleFacingNorthEast (int size);
void hollowTriangleFacingNorthEast (int size);
void solidTriangleFacingSouthWest (int size);
void hollowTriangleFacingSouthWest (int size);
}
I am only adding here the hollow and solid rectangle code. But there are more shape function in my project.
hollowRectangle.cpp:-
#include"My functions.h"
#include<iostream>
using namespace std;
namespace myFunctions
{
void hollowRectangle (int size)
{
int row, column;
for (row = 1; row <= size; row++)
{
if (row > 1 && row < size)
{
cout << "*";
for (column = 2; column < size; column++)
{
cout << ' ';
}
cout << "*";
}
else
{
for (column = 1; column <= size; column++)
{
cout << "*";
}
}
}
cout << endl;
cout << endl;
cout << "Please press enter to finish...";
cin.ignore(999,'\n');
return;
}
}
solidRectangle.cpp:-
// Program for the solid rectangle
#include"My functions.h"
#include<iostream>
using namespace std;
namespace myFunctions
{
int solidRectangle (int size)
{
int row, column;
for (row = 1; row <= size; row++)
{
for (column = 1; column <= size; column++)
{
cout << "*";
}
cout << endl;
}
cout << endl;
cout << "Please press enter to finish...";
cin.ignore(999,'\n');
return 0;
}
}
allFunctionController:- I screwed up here.
// This function will control all other functions.
#include"My functions.h"
#include"Tools.h"
#include<iostream>
using namespace std;
void allFunctionController ()
{
using namespace tools;
{
int size = getBoundedInt ("Please enter the size", 1, 75);
}
}
using namespace myFunctions;
{
void getHelp ()
{
int size,userInput;
cin >> userInput;
switch (userInput)
{
case 1:
solidRectangle (size);
}
}
}
I want to know how to handle all these header files and use the function in my allFunctionController function.
I didn't write my main function yet. Please let me know if there is anything wrong in my posting either code or attachment. Thanks in advance.

why is loop stuck

Only problems remaining now are that my choice while loop is infinite since the break statements dont seem to be breaking out of the loop at all, so the program doesn't read the answer loop. Also, "Invalid Entry" displays every other incorrect input instead of displaying everytime an invalid character is entered
#include <iostream>
#include <cctype>
using namespace std;
int getAges(int age, const int SIZE);
char getChoice();
void displayInOrder(int numbers[], const int SIZE, char choice);
void displayInReverse(int numbers[], const int SIZE, char choice);
int main()
{
const int SIZE = 5;
int numbers[SIZE] = { 1, 2 ,3 ,4, 5 };
char answer = 0;
int age = 0;
char choice = 0;
while (choice = getChoice())
{
if (toupper(choice) == 'O')
{
displayInOrder(numbers, SIZE, choice);
break;
}
else if (toupper(choice) == 'R')
{
displayInReverse(numbers, SIZE, choice);
break;
}
else
{
cout << "Invalid entry! - Must be O or R\n\n";
break;
}
}
while (toupper(answer) == 'Y')
{
system("cls");
age = getAges(age, SIZE);
choice = getChoice();
displayInOrder(numbers, SIZE, choice);
displayInReverse(numbers, SIZE, choice);
cout << "Run program again (Y or N)? ";
cin >> answer;
if (toupper(answer) == 'N')
{
exit();
}
}
return 0;
}
int getAges(int age, const int SIZE)
{
cout << "Enter " << SIZE << " ages: \n\n";
cin >> age;
cout << endl;
cin >> age;
cout << endl;
cin >> age;
cout << endl;
cin >> age;
cout << endl;
cin >> age;
cout << endl;
return age;
}
char getChoice()
{
char choice;
cout << "How do you want to see the ages displayed? \n\n Enter O for In Order, or R for In Reverse.\n\n";
cin >> choice;
return choice;
}
void displayInOrder(int numbers[], const int SIZE, char answer)
{
cout << "Here are the ages in order: \n\n";
for (int i = 0; i < SIZE; i++)
{
cout << numbers[i] << endl;
}
}
void displayInReverse(int numbers[], const int SIZE, char answer)
{
cout << "Here are the ages in reverse order: \n\n";
for (int i = SIZE - 1; i >= 0; i--)
{
cout << numbers[i] << endl;
}
}
1."Invalid Entry" displays every other incorrect input: you have a getChoice() call inside the while loop, here:
else
{
cout << "Invalid entry! - Must be O or R\n\n";
choice = getChoice();
}
which is followed by a getChoice() call in the
while (choice = getChoice())
Hence the previous getChoice() is not processed.
2."I'm not sure how to close the program if the user enters N for answer", You should think about if you can ever reach the second while loop and where you are setting the answer variable or basically where you are taking the user input for ending the program? You should see if it can it be taken care of in the first while loop ?

Why does my program skip the first function? (Beginner C++)

I don't understand why getAges is being skipped.
#include <iostream>
#include <cctype>
using namespace std;
int getAges(int age, const int SIZE);
char getChoice();
void displayInOrder(int numbers[], const int SIZE, char choice);
void displayInReverse(int numbers[], const int SIZE, char choice);
int main()
{
const int SIZE = 5;
int numbers[SIZE] = { 1, 2 ,3 ,4, 5 };
char answer;
int age;
char choice;
if (toupper(choice) == 'O')
{
displayInOrder(numbers, SIZE, choice);
}
else if (toupper(choice) == 'R')
{
displayInReverse(numbers, SIZE, choice);
}
else
{
cout << "Invalid entry! - Must be O or R\n\n";
}
if (toupper(answer) == 'Y')
{
system("cls");
age = getAges(age, SIZE);
choice = getChoice();
displayInOrder(numbers, SIZE, choice);
displayInReverse(numbers, SIZE, choice);
cout << "Run program again (Y or N)? ";
cin >> answer;
break;
}
else if (toupper(answer) == 'N')
{
return 0;
}
return 0;
}
int getAges(int age, const int SIZE)
{
cout << "Enter " << SIZE << " ages: \n\n";
cin >> age;
cout << endl;
cin >> age;
cout << endl;
cin >> age;
cout << endl;
cin >> age;
cout << endl;
cin >> age;
cout << endl;
return age;
}
char getChoice()
{
char choice;
cout << "How do you want to see the ages displayed? \n\n Enter O for In Order, or R for In Reverse.\n\n";
cin >> choice;
return choice;
}
void displayInOrder(int numbers[], const int SIZE, char answer)
{
cout << "Here are the ages in order: \n\n";
for (int i = 0; i < SIZE; i++)
{
cout << numbers[i] << endl;
}
}
void displayInReverse(int numbers[], const int SIZE, char answer)
{
cout << "Here are the ages in reverse order: \n\n";
for (int i = SIZE - 1; i >= 0; i--)
{
cout << numbers[i] << endl;
}
}
I started working on this before the OP updated the title to their original question about "while loops & break statements". However at the time I came across this question the OP had originally removed the while loops. I was looking over the provided functions to get an idea of what the OP was trying to do and this is what I have come up with.
First: while loops are exactly what you want here, but you want a specific type of while loop, a do-while loop in this case.
Next: There is no need for break statements if you know how to structure your do-while loop correctly.
Finally: I made some modifications to the OP's existing functions by changing or removing unnecessary parameter(s), return type(s) & code duplication. I removed a function that was no longer needed. I changed the output formatting of the messages to display a clean looking program. I also removed a bad practice of having using namespace std; in the global scope.
I did this to demonstrate to the OP how a while loop can be constructed without the need of break statements and that they were originally on the right track but needed a little bit of assistance to get on their way.
Here is the source code to a working program on what I think the OP was aiming to do.
#include <iostream>
#include <cctype>
void getAge( int& age );
void displayInOrder( int numbers[], const int SIZE);
void displayInReverse( int numbers[], const int SIZE );
int main() {
const int SIZE = 5;
int numbers[SIZE] = { 0 };
char answer = '\0';
int age = 0;
char choice = '\0';
std::cout << "========================================================================\n"
<< "This program will have the user enter in "
<< SIZE
<< " Ages. \nThen ask the user in which order to display the list of ages.\n"
<< "Finally the program will ask the user if they want to continue or not.\n"
<< "========================================================================\n\n";
do {
for ( int i = 0; i < SIZE; i++ ) {
getAge( age );
numbers[i] = age;
}
std::cout << "\nPlease enter 'O' for ordered or 'R' for reversed list.\n";
std::cin >> choice;
if ( toupper( choice ) == 'O' ) {
displayInOrder( numbers, SIZE );
}
if ( toupper( choice ) == 'R' ) {
displayInReverse( numbers, SIZE );
}
std::cout << "\nDo you want to run program again (Y/N)?";
std::cin >> answer;
} while ( toupper( answer ) == 'Y' );
return 0;
}
void getAge( int& age ) {
int temp;
std::cout << "Enter an age: \n";
std::cin >> temp;
age = temp;
}
void displayInOrder( int numbers[], const int SIZE ) {
std::cout << "\nHere are the ages in order: \n";
for ( int i = 0; i < SIZE; i++ ) {
std::cout << numbers[i] << std::endl;
}
}
void displayInReverse( int numbers[], const int SIZE ) {
std::cout << "\nHere are the ages in reverse order: \n";
for ( int i = SIZE - 1; i >= 0; i-- ) {
std::cout << numbers[i] << std::endl;
}
}

Regarding Structs and Using Them With Array's

I'm trying to write a program that will take every line from a text file and load the value into an array. For some reason however, when I try create a dynamic array and try to put information in any position beyond 0, the information from from position zero gets copied over and I can't seem to understand why. Specifically in this program its in the readInventory function I have written. Basically, why can't I copy one struct to the other?
Sample from file
A009 Strawberries_Case 0 12.50 8
4028 STRAWBERRIES_PINT 0 0.99 104
4383 MINNEOLAS 1 0.79 187.3
4261 Rice_1_LB_Bag 0 0.49 107
Code from program
#include <iostream>
#include <string>
#include <cstring>
#include <iomanip>
#include <fstream>
using namespace std;
struct Product
{
string PLU;
string name;
int salesType;
double unitPrice/*rice per pound*/;
double inventory;
};
struct ItemSold
{
string PLU;
string name;
double cost;
};
Product *inventoryLevels = new Product[100];
ItemSold *itemsSold = new ItemSold[100];
bool readInventory(string filename, int &numberOfItems);
double checkout(int inventoryLength);
double price(string PLU, double units);
int typeCheck(string PLU, int inventoryLength);
string nameCheck(string PLU, int inventoryLength);
int main()
{
int numberOfItems = 0;
string filename = "products.txt";
int total;
if (readInventory(filename, numberOfItems))
{
cout << "Inventory file has errors, please make changes before continuing" << endl << endl;
}
total = checkout(numberOfItems);
cout << total;
system("pause");
}
double checkout(int inventoryLength)
{ // Function that will be used to perform the checkout by the user
string PLU = "1";
double units/*pounds*/;
int salesType;
int counter = 0;
int temp;
double total = 0;
while (PLU != "0")
{
cout << "Enter a PLU: ";
cin >> PLU;
itemsSold[counter].PLU = PLU;
if (PLU == "0")
{
// do nothing
}
else
{
itemsSold[counter].name = nameCheck(PLU, inventoryLength);
if (typeCheck(PLU, inventoryLength) == 0)
{
cout << " Enter the number of units being bought: ";
cin >> units;
while (units > inventoryLevels[counter].inventory)
{
cout << "You have entered in more units than we have on hand \n Please reduce the number of units being bought\n";
cout << " Enter the number of units being bought: ";
cin >> units;
}
itemsSold[counter].cost = price(PLU, units);
inventoryLevels[counter].inventory -= units;
}
else
{
cout << "Enter the number of pounds of the item being bought: ";
cin >> units;
itemsSold[counter].cost = price(PLU, units);
while (units > inventoryLevels[counter].inventory)
{
cout << "You have entered in more pounds than we have on hand \n Please reduce the number of pounds being bought\n";
cout << "Enter the number of pounds of the item being bought: ";
cin >> units;
}
inventoryLevels[counter].inventory -= units;
}
counter++;
}
}
temp = counter;
while (temp >= 0)
{
total += itemsSold[temp].cost;
temp--;
}
return total;
}
string nameCheck(string PLU, int inventoryLength)
{
for (int k = 0; k < inventoryLength; k++)
{
if (inventoryLevels[k].PLU == PLU)
{
return inventoryLevels[k].name;
}
}
return "We are currently out of stock of this item.";
}
int typeCheck(string PLU, int inventoryLength)
{
for (int k = 0; k < inventoryLength ; k++)
{
if (inventoryLevels[k].PLU == PLU)
{
return inventoryLevels[k].salesType;
}
}
}
double price(string PLU, double units)
{ //
double price;
for (int k = 0; k < 100; k++)
{
if (inventoryLevels[k].PLU == PLU)
{
price = units * (inventoryLevels[k].unitPrice);
return price;
}
}
}
bool readInventory(string filename, int &numberOfItems)
{
// File object
fstream inventory;
// Some temp variable used to validate information is still in file while it is being transfered to array
//string temp;
// Open the inventory file
inventory.open(filename);
// Will temporarily hold the properties of an item until loaded onto the array
Product temp;
// Counter will allow for a new item to be stored onto the next available location in the array
int counter = 0;
// Will demonstrate whether or not there is an error
int error = 0;
// Store items and their properties in the global array
while (inventory >> temp.PLU >> temp.name >> temp.salesType >> temp.unitPrice >> temp.inventory)
{
// Checks to see if they
if ((temp.PLU.at(0) > 57) || (temp.PLU.at(1) > 57) || (temp.PLU.at(2) > 57) || (temp.PLU.at(3) > 57))
{
error++;
}
else
{
inventoryLevels[numberOfItems].PLU = temp.PLU;
inventoryLevels[numberOfItems].name = temp.name;
inventoryLevels[numberOfItems].salesType = temp.salesType;
inventoryLevels[numberOfItems].unitPrice = temp.unitPrice;
inventoryLevels[numberOfItems].inventory = temp.inventory;
numberOfItems++;
counter++;
}
}
// If there is no error return true
if (error == 0)
{
return false;
}
// If there is an error return false
else if (error > 0)
{
return true;
}
}
When you assign values here,
while (inventory >> temp.PLU >> temp.name >> temp.salesType >> temp.unitPrice >> temp.inventory)
Am I right to assume that the input file is in the format (since you're assigning each line to the variables?
line 1: Some string you want assigned to PLU
line 2: Some string you want assigned to name
line 3: Some Int you want assigned to salestype
..........
..........
line n:string PLU

Can i check if entered value is string or integer in c++

I want to check if the user entered value is a string or an integer. The input is taken as cin>>obj[i].int_code; in the code.
The problem is that if user enter any string instead of an integer, the program goes in an infinite loop.
#include<iostream>
using namespace std;
class item{
public:
int int_code;
string str_name;
};
item obj[100];
main(){
int c,i=0,int_cd,n=0,pos=0;
do{
cout<<"\n_______YOUR OPTIONS________\n";
cout<<"\t1.Add Item\n\t2.View Item\n\t3.Delete Item\n\t4.List Item\n\t5.Exit\n";
cout<<"Enter your choice: ";
cin>>c;
switch(c){
case 1://Add Item
cout<<"Enter the item_code: ";
cin>>obj[i].int_code;
cout<<"Enter the item_name: ";
cin>>obj[i].str_name;
i++;
n++;
break;
case 2://View item
cout<<"Enter the item_code: ";
cin>>int_cd;
for(i = 0;i < n;i++)
if(int_cd == obj[i].int_code)
cout<<obj[i].int_code<<"\t"<<obj[i].str_name<<"\n";
break;
case 3://Delete Item
cout<<"Enter the item_name: ";
cin>>int_cd;
for(i = 0;i < n; i++)
if(int_cd==obj[i].int_code)
pos=i;
for(i=pos;i<n;i++){
if(obj[i].int_code != NULL)
obj[i]=obj[i+1];
else
obj[i].int_code=NULL;
//obj[i].str_name=;
}
n--;
break;
case 4://list Item
for(i=0;i<n;i++)
cout<<obj[i].int_code<<"\t"<<obj[i].str_name<<"\n";
break;
default:
cout<<"Enter any number between 1 to 5";
break;
}
}while( c != 5 );
}
enter code here
Use boost::lexical_cast:
string str;
cin >> str;
int val;
try
{
val = lexical_cast<int>(str));
}
catch(const bad_lexical_cast &)
{
// not an int
}
change your line
from
cin>>c;
to
c = -1;
cin>>c;
if (c < 1 || c > 5)
{
cout<<"Enter any number between 1 to 5";
continue;
}
As an alternative to lexical_cast you could do something like this:
#include <iostream>
static const int ZERO_ASCII = 48;
static const int MAX_OPTION = 5;
static const int MIN_OPTION = 1;
int main() {
std::string input;
std::cin >> input;
if(input.length() > 1 ){
std::cout << "Not correct length" << input << std::endl;
return -1; // in your case use "continue"
}
char val = *(input.c_str());
int intVal = static_cast<int>(val);
int option = intVal - ZERO_ASCII; // see your printed out ASCII chart :)
if (MIN_OPTION > option || option > MAX_OPTION) {
std::cout << "Not valid value " << option << std::endl;
return -1; // in your case use "continue"
}
std::cout << "selected option " << option << std::endl;
}
This is a valid option because of a couple of things:
Your user is giving you a random string value. So your program
should read a random string value and then validate it.
You can apply any kind of checking on it you like. Here I have checked that
it is one character long and that the value is the ASCII
representation of a digit, and that the digit is in a range.
For simple validation it is less costly to do if statements than exceptions as users often give you garbage input.
Exit when Not A Number :
#include<iostream>
using namespace std;
class item{
public:
int int_code;
string str_name;
};
item obj[100];
main(){
int c,i=0,int_cd,n=0,pos=0;
do{
cout<<"\n_______YOUR OPTIONS________\n";
cout<<"\t1.Add Item\n\t2.View Item\n\t3.Delete Item\n\t4.List Item\n\t5.Exit\n";
cout<<"Enter your choice: ";
cin >> c;
if (!cin) break;
switch(c){
case 1://Add Item
cout<<"Enter the item_code: ";
cin>>obj[i].int_code;
cout<<"Enter the item_name: ";
cin>>obj[i].str_name;
i++;
n++;
break;
case 2://View item
cout<<"Enter the item_code: ";
cin>>int_cd;
for(i = 0;i < n;i++)
if(int_cd == obj[i].int_code)
cout<<obj[i].int_code<<"\t"<<obj[i].str_name<<"\n";
break;
case 3://Delete Item
cout<<"Enter the item_name: ";
cin>>int_cd;
for(i = 0;i < n; i++)
if(int_cd==obj[i].int_code)
pos=i;
for(i=pos;i<n;i++){
if(obj[i].int_code != 0)
obj[i]=obj[i+1];
else
obj[i].int_code= 0;
//obj[i].str_name=;
}
n--;
break;
case 4://list Item
for(i=0;i<n;i++)
cout<<obj[i].int_code<<"\t"<<obj[i].str_name<<"\n";
break;
default:
cout<<"Enter any number between 1 to 5";
break;
}
}while( c != 5 );
}
Please note that the "check if entered value is a string or integer" part is an issue in multiple parts of the application. Namely, case 1, 2, and 3 all expect integer inputs (case 3 is addressed further below). The get_int and get_string methods are adapted from How to make cin take only numbers. Initially I only created a get_int method; however, I found that a get_string was also needed otherwise the "Enter your choice" would occur twice, rather than once, after a "Add Item", case 1, was completed.
Additionally, the "Delete Item", case 3, had an error in the wording as the request is for the "item_name"; however, the cin is expecting an integer, and not a string, so I modified the wording there as well as the input method. I commented out the cout statement in the default as it is now redundant if a previous case was not applicable to the entered value. Lastly, the "Delete Item" code still had a bug in it (fixed below) as a request to delete item_code 2 would delete an item_code 1 if that was only contained item due to pos not being reset.
#include <iostream>
#include <limits>
#include <sstream>
#include <string>
using namespace std;
class item
{
public:
int int_code;
string str_name;
};
item obj[100];
string get_string(string message)
{
string line = "";
string rs = "";
cout << message;
getline(cin, line);
stringstream ss(line);
ss >> rs;
return rs;
}
int get_int(string message)
{
int ri = -1;
string line = "";
bool isint = false;
while (!isint)
{
cout << message;
getline(cin, line);
stringstream ss(line);
if (ss >> ri)
{
if (ss.eof())
{ // Success
isint = true;
}
}
}
return ri;
}
int main (int argc, char ** argv)
{
int c,i=0,int_cd,n=0,pos=0;
do
{
cout<<"\n_______YOUR OPTIONS________\n";
cout<<"\t1.Add Item\n\t2.View Item\n\t3.Delete Item\n\t4.List Item\n\t5.Exit\n";
c = get_int("Enter your choice: ");
switch(c){
case 1://Add Item
obj[i].int_code = get_int("Enter the item_code: ");
obj[i].str_name = get_string("Enter the item_name: ");
i++;
n++;
break;
case 2://View item
int_cd = get_int("Enter the item_code: ");
for(i = 0;i < n;i++)
if(int_cd == obj[i].int_code)
cout<<obj[i].int_code<<"\t"<<obj[i].str_name.c_str()<<"\n";
break;
case 3://Delete Item
int_cd = get_int("Enter the item_code: ");
pos = -1;
for(i = 0;i < n; i++)
if(int_cd==obj[i].int_code)
pos=i;
// ensure specified item_code is found before deleting an item
if(pos != -1)
{
for(i=pos;i<n;i++)
{
if(obj[i].int_code != NULL)
obj[i]=obj[i+1];
else
obj[i].int_code=NULL;
//obj[i].str_name=;
}
n--;
}
break;
case 4://list Item
for(i=0;i<n;i++)
cout<<obj[i].int_code<<"\t"<< obj[i].str_name.c_str() <<"\n";
break;
default:
//cout<< "Enter any number between 1 to 5" << endl;
break;
}
} while( c != 5 );
return 0;
}