Search for objects within a vector - c++

I am trying to find a way, within my code to search for an object that is in the Vectors that I have used. I am already pushing back the information into the different vectors and I know about .size to display the info. I want the user to be able to enter the bank account number then if that is correct display the contents of the other vectors.
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
//declaring four vectors
std::vector<string>names;
std::vector<string>address;
std::vector<int>age;
std::vector<double>accountnumber;
//forward declaration of functions
void namesInput ();
void addressInput ();
void ageInput ();
void accountnumberInput ();
int main()
{
//variable for switch statement
int choice;
system("title HSBC Online Banking");
system("color B6");
cout << "Please select from the following options" << endl;
cout << "----------------------------------------" << endl;
cout << "1. Enter profile " << endl;
cout << "2. Search for client " << endl;
cout << "3. Exit" << endl;
cin >> choice;
switch(choice)
{
case 1:
//calling functions for first switch case
namesInput ();
addressInput ();
ageInput ();
accountnumberInput ();
system("cls");
break;
case 2:
break;
case 3:
system("exit");
break;
}
return 0;
}
void namesInput ()
{
system("cls");
for (int i = 1; i <= 3; i++)
{
string temp;//variable to give to vector
cout<<"Enter " << i << " first, middle and last names : ";
cin>>temp;
names.push_back(temp);//push back into vector
}
}
void addressInput ()
{
system ("cls");
for (int i = 1; i <= 3; i++)
{
string temp;//variable to give to vector
cout<<"Enter " << i << " House Number, Street, Postcode : ";
cin>>temp;
address.push_back(temp);//push back into vector
}
}
void ageInput ()
{
system ("cls");
for (int i = 1; i <= 3; i++)
{
int temp;//variable to give to vector
cout<<"Enter " << i << " Day, Month, Year : ";
cin>>temp;
age.push_back(temp);//push back into vector
}
}
void accountnumberInput ()
{
system ("cls");
for (int i = 1; i <= 1; i++)
{
int temp;//variable to give to vector
cout<<"Enter " << i << " Account Number ";
cin>>temp;
accountnumber.push_back(temp);//push back into vector
}
main ();
}
void findClient ()
{
cout << "To find a client please enter their account number" << endl;
}

std::vector<double>accountnumber;
Using a double for account numbers does not seem a good choice to me: you may want to use a std::string instead.
For example: note that "exact" comparison between doubles is not possible (so searching for account numbers using doubles as keys is problematic); instead you can do that with strings.
So, assuming you use a vector<string> for account numbers, you can use std::find() to find a given account position in the vector, e.g.:
auto it = find(accountNumbers.begin(), accountNumbers.end(),
accountNumberToFind);
if (it != accountNumbers.end())
{
... Found, process it ...
}
Once you have the iterator to the found account, you can get the vector 0-based index from it using a simple pointer/iterator arithmetic like (it - accountNumbers.begin()).
Then, given this index, you can access the corresponding items in the other vectors.
However, from an object-oriented design perspective, I'd prefer defining a class for accounts, with several fields like account number, name, address, etc., and have a single vector<Account> (instead of several vectors of single account attributes).

There are some parts of your code that I'd suggest to revisit, however, according to you code, you can just do the following:
void lookForAccount(){
system ("cls");
for (int i = 1; i <= 1; i++)
{
int temp;//variable to give to vector
cout<<"Enter " << i << " Account Number you want to look for";
cin>>temp;
for(int j = 0;j<accountnumber.size();j++){
if(accountnumber[j]==temp){
cout<<"account number: "<<accountnumber[j]<<", name: "<<names[j]<<"etc..."<<endl;
}
}
}
main ();
}
Instead of this dummy method I'd anyway suggest to use iterators and std::find.
However, as pointed out in comments, this code is bug prone due to several reasons: handling account number by double is not the best choiche. Furthermore, I'd suggest to redesign your code to handle all the account information using a C++ objects.

Related

Delete data from a dynamically allocated array in c++

I am trying to delete a record from an entered position, from a dynamically allocated array in c++, and when i try to run the program it throws an error stating
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
The insertion and displaying of the records are running perfectly fine, the only thing that throws an error is delete operation.
The Code
#include <iostream>
using namespace std;
struct employee{
string name;
int empId;
string dept;
int age;
};
employee *emp = new employee[5];
void insertData(){
for (int i = 0; i<5; i++){
cout<<"Enter the Employee name"<<endl;
cin>>emp -> name;
cout<<"Enter the Employee Id"<<endl;
cin>>emp -> empId;
cout<<"Enter the Employee Department"<<endl;
cin>>emp -> dept;
cout<<"Enter the Employee age"<<endl;
cin>>emp -> age;
}
}
void displayData(){
for (int i = 0; i < 5; ++i) {
cout<<"Employee"<<i+1<<" Data"<<endl;
cout<<"Name : "<<emp -> name<<endl;
cout<<" Employe ID : "<<emp -> empId<<endl;
cout<<"Department : "<<emp -> dept<<endl;
cout<<"Age : "<<emp -> age<<endl<<endl;
}
}
void deleteData(){
int pos;
cout<<"Enter the position you want to delete Data";
cin>>pos;
if (pos>5){
cout<<"Invalid Size please enter a size smaller than 5";
}
for (int i = pos; i < 5; ++i) {
emp[i] = emp[i+1];
}
}
int menu(){
int x;
do {
int n;
cout << "Please enter the number corresponding to an operation you want to perform\n";
cout << "1. Insert Data" << endl;
cout << "2. Display Data" << endl;
cout << "3. Delete Data" << endl;
cout << "4. Exit" << endl;
cin >> n;
switch (n) {
case 1: {
insertData();
break;
}
case 2: {
displayData();
break;
}
case 3: {
deleteData();
break;
}
case 4: {
exit(0);
}
default:
cout << "Invalid Choice, Enter a valid choice";
return 1;
}
cout<<"Press 1 to continue or 0 to exit";
cin>>x;
} while (x == 1);
}
int main() {
menu();
return 0;
}
Your code has several logic issues.
Inserting and displaying data
When you insert and display data with insertData and displayData you loop over five indices (i) but you never used that variable in your loop. You simply operate all five times on the pointer to the first element in the array.
Deleting data
You print an error message if pos is greater than 5, but then you go ahead and run the rest of the function anyway. A return would break out of the function at this point. Also, I suggest writing to std::cerr for error messages.
You iterate from pos to 4, but copy from index 5, which is out of bounds. This yields undefined behavior. You should change your bounds to i < 4. Because arrays are indexed starting at 0 you also need to start at pos - 1.
You never clear out the data in the last element. As you're only deleting one record at a time, you now it'll always be the last one that needs to be cleared.
void deleteData(){
int pos;
cout<<"Enter the position you want to delete Data";
cin>>pos;
if (pos>5){
cout<<"Invalid Size please enter a size smaller than 5";
}
for (int i = pos; i < 5; ++i) {
emp[i] = emp[i+1];
}
}
Suggested:
void deleteData() {
int pos;
cout << "Enter the position you want to delete Data ";
cin >> pos;
if (pos > 5){
cout << "Invalid Size please enter a size smaller than 5\n";
return;
}
for (int i = pos - 1; i < 4; ++i) {
emp[i] = emp[i+1];
}
emp[4].name = "";
emp[4].empId = 0;
emp[4].dept = "";
emp[4].age = 0;
}
Menu
In your menu function you should initialize x to 1, as you don't error check user input at the end.
You return in the default case, which will prevent the loop from repeating to get a valid input.
You never use the return value of menu and it may not ever return, which your compiler should warn you about. The return type should be void.
void menu() {
int x = 1;
do {
int n;
cout << "Please enter the number corresponding to an operation you want to perform\n";
cout << "1. Insert Data" << endl;
cout << "2. Display Data" << endl;
cout << "3. Delete Data" << endl;
cout << "4. Exit" << endl;
cin >> n;
switch (n) {
case 1:
insertData();
break;
case 2:
displayData();
break;
case 3:
deleteData();
break;
case 4:
exit(0);
default:
cerr << "Invalid Choice, Enter a valid choice";
}
cout << "Press 1 to continue or 0 to exit";
cin >> x;
} while (x == 1);
}
Best practices
You use the magic number 5 a lot. Give it a name so it's easier to modify if needed.
const int NUM_EMPLOYEES = 5;
There are many suggestions. Your array does not have to live at a global scope. It should not. It should be declared inside main and then passed to the functions as an argument.
Further, there is no need for it to be dynamically allocated at all. If you are going to dynamically allocate with new you'll want to remember to de-allocate with delete []. Most modern desktops OSes will automatically release that memory when your program finishes, but it's a good habit to get into.
Alternatively, you can dynamically allocate with a smart pointer and the smart pointer will handle the de-allocation for you.
auto emp = std::make_unique<emp[]>(NUM_EMPLOYEES);
Incorporating some of these ideas might look like:
int main() {
employee emp[NUM_EMPLOYEES];
insertData(emp, NUM_EMPLOYEES);
return 0;
}
You tie modifying your data very closely to the UI. These can and probably should be separated. For instance, you might have a int menu() function that prompts for a menu choice and returns it, but doesn't actually do anything to the data.
int menu() {
while (true) {
cout << "Please enter the number corresponding to an operation you want to perform\n";
cout << "1. Insert Data" << endl;
cout << "2. Display Data" << endl;
cout << "3. Delete Data" << endl;
cout << "4. Exit" << endl;
int choice = 0;
cin >> choice;
if (choice < 1 || choice > 4) {
cerr << "Invalid option." << endl;
continue;
}
return choice;
}
}
You can now use this valid menu choice to decide what to do to your data.
Because all of your functions need to accept this data, you should make your collection of employees a class/struct, and implement these functions as member functions. I suspect that's a bit beyond where you're at with C++, but object oriented programming and model-view-controller design are things to read up on.
This (out of scope) memory allocation is so wrong...
employee *emp = new employee[5];
just do it:
employee emp[5];
In your deleteData() perhaps you want to set entries to zero instead of copying from the next position (I guess this is what delete denotes). For example you may want this implementation:
void deleteData(){
int pos;
cout<<"Enter the position you want to delete Data";
cin>>pos;
if (pos<5) {
emp[pos].name = "";
emp[pos].empId = 0;
emp[pos].dept = "";
emp[pos].age = 0;
} else {
cout<<"Invalid Size please enter a size smaller than 5";
}
}
This implementation prevents the potential out-of-bound errors!

Couting 2 different items in c++

I am trying to make a game selector that you put in your items and it will spit back out a random item. The final functionality of this program is that you can say how many items you want to be selected. I have the random selector working fine but I can't figure out how to change how many items to select. When I try and run this code it will print out the same item the amount of times selected. I want it to do different items. Here is my code so far:
/* Me
6-14-22
Game Selector
*/
#include <iostream>
#include <avector>
#include <random>
using namespace std;
int generated;
vector<string> gameList;
bool going = true;
string usrInp = "";
int gamesCount = 0;
int input() {
while(going){
cout << "Please enter your Items:" << endl;
getline(cin, usrInp);
cout << endl;
if(usrInp == "Done" || usrInp == "done"){
going = false;
return 0;
}
gameList.push_back(usrInp);
}
}
void pickGame() {
srand(time(0));
generated = (rand() % gameList.size());
cout << endl;
cout << gameList[generated] << endl;
}
void gamesNumber(){
cout << "Please enter the amount of games you want :" << endl;
cin >> gamesCount;
int t = 0;
while(t<=gamesCount){
if(t == gamesCount){
pickGame();
t++;
}
else{
t++;
}
}
}
/*
cin gamesCount
pick the amount of games that are in the int of gamesCount
*/
int main() {
input();
gamesNumber();
//gamesNumber();
//gameList.push_back("Minecraft");
//gameList.push_back("Film mac up");
//gameList.push_back("Raft");
//gameList.push_back("Roblox");
//gameList.push_back("Forza Horizon 4");
return 0;
}
Your game picking function looks fine, but the gamesNumber() function is kind of weird.
From what I understood, you want to pick gamesCount games. So you just need to call the pickGame function gamesCount times. Meaning that you can just use a for loop:
void gamesNumber(){
cout << "Please enter the amount of games you want :" << endl;
cin >> gamesCount;
for(int i = 0; i < gamesCount; i++) pickGame();
}

Sorting two arrays that are linked into descending order. One is a string array, one is an int array. c++

I'm still relatively new to coding and a recent assignment I had has been stumping me quite a bit.
I have two arrays that are essentially linked to one another. 0 on one side must be 0 on the other, and I need to find the easiest way to sort the one with the numbers into descending order while doing the same to the other side.
int main()
{
/// Declare Variables
int studentNum, j;
int studentGrade[20];
string studentName[20];
/// Prompt the user for the number of loops that will be required
cout << "How many students are in the class? ";
cin >> studentNum;
cout << endl;
/// Enter a for loop
for(int i=0;i<studentNum;i++)
{
/// Prompt the user to enter the names of each student in the array, as well as their respective grade.
cout << "Enter the student's name: ";
cin >> studentName[i];
cout << "Enter the student's grade (0-100): ";
cin >> studentGrade[i];
}
cout << endl << endl;
cout << setw(25) << left << "Student's Name" << setw(25)<< "Test Score" << endl;
///********Sorting block required*********
/// Enter another for loop, this time to show the array to the screen
for (int i=0;i<studentNum;i++)
{
cout << setw(25) << studentName[i] << setw(25) << studentGrade[i] << endl;
}
return 0;
}
I've looked up as many answers to this question as I can, but haven't been able to find something that would work for me. Does anyone know something I could do here? I have to keep these as two separate arrays. If possible as well, I'd like to try not using sort().
You could sort the arrays like this in a double for loop:
for(int j=0 ; j<studentNum ; j++)
for(int i=0 ; i<studentNum-1 ; i++){
if(studentGrade[i] < studentGrade[i+1]){ //swapping condition
string temp = studentName[i];
studentName[i] = studentName[i+1];
studentName[i+1] = temp;
int x = studentGrade[i];
studentGrade[i] = studentGrade[i+1];
studentGrade[i+1] = x;
}
}
If the grade of a student in the array is lower than the grade of the student next to him in the array then you could swap them and also swap their names respectively
it doesn't matter what sorting algorithm you choose, you just need to go through one of the arrays and whenever you change a cell's index you do it to the same cell index in the other array
for example:
for (int i = 0; i < size; i++){
if(arr[i]<arr[i+1]){
temp=arr[i];
temp2=arr2[i];
arr[i]=arr[i+1];
arr2[i]=arr2[i+1];
arr[i+1]=temp;
arr2[i+1]=temp2;
}
}
Use the C++ STL conventions, vector, pair and sort
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
vector<pair<string, int> > students;
cin >> n;
// Input name and grade of all students
while (n--) {
string name;
int grade;
cin >> name >> grade;
students.push_back(make_pair(name, grade));
}
// Sort students based on their grades descending
sort(students.begin(), students.end(),
[](const auto & a, const auto & b) -> bool {
return a.second > b.second;
});
// Output students' name and grade
for (auto & s : students) {
cout << setw(25) << s.first << setw(25) << s.second << endl;
}
return 0;
}

C++ Phone Book - User Input Into Arrays

I'm very new at C++ and I am having trouble with my phone book program.
The issue is when I go to add a contact, it saves the name and number in the arrays. If I choose switch case 2 after adding each contact, it'll list all the contacts and phone numbers normally. But if I select switch case 1 multiple times in a row and add more than one contact before I select switch case 2 to display all the contacts, it will only print the most recent contact I added.
The code is unfinished, but I can't seem to figure this one out! When I add more than one contact at a time, does it override the most recent one I just added? Sorry if I am not explaining this well, I'm not yet familiar with all the proper terminology!
I also don't want to use a loop for the input, so the user will not have to input ten names and numbers all at once if they don't want to. Unless there's a way to use a loop and have them end it after a certain amount of entries.
#include <iostream>
#include <cstdlib>
#include <iomanip>
#include <string>
using namespace std;
string nameArray[10];
string numberArray[10];
int arraySize = 10;
int index;
int i;
void addContact() {
// Get user input
cout << "\n\tEnter contact information" << endl;
cout << "\t==========================" << endl;
cout << "\tEnter name: ";
getline(cin, nameArray[i]);
cout << "\tEnter phone number: ";
cin >> numberArray[i];
cin.ignore();
}
void viewAll() {
// Declare variables
int pass = -1;
string tempNumber = "";
string tempName = "";
// Sort array in ascending order
for(pass=0; pass<9; pass++) {
for(index = 0; index < (9 - pass); index++) {
if(nameArray[index] > nameArray[index + 1]) {
tempName = nameArray[index];
nameArray[index] = nameArray[index + 1];
nameArray[index + 1] = tempName;
tempNumber = numberArray[index];
numberArray[index] = numberArray[index + 1];
numberArray[index + 1] = tempNumber;
}
}
}
// Print contacts after sort
cout << endl;
for(int j=0; j<arraySize; j++) {
cout << '\t' << nameArray[j] << '\t' << '\t' << numberArray[j] << endl;
}
}
void searchContact() {
}
void editContact() {
}
void deleteContact() {
}
int main() {
int choice;
while(1) {
cout << "\n\t\tMAIN MENU" << endl;
cout << "\t=======================" << endl;
cout << "\t [1] Add Contact" << endl;
cout << "\t [2] View All Contacts" << endl;
cout << "\t [3] Search Contact" << endl;
cout << "\t [4] Edit Contact" << endl;
cout << "\t [5] Delete Contact" << endl;
cout << "\t [6] Exit Program" << endl;
cout << "\t=======================" << endl;
cout << '\t';
cin >> choice;
switch(choice) {
case 1: // Add a new contact
cin.ignore();
addContact();
break;
case 2: // Print all contacts in alphabetical order
viewAll();
break;
case 3: // Search and print contact name and phone number
searchContact();
break;
case 4: // Edit a contact
editContact();
break;
case 5: // Delete a contact
deleteContact();
break;
case 6: // End program
return 0;
break;
default:
cout << "\nInvalid choice." << endl;
break;
}
}
return 0;
}
i think Johnny Mopp has given you the correct answer, but you said your new so i'd like to give you a slightly longer explanation, and a little bonus advice.
Consider your addContact function. You ask for values to be inserted into the name and numbers array at position i. You need to update that position after you add a contact or it will simply overwrite what was there previously. So a ++i; at the end of the function will solve your problem as this means next time you add a contact it goes to the next slot in the array. Now be mindful of this as your array only has (right now) 10 items in it, so once you add 10 entries i will have a value of 10 now which if you try to do nameArray[i] it would be trying to access, or worse write to, the 11th item in your array which does not exist, this is very bad (take a quick google tour of "buffer overflow error"). So make sure you add a safety check in at the start of addContact that checks if i == 10 in which case you could for example: print an error message then return from the function immediately. Definately DO NOT try to access an element of the array that does not exist.
I would also recommend explicitly initialising i to 0 just for clarity (it will be 0 because it is a global variable, but it would not be 0 if it was declared inside a function, so its a good habit to get into)
Finally, you seem to be using a mix of declaring a loop variable outside of the loop for(pass=0;...) and declaring it inside the loop for(int y = 0;...) from what i can see you dont use the variables declared outside of the loop like pass or index for anything except looping, so consider declaring them in the loop where they are used, this just keeps things a bit tidier and avoids mistakes where because the variable is still in scope someone might think its valid to use it as an array index or the likes.
Hope thats useful.

How can I use 2D array in C++ using Visual Studio?

I'm new to this site and programming in C++ language this semester.
I have been really trying for 2 days and have asked classmates but they do not know either. A classmate said to use the 2D arrays but I don't know what that is and my professor has not gone over 2D arrays.
I am stuck and would really appreciate help.
The input file contains this:
Plain_Egg 1.45
Bacon_and_Egg 2.45
Muffin 0.99
French_Toast 1.99
Fruit_Basket 2.49
Cereal 0.69
Coffee 0.50
Tea 0.75
idk how to display all the "users" orders
Basically a receipt, like he orders this and how many, then ask "u want anything else?", then take the order number and how many again, THEN at the end give back a receipt that looks like this
bacon_and_eggs $2.45
Muffin $0.99
Coffee $0.50
Tax $0.20
Amount Due $4.14
Here is my code:
// Libraries
#include <iostream>
#include <string>
#include <iomanip>
#include <fstream>
#include <cmath>
using namespace std;
//structures
struct menuItemType {
string itemName;
double itemCost;
};
// Prototypes
void header();
void readData(menuItemType menu[]);
void Display(menuItemType menu[]);
int main() {
header();
menuItemType menu [8];
readData(menu);
Display(menu);
//system("pause");
return 0;
}
void header() {
char c= 61;
for (int i=0; i < 64; i++) {
cout << c;
}
cout << c << endl;
cout << endl;
cout << "Breakfast Menu" <<endl;
for (int i=0; i < 64; i++) {
cout << c;
}
cout << "" << c << endl;
cout << endl;
}
void readData(menuItemType item[]) {
int i=0;
ifstream in;
in.open("input.txt");
cout << fixed << setprecision(2);
while(!in.eof()) {
in >> item[i].itemName >> item[i].itemCost;
++i;
}
}
void Display(menuItemType item[]) {
int choice = 0, quantity = 0;
double total = 0.0, totalF = 0.0, tax = 0.0;
char exit = 'y';
int j = 1, z = 1, i = 1;
//the Menu
for (int i=0; i<8; i++){
cout << j << ". " << setw(18) << left << item[i].itemName << "$" << setw(10) << item[i].itemCost << endl;
j++;
}
cout << endl;
while(exit == 'y' || exit == 'Y') {
cout << "Please Enter your Selection or 0 to Exit : ";
cin >> choice;
if(cin.fail()) {
cout << "*******Invalid selection*******" << endl;
cin.clear();
cin.ignore(1000,'\n');
} else if (choice==0) {break; }
else {
cout<< "Enter Quantity: ";
cin>> quantity;
if (quantity==0) { break;}
else {
choice--;
total += (quantity * item[choice].itemCost);
tax = (total * .05);
totalF = total + tax;
cout << endl;
}
cout << endl;
cout << "======================================================" << endl;
cout << item[choice].itemName << "\t\t" << item[choice].itemCost << endl;
cout << "======================================================" << endl;
cout << "Do you want to continue (Y/N): ";
cin >> exit;
}
}
}
First off, you don't need a two dimensional array for this! You already have a one dimensional array of a suitable structure, as far as I can tell: Something which stores the name of the object and its price. What is somewhat missing is how many objects are currently in the array and how much space it has. If you want to go with the content of the entire array, make sure that you objects are correctly initialized, e.g., that the names are empty (this happens automatically, actually) and that the prices are zero (this does not).
I'm not sure if it is a copy&paste errors but the headers are incorrectly included. The include directives should look something like this:
#include <iostream>
The actual loop reading the values doesn't really work: You always need to check that the input was successful after you tried to read! Also, using eof() for checking that the loop ends is wrong (I don't know where people pick this up from; any book recommending the use of eof() for checking input loops is only useful for burning). The loop should look something like this:
while (i < ArraySize && in >> item[i].itemName >> item[i].itemCost)
++i;
}
This also fixes the potential boundary overrun in case there is more input than the array can consume. You might want to consider using a std::vector<Item> instead: this class keeps track of how many elements there are and you can append new elements as needed.
Note that you didn't quite say what you are stuck with: You'd need to come up with a clearer description of what your actual problem is. The above is just correcting existing errors and readjusting the direction to look into (i.e., forget about two dimensional arrays for now).