I have written a function in a program for entering a unique number but its not working. Something is wrong with the for loop.
I need to validate that employee id is unique.
I have made a structure named employee and "emp.id" is employee id. When the user inputs an id, it should not match previous Id's which user might have entered before. This is just a function of the main program, which validates that employee id is unique.
void uniquieid()
{
int check,i;
string code;
string tempemp1;
cout<< "enter id";
cin>> code;
while(!(num-1))
{
for(i=0;i<=num-1;i++)
{
if(emp[i].id.compare(code)==0)//comparing
{
check =1;
cout<<"enter id again";
break;
}
if(check=0) //csaasc
{
emp[i].id=code;
}
}
}
getch();
}
If the order that the ids are entered doesn't matter, I would do something like (note: untested):
using EmpIds = std::set<std::string>;
void addUniqueId(EmpIds& ids)
{
std::pair<EmpIds::iterator, bool> inserted;
const char* again = "";
do {
std::cout << "enter id" << again;
again = " again";
std::string id;
if (!(std::cin >> id))
throw std::runtime_error("No more ids!");
inserted = ids.insert(id);
} while (!inserted.second);
}
There are so many things wrong with the code, but maybe it should look more like this:
void uniqueid() {
int check=1;
string code;
string tempemp1;
cout<< "enter id";
while(check) {
cin >> code;
check = 0;
for (int i = 0; i < num; ++i) {
if (emp[i].id.compare(code)==0) {
check = 1;
cout << "enter id again";
break;
}
}
if (check==0) {
/* emp[i].id=code; */
}
}
getch();
}
Note how int check=1; starts at 1 to mean that the code needs re-entering.
So while(check) means that while the code is not unique keep going.
The for loop does the compare as before, but note the idiomatic form.
The other if (check==0) is outside the for loop and this means that no duplicates were detected so code can be used. However, I'm not sure which employee the code should apply to so I've just commented out the code.
Can you post the employee structure?
Because from this, everything looks OK, but your if function refers to emp.
So something in your structure is causing the problem.
Without your structure, anyone answering probably won't be able to find the problem.
Right now, all i can advise you to do is store employee ids in a vector and iterate through it using a for loop.
You could do
void uniqueid() {
std::vector<std::string> empIds;
std::string code;
CODE TO STORE IDs INTO VECTOR HERE;
int vectorLength = empIds.size();
std::cout << "enter id";
std::cin >> code;
for (int i = 0; i < vectorLength; i++) {
if (empIds[i] == code) {
std::cout << "enter id again";
std::cin >> code;
} else {
empIds.push_back(code);
}
}
}
For a start, something like the below should work.
map <string, bool> seen;
bool isUniqueId(string id)
{
return seen[id];
}
void addId(string id)
{
seen[id] = true;
}
From main(), whenever user inputs a string id, use isUniqueId(id) to ensure its unique, and if its unique, call addId(id).
Edit : (upon request from the OP)
Your transformed code may look like below after using map.
// Global map, defaults to false
map <string, bool> seen; // seen map to store if an id is seen already or not.
void uniqueId()
{
bool good = true; // set up a good flag to check if id is good or not.
int numEmployees = 0; // Count to store number of employees with unique ids so far
string id;
cout<< "enter id\n";
cin>> id;
while(good)
{
good = false; // Assume this is unique!
if(seen[id]) // Check if we already saw this id before
{
good = true; // Alas! We already have seen this id
cout<<"enter id again\n";
continue; // If id already exists, ask for another id setting good = true;
// Note that the above continue is NOT required as loop will run again (good = true).
// Just for clarity sake.
}
else
{
// Voila, we have a new employee with unique id.
seen[id] = true; // Unique, mark as seen now
emp[numEmployees].id=code; // Note numEmployees here
numEmployees++; // Increment the count
}
}
getch();
}
At the end of while loop, you would have successfully gotten a unique id from user, otherwise it will keep asking the user for new id.
Related
I have a database simulator coded in C++, and the way it works essentially is that the user says "insert 'item' 'quantity' 'price'" with item being a string and quantity/price being an int.
The issue I am running into is that whenever the user enters "insert" and doesn't put the other fields, a "vector subscript out of range" error pops up.
So, for example, "insert keyboard 20" would give me the error because no price was given.
I thought it was because the values are not originally initialized, but I tried to do that and nothing changed. I've tried initializing them in the structure to 0, but it still makes me abort the program. I imagine it's because the class I'm using is searching for 3 variables, and when it doesn't get them, it crashes.
I'm honestly not sure that there is a way to do this with my current code (I can't really completely overhaul it, they wanted classes), but I figured I'd take a shot in the dark with you tech gurus.
Below are the two classes that I am using.
The class that edits my created structure database:
class ProductDB
{
public:
ProductDB() = default;
~ProductDB() = default;
//Commands to give ProductDB control over appending, removing, updating, finding, and printing
void append(const string& name, int quantity, double price);
private:
vector<Product> items;
//initialize sequence counter for append
int seq = 0;
//check for unique names using set function
set<string> productNames;
};
And here is the class that inserts the information into the database:
//class to append
void ProductDB::append(const string& name, int quantity, double price)
{
if (quantity <= 0 || price <= 0) {
cout << "Input Error: Please enter a quantity" << endl;
return;
}
if (productNames.find(name) != productNames.end()) {
cout << "Input Error: That name already exists, Please enter an unique name!" << endl;
return;
}
Product item;
//running total for sequence
item.id = ++seq;
item.name = name;
item.quantity = quantity;
item.price = price;
items.push_back(item);
// insert name in database as the product gets inserted
productNames.insert(name);
cout << "Entry: '" << item.name << "' inserted successfully!" << endl;
}
And this is where I call to the class:
//insert command
if (cmdInput[0] == "insert")
{
string name = cmdInput[1];
int quantity = stoi(cmdInput[2]);
double price = stod(cmdInput[3]);
itemsDB.append(name, quantity, price);
}
Something like this:
//insert command
if (cmdInput[0] == "insert")
{
if( (int)cmdInput.size() < 4 ) {
std:cout << "Not enough input params\n";
}
else {
string name = cmdInput[1];
int quantity = stoi(cmdInput[2]);
double price = stod(cmdInput[3]);
itemsDB.append(name, quantity, price);
}
}
This technique is called "firewalling": writing code that checks the input for correctness BEFORE starting to process the input. This keeps all the messy if statements and error handling separate from the processing code which can proceed assuming everything is good and so can be coded in a clear straightforward manner, easily understood and maintained.
I am working on an assignment which has the following goals:
Store user provided customer info into an array of structs.
Write functions to add, display all or retrieve a customer(s).
I have an issue with writing my findCust (retrieval routine). I would like to prompt the user for a first and last name of any customer, and then to find the relevant customer in the array of customers and print out their information. I'm kind of stuck and not sure how to proceed.
This is what I have so far:
void findCust(Customer customers[], int loc)
{
string name;
const int t = 100;
cout << "\nEnter the name of the customer you would like to look up: ";
getline(cin, name);
cout << endl;
for (int i = 0; i <= loc; i++) {
}
}
This is how the Customer struct is:
struct Customer {
string firstname;
string lastname;
Address home;
Address business;
};
Here's my main function:
int main() {
title("Customer Contact Menu");
int choice = 0;
int loc = 0;
const int SIZE = 100;
Customer contacts[SIZE];
while (choice < 5) {
choice = displayMenu();
switch (choice) {
case 1:
contacts[loc] = getCustomer();
loc++;
break;
case 2:
for (int x = 0; x < loc; x++) {
showCustomer(contacts[x]);
}
break;
case 3:
findCust(contacts,loc);
break;
case 4:
endProg();
}
}
}
I want to know how exactly to read information stored in the customer array, and compare it to the user input. I tried using a customer.compare command, I've tried a few things as well, I tried a linear search etc. But the problem with this is user input can't be compared to a structure. That's the part I'm stuck on.
If I understood your question correctly you want to read and find a customer, and then print their information. In order to do this I would structure the function like so:
void findCust(Customer customers[], int array_size)
{
string first_name, last_name;
cout << "\nEnter the name of the customer you would like to look up: ";
cin >> first_name >> last_name;
for (int i = 0; i < array_size; i++) {
}
}
Inside the for loop you can run a linear search and just iterate over all the customers and compare them. i.e. Go through the array and for each customers[i].firstname and customers[i].lastname check if they match the first_name and last_name variables.
If they do then call print(customers[i]) which is the function that will print out the given customer. You can have the function's definition be similar to void print(Customer customer) and this can contain all the printing to the stream.
Hopefully that helps you get started.
I've started programming using C++ few weeks back.
I'm working on an application store user input data into an array list. When entering user data the application must be able to check whether the user already exists in the array list.
The program is unable to store the user input or able to check whether the user already exists in the array list..
int linearSearch(int array[], int size, int searchValue)
{
for (int i = 0; i < size; i++)
{
if (searchValue == array[i])
{
return i;
break;
}
}
return -1;
}
void customerReg(){
const int Capacity = 99;
int cnic[Capacity];
int customerNic;
int search = 0;
cout << "Enter Customer NIC: \n";
cin >> cnic[Capacity];
search = linearSearch(cnic, Capacity, customerNic);
if (search != -1){
cout << "Customer is already registered!\n";
}
else {
string customerName;
cout << "Enter Customer Name: \n";
cin >> customerName;
}
What about:
...
cout << "Enter Customer NIC: \n";
cin >> customerNic; // <=== instead of: cnic[Capacity];
Other remarks:
the break is not necessary: the return will already interupt the search loop
cnic[Capacity] is out of range, so puting a value in it might cause some troubles
cnic[] is not initialised
It is not clear how you fill cnic[], which is by the way local to the function and be lost as soon as you return from it.
Depending how you initalize/fill cnic, it could make sense to keep track of the number of customers that are registered in the table.
Edit:
I assume that you can't use vectors or maps for your exercise, and that you're right at the beginning of your learning.
So I suppose that customerReg() is the first function that you are working on, and that others will follow (display, delete, modifiy...). If this is the case, you have to keep your customer data outside the functions:
const int Capacity = 99;
int cnic[Capacity] {};
int customer_count=0; // counter to the last customer inserted
Then in customerReg() you should call your search function using the number of customers instead of the maximal Capacity:
search = linearSearch(cnic, customer_count, customerNic);
Later, in the else branch you have to insert the new id into the array:
else {
if (customer_count==Capacity) {
cout << "Oops ! Reached max capacity"<<endl;
else {
string customerName;
cout << "Enter Customer Name: \n";
cin >> customerName;
...
cnic[customer_count] = customerNic; // here you store the id
... // store (I don't know where) the other customer elements you've asked for
customer_count++; // increment the number of users that are stored.
}
}
I'm having quite the issue trying to figure out why these code segments are printing the error message even when I have done cout statements within the block that should return true / not print that error message. Any ideas? I'm new here so please let me know if this isn't allowed. Thanks!
Use of function:
case 'a':
{
// Format: a ID credits GPA
// Adds a student with the given student ID (ID), number of
// credits (credits), and overall GPA (GPA) to the database.
// If the student is already in the database, an error
// message should be printed indicating this.
int credits = 0;
double gpa = 0;
cin >> studentID;
cin >> credits;
cin >> gpa;
// Adds the student and checks to see if the student was actually added
// or if there was an existing student with the specified ID
bool added = addStudent(studentID, credits, gpa);
if(added == false);
{
cout << "Student already exists in database, nothing changed." << endl;
// Still prints this when executed with valid
}
break;
}
Function for adding student to array:
bool addStudent (int id, int numCredits, double gpa) {
// Check to see if student exists
if (nextEntry != 0)
{
for (int x = 0; x < 7000; x++) {
Student tmp = studentRecords[x];
if (tmp.studentId == id)
{
return false;
cout << "hey" << endl;
}
}
}
// If student does not exist, add to records database
if (nextEntry != 7000)
{
studentRecords[nextEntry].studentId = id;
studentRecords[nextEntry].numCredits = numCredits;
studentRecords[nextEntry].gpa = gpa;
nextEntry++;
return true;
// confirmed I can get here
}
return false;
}
You have an extra ; after your if (added==false) statement. This will terminate the if statement and the code after will run regardless of the check.
I have a struct called users containing username information:
struct User{
string name;
string type;
int credit;
bool loginState;
};
My program reads in a txt file and creates an array of User struct types called "users" to store all the data. Im trying to create a function that deletes a user, so in the for loop below I'm searching for the string
userName
in the users array. If the user name exists then all the information of that user account is stored in the User temp. Otherwise an error is generated stating that the user entered does not exist.
string userName;
User temp;
cout<<"Please enter a username to delete:";
cin >> userName;
for(int i=0; i<usersSize; i++){
if((users[i].name).compare(userName) == 0){
temp.name = users[i].name;
temp.type = users[i].type;
temp.credit = users[i].credit;
temp.loginState = users[i].loginState;
}else{
cout << "Error: User does not exist";
}
}
I've tested my program and no matter what the input is, whether the user exists or not, the if statement always outputs the second condition. How can I fix this?
You need to first check if the user exists and then process the user which was found. The problem in your code is that the for loop checks all users and shows a message for all users but the one that matches (if any).
Check this code:
bool userWasFound = false;
int i;
for(i=0; i<usersSize; i++){
if((users[i].name).compare(userName) == 0){
userWasFound = true;
break;
}
}
// If no user was found, 'userWasFound' will still be 'false' at this point
if(userWasFound){
temp.name = users[i].name;
temp.type = users[i].type;
temp.credit = users[i].credit;
temp.loginState = users[i].loginState;
}else{
cout << "Error: User does not exist";
}
Use a flag to indicate that user found or not.. e.g;
bool flag=false;
for(int i=0; i<usersSize; i++){
if((users[i].name).compare(userName) == 0){
temp.name = users[i].name;
temp.type = users[i].type;
temp.credit = users[i].credit;
temp.loginState = users[i].loginState;
flag=true;
break;
}
}
if(!flag){
cout << "Error: User does not exist";
}
Hope it helped...