How to add new objects to vector in C++ - c++

I am trying to create a program which allows a user to add an object of class called Vehicle to an inventory that is stored in a vector. The vector has an initial size of zero. Each object is a vehicle that the user enters the attributes of.
What I cannot wrap my head around is how to let the user keep adding vehicles if each vehicle needs to be its own separate object. How do you let C++ determine what the name of new objects should be if the user decides to keep adding more vehicles (objects) to the inventory (vector called carList).
Could someone guide me in the right direction? I apologize if this is obvious, I am new to the language. Must I do something that involves dynamically allocating objects or something similar?
Here is my (incomplete) code:
void addVehicle(vector<Vehicle> carList)
{
char stop; // Needed for stopping the do-while loop
string VIN = "", // Needed to hold user input for the VIN
Make = "", // Needed to hold user input for the Make
Model = ""; // Needed to hold user input for the Model
int Year = 0; // Needed to hold user input for the Year
double Price = 0.0; // Needed to hold user input for the Price
cout << "You have chosen to add a vehicle to your inventory.\n\n";
do
{
cout << "There are currently " << carList.size() << " vehicles in your inventory.\n\n"
<< "\t\t\tVehicle #" << (carList.size() + 1) << ": \n"
<< "\t\t___________________________\n\n";
Vehicle /*new object needs to go here*/
carList.push_back(/*new object from the line above*/);
// Prompt user to input VIN
cout << "VIN: ";
cin >> VIN;
// Prompt user to input Make
cout << "Make: ";
cin.ignore();
getline(cin, Make);
// Prompt user to input Model
cout << "Model: ";
getline(cin, Model);
// Prompt user to input Year
cout << "Year: ";
cin >> Year;
// Prompt user to input Price
cout << "Price: $";
cin >> Price;
Call to the overloaded constructor to store user input in object
/*(newly created object)*/.Vehicle::Vehicle(VIN, Make, Model, Year, Price);
// Ask user if they would like to enter another vehicle
cout << "\nWould you like to enter another vehicle? (Y/N):";
cin.ignore();
stop = cin.get();
} while (stop != 'N');
}
Any help would be appreciated. Thanks!

How about you first create the object and then push a copy into the vector?
Call to the overloaded constructor to store user input in object
Vehicle temp(VIN, Make, Model, Year, Price);
carList.push_back(temp);
But there's no need for the variable, really:
Call to the overloaded constructor to store user input in object
carList.push_back(Vehicle(VIN, Make, Model, Year, Price));
And if you have C++11, you can even construct the object directly in place:
Call to the overloaded constructor to store user input in object
carList.emplace_back(VIN, Make, Model, Year, Price);
Look ma, no copies!

Related

c++ User input validation in sorted array

Hello i have a assinment that im making a weater program where we ask the user to enter info
first enter how many citys to use
then enter city name and degrees
then i will print out the list in order starting with the coldest city
and last i need to add a search funkar to search by degrees to find a location with that degrees
this one i havent started with
but my MAIN problem is that i need to validate that the user input is between -60 and 60 when enter the city and degrees... i just dont get it to work with anything... can someone please help out?`
cout<<"Enter Name of City and degrees \n\n";
for(i=0;i<n;i++){
cout<<"---------\n";
cin>>s_array[i].name;
cin>>s_array[i].degrees;
this is the code where user put in city and degree EX Rio 50
i just dont know how to validate it to be between -60 and 60`
What you're looking for, is simple data validation.
Assuming you have a struct City:
// used to hold the data
struct City {
string name;
double degrees;
};
and in your main(), you have initialised an array of these structs:
bool temperatureValid(const City);
int main() {
const int32_t totalCities = 12;
City cities[totalCities];
for (int32_t i = 0; i < totalCities; i++) {
// add data to structs
cout << "Enter city name: ";
cin >> cities[i].name; // you might want to validate this, too
cout << "Enter temperature: ";
cin >> cities[i].degrees;
cout << cities[i].name << " has a temperature of " << cities[i].degrees << "°" << endl;
if (temperatureValid(cities[i])) {
// cool... or not
} else {
cerr << "Invalid temperature range!" << endl;
--i; // make sure we can do this one again
continue;
}
}
return 0;
}
bool temperatureValid(const City city) {
return city.degrees >= -60 && city.degrees <= 60;
}
First of all, you should create a class. I understand from your code you must use class. If you don't have to it is easier than this. Then you should create an object.
Basic logic below here. You should create a class well.
class Weather //create class
Weather city // create object
cout<<"Please enter a city name:"<<endl;
cin>>city.name;
cout<<"Please enter a city degree:"<<endl;
cin>>city.degrees;

A decision condition is triggered without input

I am currently working on a very simple project and I found a problem in the testing phase when I tried to enter his name for the new employee and the decision condition was suddenly triggered, I am not sure why this happened. Based on my limited coding experience, in general, a statement in an output judgment statement needs to fulfil a judgment condition, but why would a judgment condition be triggered if I didn't do any input? Thank you all for your help.
Here is a part of the code.
void Management::Add_Staff() {
std::cout << "Please enter the number of staffs you want to add: " << std::endl;
int addNum = 0; // saves the amount entered by the user
std::cin >> addNum;
while (addNum <= 0 || addNum >= 50) {
std::cout << "Invaild number. Please try again" << std::endl;
std::cout << "Please enter the number of staffs you want to add: " << std::endl;
std::cin.clear(); // clear error enter
std::cin.ignore(INT_MAX, '\n'); // INT_MAX means an extremely large number,'\n' means empty space
std::cin >> addNum;
}
int new_Size = this->_StaffNumber + addNum; // The number of existing employees plus
// the number of new employees
Person** new_Space = new Person*[new_Size]; // Open up new space
if (this->_StaffArray !=
NULL) // if the data of the original pointer is not null
{
for (int i = 0; i < this->_StaffNumber;
i++) // data of the original pointer is added to the new pointer
{
new_Space[i] = this->_StaffArray[i];
}
}
for (int i = 0; i < addNum; i++) {
int ID; // create an variable nameed id to store the staff number entered
// from users
std::cout << "Please enter pure and positive number as the staff number of " << i + 1 << " staff: " << std::endl;
std::cin >> ID;
while (ID <= 0) {
std::cout << "Invalid staff number, please enter again: " << std::endl;
std::cin.clear();
std::cin.ignore(INT_MAX, '\n');
std::cin >> ID;
}
std::string NAME; // create an variable nameed id to store the staff
// number entered from users
std::cout << "Please enter the name: " << std::endl;
// std::cin >> NAME;
while (std::getline(std::cin, NAME)) {
if (NAME.length() == 0)
{
std::cout << "Your input is not correct. Please re-enter your name" <<
std::endl;
}
// This will check if the NAME contains only characters.
else if (std::all_of(NAME.begin(), NAME.end(), isalpha)) // isalpha: The function returns a non-zero value if the argument is an alphabetic character, or zero otherwise.
{
break;
}
else {
std::cout << "Only characters are allowed:" << std::endl;
}
}
That is my test case.
*********************************************************
********Welcome to the employee management system********
***********0.Exit the management page********************
***********1.Add the employee information****************
***********2.Display the employee information************
***********3.Delete the employee information*************
***********4.Modify the employee information************
***********5.Search the employee information************
***********6.Sort by number*****************************
Please enter the numbers 0 through 6 as your next step
1
Please enter the number of staffs you want to add:
1
Please enter pure and positive number as the staff number of 1 staff:
12
Please enter the name:
Your input is not correct. Please re-enter your name
After I entered the employee number, the judgment condition was triggered before I entered the name, but I didn't enter a space, I didn't even have time to enter something, and the judgment condition was triggered.
When you get input form the user using std::cin the input from the user does not go directly into the program. Instead that input sits in a buffer, which temperately stores that user entered data so you can later tie that data to a variable or perform some other task with that data. However, if that buffer does not get cleared and you use std::getline then std::getline will read the buffer instead of the new user input that you actually wanted. This is why its important to make use of the std::cin.ignore() function, which will clear the buffer of unwanted int and characters. If you want a more en-depth overview of std::cin.ignore() check out this link .
The Fix:
Looking at your code you do make use of cin.ignore() to clear the buffer but only the user enters something other then a number which will drop them into that while loop.
This is what you currently have:
while (ID <= 0) {
std::cout << "Invalid staff number, please enter again: " << std::endl;
std::cin.clear();
std::cin.ignore(INT_MAX, '\n');
std::cin >> ID;
}
std::string NAME; // create an variable named id to store the staff
// number entered from users
std::cout << "Please enter the name: " << std::endl;
To correct this you will need that std::cin.ignore() call out side of the while loop so that it always happens whether there is an error or not. I have a comment that says NEW CODE LINE for where I made the change.
while (ID <= 0) {
std::cout << "Invalid staff number, please enter again: " << std::endl;
std::cin.clear();
std::cin.ignore(INT_MAX, '\n');
std::cin >> ID;
}
std::cin.ignore(INT_MAX, '\n');//NEW CODE LINE
std::string NAME; // create an variable named id to store the staff
//number entered from users
std::cout << "Please enter the name: " << std::endl;

C++ How can i create Object automatically via program directly

Ok I searched for questions but couldn't get my answer, or was not using appropriate term.
if(choice == 2){
string tempName, tempAddress; int tempNic,tempContact;
cout << "\n\t\t*\tWelcome to Our Sponsor Registeration Section\t*\n\n";
cout << "Please enter your name : "; cin>>tempName;
cout << "Please enter your National Identity Card Number : "; cin>>tempNic;
cout << "Please enter your Contact Number : "; cin>>tempContact;
cout << "Please enter your Address : "; cin>>tempAddress;
// prototype Sponsor(string n, string add, int nic_n, int phone) constructor
Sponsor (Constructor goes here) // how to make many objects now?
}
the code is pasted here https://codeshare.io/aVxl42
check line 69 where i am going to use a constructor to add the values, by this i can add 1 object, but what shall i do such that if a person who is using program wants to add more objects do it?
I know i need to encapsulate something between 61 and 70.
Please help me how i work this out.
I'm guessing you want to make it loop? I'd suggest a while-loop.
I haven't used vectors in forever(professors forbid it) so I may make some mistake, but you'll get the overall point.
bool stop = false; //This is to check after each loop if it should continue or not
char contChoice;
vector<Sponsor> sponsors;
while(!stop){
if(choice == 2){
string tempName, tempAddress; int tempNic,tempContact;
cout << "\n\t\t*\tWelcome to Our Sponsor Registeration Section\t*\n\n";
cout << "Please enter your name : "; cin>>tempName;
cout << "Please enter your National Identity Card Number : "; cin>>tempNic;
cout << "Please enter your Contact Number : "; cin>>tempContact;
cout << "Please enter your Address : "; cin>>tempAddress;
// prototype Sponsor(string n, string add, int nic_n, int phone) constructor
sponsors.push_back(Sponsor(tempName, tempAddress, tempContact, tempNic));
//Add whatever other arguments you want to pass in, in whatever order
cout << "Do you want to continue? [Y/N]: "; cin>>contChoice;
if(contChoice == 'N' || contChoice == 'n')
stop = true;
else stop = false; //This isn't really necessary since it is false by default
}
}
But I would also suggest that you make set-member functions in Sponsor at least. You can also use a dynamic array and make it expand, which is trickier than a vector, way trickier in fact.

getline(cin, name) causes seemingly never-ending prompt for input

I'm writing a program that needs to read user input into a string object. I'm using getline(cin, name), but when it gets to the prompt, I can type anything in and press enter, but it'll just go to the next line and the cursor will keep blinking, prompting for more input. Essentially, the prompt for input never seems to end, no matter how many characters I type or how many times I press enter. I don't even know if it's actually sending the input into the string object. What could be causing this?
This is the entirety of the main function so far (it's not complete, the switch-case will eventually have 6 options, but it compiles without error) The relevant section begins at switch case 1:
#include <string>
#include <array>
#include <iostream>
#include "stdlib.h"
#include "Bank.h" //My own class. There is also a Bank.cpp, but I won't include the code in these unless they're deemed relevant
using namespace std;
void displayAccountInfo(); //will retrieve info on bank object
void main()
{
int accsCreated = 0; //Keeps track of how many accounts have been created so far. Allows placement of pointer to new bank object at an empty array index.
int option = 0; //Stores the option chosen by the user. Used in switch-case. Also ends do-while loop when ==6.
Bank* accounts[10]; //Will hold pointers to each bank object created by user in sequential order. No more than 10 accounts will ever be created.
Bank* accpntr; //Will point to one of the Bank objects. Used to initialize a pointer to the object in the accounts[] array.
//begin Menu prompt
do
{
cout << "[1] Create Bank object with values for accountNumber, name, and balance." << endl;
cout << "[2] Create Bank object with no parameters." << endl;
cout << "[6] End program" << endl;
cin >> option;
//begin option branch:
switch (option)
{
case 1:
{
int num; //holds account number
string name; //will hold account name as string object for use in Bank constructor
double balance; //holds account balance
cout << endl << "Enter an account number: ";
cin >> num;
cout << endl << "Enter a name for the account: ";
cin.ignore(std::numeric_limits<std::streamsize>::max()); //clears cin's buffer so getline() does not get skipped
getline(cin,name);
cout << endl << "Enter the balance of the account: ";
cin >> balance;
cout << endl;
accpntr = new Bank(num, name, balance); //creates a new bank object with attributes and a reference to it
accounts[accsCreated] = accpntr; //adds pointer to new bank object to first empty spot in array
accsCreated++; //increments total of how many bank objects have been created/what index position of accounts[] to create the next one at
} break; //end case 1
case 2:
{
accpntr = new Bank(); //creates a new bank object with an accountNumber of 9999, an empty name attribute, and a balance value of zero.
accounts[accsCreated] = accpntr; //adds pointer to new bank object to first empty spot in array
accsCreated++; //increments total of how many bank objects have been created/what index position of accounts[] to create the next one at
} break; //end case 2
case 6:
{
cout << "Ending Program." << endl;
}
} //end switch-case block
}
while (option != 6); //end menu prompt when user chooses option 6.
//end menu block
} //end function main()
The first problem is here:
cin.ignore(std::numeric_limits<std::streamsize>::max());
istream::ignore behaves like other input functions. If there's no input in the buffer, it'll block and wait until it's avaliable. It'll stop once it ignores as many characters as you told it to, or once it reaches the delimiter character (the second parameter, which you didn't specify and it defaults to traits::eof). You never even reach getline call.
To fix it, specify the delimiter:
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
With alternating prompts and inputs, which impregnates a line structure on your input, you should stick to line-oriented input and read everything as a line, and use operations that convert numeric values from strings whenever appropriate.
This should be more robust than juggling with line delimiters.

C++ file input/output and array assistance

I have a C++ project to do for my class and it's quite intricate, to me at least. I've got the general idea and concept down, but i'm running into some other problems when it comes to the arrays and file stuff. Below is what the project consists of
You will be building and modifying a class roster system for a Teacher to manage his class roster and their final grades. This program
will use functions for the various menu options, and you will work with
the data in arrays or vectors. The program will provide a menu system that allows for the teacher to perform tasks until he chooses to close the program. The program will read and write to a file called
classroster.txt. Any and all additions, deletions, or changes to the roster will be saved in classroster.txt file.
This file will contain the names of each of the students in the class with their grade. See the following for an example listed below of how the data would be stored in the classroster.txt file. You should work with the data using arrays or vectors.
Jim Jones C
Kevin James B
Marc Cohen A+
When the program starts it should read the data from the classroster.txt into arrays or vectors. While the program is running it should use the arrays or vectors for the functions while using the program. When the program ends it should overwrite the classroster.txt file if something has been changed. The
programs menu will offer the following options and will allow the user to keep performing functions until they choose to exit the program ( hint !!!!! you will need to use a loop for the menu system)
Add A New Student-
This will allow the user to add a new student to the system. The system should prompt for the new students full name and then grade.
It should validate that the grade is in the following values
(A+, A, A-, B+, B, B-,C+,C, C-, D+, D, D-, F) and if not
in the approved list it should prompt the user for a valid grade.
Change a Students Grade-
This will find the student in question and change the grade. If the specified student doesn’t exist the program should print an error message telling the user that you couldn’t find the specified student to
change their grade.
Remove a Student-
Will remove a student and their grade from the roster. If the specified student doesn’t exist the program should print an error message telling the user that you couldn’t find the specified student to remove.
Display Class Roster–
(Bonus Points if you can display the names is alphabetical order) This
function will display the list of all the students and their grades on
the screen that looks like this:
Student Name Grade
Jim Jones C
Kevin James B-
Marc Cohen A+
This is what i have so far, it's obviously not done yet
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
const int num_of_students;
const int new_student = 1, change_grade = 2, remove_student = 3, display_roster = 4, quit = 5;
int classroster[num_of_students];
int student_grade[num_of_students];
string possible_grades[13] = {"A+", "A", "A-", "B+", "B", "B-", "C+", "C", "C-", "D+", "D", "D-", "F"};
int choice;
ofstream class_file;
cout << "How many students do you have in your class?" << endl;
cin >> num_of_students;
cout << "---MENU---" << endl;
cout << "1. Add A New Student" << endl;
cout << "2. Change A Students Grade" << endl;
cout << "3. Remove A Student" << endl;
cout << "4. Display Class Roster" << endl;
cout << "5. Quit" << endl;
cout << "Enter your choice: ";
cin >> choice;
if (choice == new_student) {
for (int index = 0; index < num_of_students; index++) {
class_file.open("classroster.txt");
cout << "What is the name of the student you want to add? ";
getline(cin, classroster);
if (student_grade == possible_grades) {
cout << "What is the final grade of this student? ";
getline(cin, student_grade);
}
else {
"Please enter a valid grade!"
}
cout << "Student added!";
}
}
else if (choice == change_grade) {
class_file.open("classroster.txt");
cout << "What is the name of the student whose grade you want to change? ";
getline(cin, )
}
else if (choice == remove_student) {
}
else if (choice == display_roster) {
}
else if (choice == quit) {
}
else {
cout << "Please enter a valid choice!"
}
system("PAUSE");
return 0;
}
First, to answer your question, here's one way to search an array of student names:
int index = -1;
for(int k=0; k<num_of_students; ++k)
{
if(names[k] == name)
index = k;
}
And here's a way to change the array of grades:
student_grade[index] = 3;
More generally, you taking the wrong approach. Your code does not compile, so it looks as if you're writing it all out before testing any of it. As they never seem to teach in school, you should start with something small and simple, add complexity a little at a time, test at every step, and never add to code that doesn't work.
Let's start with the number of students:
int main() {
const int num_of_students;
cout << "How many students do you have in your class?" << endl;
cin >> num_of_students;
return(0);
}
Try to compile this, and you'll find that there's something wrong. Fix it and try constructing an array of int and filling it in. Once that's working, try an array of string. Small steps.
You realy should be using maps for this question, its makes the most sense. Here is code to read in the map from a file. After you have the map all the operations you need are already implemented in the STL. I realize you may need to use vector but I'd like to think you wouldn't be penalized for being clever and actually writing a proper solution.
#include <map>
#include <fstream>
#include <iostream>
using namespace std;
int main(){
map<string,string> data;
fstream fs("classroster.txt");
while(fs.good()){
string fname, lname, grade;
fs >> fname;
fs >> lname
fs >> grade;
fname += lname; //Concat Names to get full
if(grade == "A") //Check other grades as well.
data.emplace(fname,grade);
}
while(1){
string option;
std::cout << "Options:" << endl;
cin >> option;
//Your option selection code here
}
return 0;
}
EDIT:
maps are also sorted by key name so printing alphabetically is very easy, no sorting required.
for(auto& pairs : data)
cout << pairs.first << " " << pairs.second << endl;