check if a value belongs to a certain object - c++

I have a map with two different kinds of objects: deposit account and checking account. I want to write a money transfer methode to transfer money between two checking accounts only. Is there a way to check if both account numbers belong to the same checking account object?
bool Bank::moneyTransfer(long fromAccount,long toAccount, double amount)
{
map<long, account*>::iterator iterFrom;
map<long, account*>::iterator iterTo;
iterFrom = m_accountList.find(fromAccount);
if (iterFrom == m_accountList.end()) {
return false;
}
iterTo = m_account.find(toAccount);
if (iterFrom == m_accountList.end()) {
return false;
}
Konto *fromAccount = iterFrom->second;
Konto *toAccount = iterTo->second;
if (!fromAccount->drawMoney(amount)) {
return false;
}
toAccount->payIn(amount);
return true;
}

Q. Is there a way to check if both account numbers belong to the same checking account object?
A. Yes
As Shaktal says you're passing in the account numbers just compare them.
There are a couple things that need to be cleaned up in your code:
The fact that you're asking this question indicated that the you think that you could have the same Key in a map with 2 Values. This is not the case, this code will result in the Key 13 mapping to only a DepositAccount:
m_accountList[13] = CheckingAccount();
m_accountList[13] = DepositAccount();
Please use auto to declare your variables, especially instead of map<long, account*>::iterator aside from being easier to read, you wont have to come back and edit your logic when you change m_accountList's type, for more information on auto I believe the definitive article is: https://herbsutter.com/2013/08/12/gotw-94-solution-aaa-style-almost-always-auto/
After making these corrections, your code should look something like:
bool Bank::moneyTransfer(long fromAccount, long toAccount, double amount)
{
if(fromAccount != toAccount) {
auto iterFrom = m_accountList.find(fromAccount);
if (iterFrom != m_accountList.end()) {
auto iterTo = m_account.find(toAccount);
if (iterFrom != m_accountList.end() && iterFrom->second->drawMoney(amount)) {
iterTo->second->payIn(amount);
return true;
}
}
}
return false;
}

Related

how to check if personID is in my_customers (see my example)

In C++, the interface for this file says
*If no soup left returns OUT_OF_SOUP
* If personID not found in my_customers AND numbBowlsSoupLeft>0 then give this person a bowl of soup (return BOWL_OF_SOUP)
* and record it by creating new customer struct using personID, numbBowlsSoup=1 and adding this struct to my_customers, be sure to decrement numbBowlsSoupLeft.
for my implementation, I'm trying to put
int Soupline::getSoup(int personID) {
if (numBowlsSoupLeft == 0) {
return OUT_OF_SOUP;
}
if (!(personID : my_customers) && numbBowlsSoupLeft > 0) {
}
But that second if statement is giving me syntax errros, I just want to know how to check to see if the personID is IN my_customers?
my_customers was created in the soupline interface using:
std::vector<customer> my_customers; // keeps track of customers
First you want to use find() to search a vector.
Second, please handle the case if numbBowlsSoupLeft < 0, because that can be a huge source of problem.
Third, your syntax error is the (personID : my_customers), the : is for iteration.
int Soupline::getSoup(int personID) {
if (numBowlsSoupLeft <= 0) { // handles negative numBowlsSoupLeft
return OUT_OF_SOUP;
}
bool found_customer = false;
for (auto c : my_customers) {
if (personID == c.person_id()) { // This is my guess on how the id is stored in customer class
// Logic to process soup for customer
found_customer = true;
break;
}
}
if (!found_customer) {
// Logic to process non-customer asking for soup?
}
}
Sorry i dunno what is the return integer is supposed to be, so it is not defined in my code example.

Exception Handling with Multiple Variables

I'm trying to learn more about exception handling while working on my program. I have multiple test variables I want to test and make sure it is within range with:
public bool IsWithinRange(TextBox textbox, string name, int min, int max)
{
double number = double.Parse(textbox.Text);
if (number < min || number > max)
{
MessageBox.Show(name + " must be between " + min.ToString() + " and " + max.ToString() + ".", "Entry Error");
textbox.Focus();
return false;
}
else { return true; }
}
And calling the method using:
bool condition;
condition = CheckAll();
if (condition == true) { condition = IsWithinRange(txtVar1, "Var1", 1, 50); }
if (condition == true) { condition = IsWithinRange(txtVar2, "Var2", -100, 100); }
if (condition == true) { condition = IsWithinRange(txtVar3, "Var3", 100, 200); }
This logic works, but I was curious to see if there was a more concise, better looking way of writing some form of systematic checking of variables one by one?
You can take advantage of a few things:
Are you able to assign meaningful names to the TextBox.Name properties? If so, you can omit the second parameter in "IsWithinRange" and simply call "Textbox.Name".
As of C# 6.0, there is now a syntax to interpolate strings. So the string passed into your your MessageBox.Show syntax can be made shorter and prettier.
You can immediately assign to "condition", and you can convert your "if" statements to combined "and" statements.
All together, your code can look like this:
bool condition =
CheckAll()
&& IsWithinRange(txtVar1, 1, 50)
&& IsWithinRange(txtVar2, -100, 100)
&& IsWithinRange(txtVar3, 100, 200);
// Some other code here
With your method looking like this:
public bool IsWithinRange(TextBox textbox, int min, int max) {
double number = double.Parse(textbox.Text);
if (number < min || number > max) {
MessageBox.Show($"{textbox.Name} must be between {min} and {max}.", "Entry Error");
textbox.Focus();
return false;
}
else
return true;
}
This is assuming you actually use "condition". If not, you can omit "bool condition = " and the code runs just the same.
But there are a few things to note. Your code will continue to run even if "CheckAll" is false or any "IsWithinRange" is false. This is true in my version above or in your own version. Yes, your user will get a message, but after he clicks "okay", the remaining code will run even if the checks fail.
Also, "IsWithinRange" might be misinterpreted by a teammate or even by yourself in the future. This is because it does more than just return true/false: it sends a message if false. This violates the principle of command-query separation.
An approach to these issues ignores brevity, as that is desired but never the highest goal. What you can do is create a class that validates, whose methods separate the tasks:
class Validator {
public bool isValid = true;
public List<string> messages = new List<string>();
public Validator CheckAll() {
// Whatever your logic is for this.
return this; // Return the instance of "Validator" that called this method
}
public Validator CheckRange (TextBox textbox, int min, int max) {
double number = double.Parse(textbox.Text);
if (number < min || number > max) {
messages.Add($"{textbox.Name} must be between {min} and {max}.");
isValid = false;
}
return this;
}
public void ShowErrorsToUser () =>
MessageBox.Show(string.Join(Environment.NewLine, messages));
}
Which you would use like this:
var validator =
new Validator()
.CheckAll()
.CheckRange(txtVar1, 1, 50)
.CheckRange(txtVar2, -100, 100)
.CheckRange(txtVar3, 100, 200);
if (!validator.isValid) {
validator.ShowErrorsToUser();
txtVar1.Focus();
return; // Stop code execution!
}
// Continue with your normal logic that utilizes your textbox values.
I'll leave it to you to decide whether the class-based approach is worth your time. But I present it to you as a different way to think.

how to write an atomic account transfer function

So suppose I get two bank account A and B, and I need to atomically transfer money.
The set up is the following:
`
struct account{
int64 amount;
pthread_mutex_lock m;
}
`
here is my approach:
`
bool Transfer(int from_account, int to_account, int64 amount)
{
pthread_lock(&account[from_account].m);
bool ret = false;
if(accounts[from_account].balance>=amount)
{
accounts[from_account].balance-=amount;
ret = true;
}
pthread_unlock(&account[from_account].m);
pthread_lock(&account[to_account].m);
accounts[to_account].balance+=amount;
pthread_unlock(&account[to_account].m);
return ret;
}
`
the function transfer money from from_account to to_account, return a bool, only transfer when remaining money in the account>=ammount.
Is this function an okay approach? I guess it will not cause deadlock problem but doesn't it make the whole function non-atomic? So there might be race conditions? Please help me, thanks a lot.
Your code is logically broken. Regardless of the from_account's balance, to_account will win account unconditionally! (and I wanna be to_account owner :)
In this case, you must acquire both locks of two accounts, and it cause potentially deadlock problem.
The simplest way to avoid deadlock is enforcing the order of lock acquisition, for example, the smaller index account comes first.
bool Transfer(int from_account, int to_account, int64 amount)
{
// acquire locks (in pre-defined order)
if (from_account < to_account)
{
pthread_lock(&accounts[from_account].m);
pthread_lock(&accounts[to_account].m);
} else {
pthread_lock(&accounts[to_account].m);
pthread_lock(&accounts[from_account].m);
}
// transfer amount
bool ret = false;
if (accounts[from_account].balance >= amount)
{
accounts[from_account].balance -= amount;
accounts[to_account].balance += amount;
ret = true;
}
// release both locks
pthread_unlock(&accounts[from_account].m);
pthread_unlock(&accounts[to_account].m);
return ret;
}

How to store the state of a deeply-nested loop?

I am trying to refactor the following code, as I don't think it is structured well.
Can you think of a more elegant way to do this?
Bar::Bar()
{
m_iter1 = 0;
m_iter2 = 0;
}
bool Bar::foo()
{
_reinitialize();
for (; m_iter1 < 2; m_iter1++, m_iter2 = 0) {
_log("TRYING METHOD: [%d]", m_iter1);
if (_something_wrong(m_iter1)) {
return false;
}
for (; m_iter2 < 6; m_iter2++) {
if (_try_with_these_params(m_iter1, m_iter2, ...)) {
m_status = success;
// store next iteration in case we need to retry.
m_iter2++;
return true;
}
}
}
return false;
}
bool try_foo(Bar& bar)
{
if (bar.foo()) {
if (meet_some_criteria) {
return true;
} else {
bar.invalidate();
// retry. the Bar object stores the state.
try_foo(bar);
}
} else {
return false;
}
}
int main()
{
Bar bar;
if (try_foo(bar)) {
_log("SUCCESS");
} else {
_log("FAILURE");
}
}
The code loops over different parameter sets and tries to perform some action with these parameters. If the action is successful, then external code may invalidate the action and attempt to retry. The object which performs the action stores the state, so that external code may retry and re-enter the parameter loop at the place it left off.
The output using one parameters affect others, so the calculations need to be accomplished locally within the Bar class.
I would like to extend this idea to more dimensions, but doing so with the current design is clumsy.
A lot here depends on how expensive the various actions are.
If initially generating a candidate parameter set is cheap (and the set isn't too large), then you might want to just generate all the candidate sets, then give that result to the external code and try each in turn until you find one that the external code will accept.

Member variables of a object get overridden when creating another object in the object

I have a memory issue with a class of mine. The issue occurs when I create an object in a member function of a class. It is about the class below. I removed the member functions because they aren’t necessary:
class User
{
private:
bool locked;
bool active;
std::vector<City> * userCitys;
UserData userData;
Credentials credentials;
The problem occurs when I call this function:
int User::addCity(CityData cityData)
{
lockUserObject(); //Everything is fine here
City cityToAdd; //When this object is created, the memory of userCitys will get overridden
cityToAdd.activate();
userCitys->push_back(cityToAdd);
int cityID = userCitys->size() - 1;
userCitys->at(cityID).editCityData(cityData);
unlockUserObject();
return cityID;
}
In the first place I created userCitys on the stack. For test purpose I placed it on the Heap. The address of userCitys get overridden by some data. I can’t find the problem. the City is just a basic class:
Part of the header:
class City
{
private:
bool active;
Supplies supplies;
std::vector<Building> buildings;
std::vector<Company> companies;
std::vector<Share> shares;
std::vector<Troop> troops;
CityData cityData;
Constructor:
City::City()
{
active = false;
}
How is it possible that userCitys get overridden? This all happens on a single Thread so that can’t be a problem. I tried a lot of thing, but I can’t get it to work. What is the best approach to find the problem?
Edit:
Lock function:
void User::lockUserObject()
{
for( int i = 0; locked ; i++)
{
crossSleep(Settings::userLockSleepInterval);
if( i >= Settings::userLockMaxTimes )
Error::addError("User lock is over userLockMaxTimes",2);
}
locked = true;
}
I call the code here (Test function):
City * addCity(User * user)
{
Location location;
location.x = 0;
location.y = 1;
CityData citydata;
citydata.location = location;
citydata.villagers = 0;
citydata.cityName = "test city";
int cityID = user->addCity(citydata); //addCity is called here
City * city = user->cityAction(cityID);;
if( city == NULL)
Error::addError("Could not create a city",2);
return city;
}
The add user (Test code):
User * addUser()
{
UserData test;
test.name = "testtest";
Credentials testc("testtest",3);
//Create object user
int userID = UserControle::addUser(test,testc);
User * user = UserControle::UserAction(userID);
if( user == NULL)
Error::addError("Could not create a user",2);
return user;
}
My test function:
void testCode()
{
User * user = addUser();
City * city = addCity(user);
}
This function in called in main:
int main()
{
testCode();
return 0;
}
Here are UserAction and addUser in UserControle:
int UserControle::addUser(UserData userdata, Credentials credentials)
{
int insertID = -1;
for( int i = 0; i < (int)UserControle::users.size(); i++)
{
if( !UserControle::users.at(i).isActive() )
{
insertID = i;
break;
}
}
User userToInsert(userdata,credentials);
if( insertID != -1 )
{
UserControle::users.insert( UserControle::users.begin() + insertID,userToInsert);
return insertID;
}
else
{
UserControle::users.push_back(userToInsert);
return UserControle::users.size() - 1;
}
}
User* UserControle::UserAction(int userID) //check all indexes if greater then 0!
{
if( (int)UserControle::users.size() <= userID )
{
Error::addError("UserAction is out of range",3);
return NULL;
}
if( !UserControle::users.at(userID).isActive())
{
Error::addError("UserAction, the user is not active.",3);
return NULL;
}
return &UserControle::users[userID];
}
There's a few things you could try:
Remove code until the fault goes away. In other words, distill a minimal example from your code. I guess you'll then see the error yourself, otherwise post that small example program here and others will.
Don't use raw pointers. The question with those is always who owns what they point to. Use smart pointers instead, e.g. unique_ptr (C++11) or auto_ptr (C++98) for exclusive ownership.
If you have pointer members like "userCities", you need to think about what happens when copying instances of that class (you already wrote a proper destructor, or?). So, either prevent copying (make copy-constructor and assignment operator private and without implementing it) or implement them in a way that the vectors are properly cloned and not shared between different instances.
Don't use C-style casts. If those are necessary to get anything through the compiler, the code is probably broken.