How to return null in map? - c++

I am trying to return null if the accountNo wasn't find the the map.
But I have only used linkedlist in the past in java.
I have no idea how to return something else in c++ map.
113 Account Bank::BalanceEnquiry(long accountNo){
114 map<long, Account>::iterator itr = accounts.find(accountNo);
115 return itr->second;
116 }
Can anyone help?

You can use std::optional, which is a wrapper that may or may not contain a value:
std::optional<Account> Bank::BalanceEnquiry(long accountNo){
auto itr = accounts.find(accountNo);
if(itr == accounts.end()) {
return std::nullopt; // empty value, that's like null from Java
}
return std::optional<Account>{itr->second}; // return non-empty value
}
It can be used like this (with a Bank-object myBank):
std::optional<Account> balanceEnquiry = myBank.BalanceEnquiry(someValue);
if(balanceEnquiry) {
// entry found, we can extract the actual value
Account foundAccount = balanceEnquiry.value();
}
else {
// entry not found
}

Unlike Java in C++ you can return object by value (or by reference) or by pointer. If you are returning by value (as in your code) you cannot return nullptr unless your class Account has special state. So you have to change return type. Possible variants:
// return a pointer
Account *Bank::BalanceEnquiry(long accountNo){
auto itr = accounts.find(accountNo);
return itr == accounts.end() ? nullptr : &(itr->second);
}
// usage
auto account = bank.BalanceEnquiry(123);
if( account ) account->do_something();
// return std::optional
std::optional<Account> Bank::BalanceEnquiry(long accountNo){
auto itr = accounts.find(accountNo);
return itr == accounts.end() ? std::optional<Account>() : itr->second;
}
// usage
auto account = bank.BalanceEnquiry(123);
if( account ) account.value().do_something();

Related

Is it neccessary to use Json::value object=Json::objectValue to init?

To work with json using a library jsoncpp,is it neccessary to use Json::objectvalue?
Json::Value jsn_req;
jsn_req["header"] = Json::objectValue;
jsn_req["header"]["sid"] = 0;
or:
Json::Value jsn_req;
jsn_req["header"]["sid"] = 0;
What's the difference between this?
read the source code, may help. operator[] create null value if the key is not exist. Then a null value can add not exist key too.
diff:
the first just trans the value of "header" from null to object, the second doesn't do it.
the first find "header" twice, but the second only find it once.
Both of then could work, but the second must be quick, it's not necessary to trans it.
Value& Value::operator[](const char* key) {
return resolveReference(key, key + strlen(key));
}
Value& Value::resolveReference(char const* key, char const* end) {
JSON_ASSERT_MESSAGE(
type() == nullValue || type() == objectValue,
"in Json::Value::resolveReference(key, end): requires objectValue");
if (type() == nullValue)
*this = Value(objectValue);
CZString actualKey(key, static_cast<unsigned>(end - key),
CZString::duplicateOnCopy);
auto it = value_.map_->lower_bound(actualKey);
if (it != value_.map_->end() && (*it).first == actualKey)
return (*it).second;
ObjectValues::value_type defaultValue(actualKey, nullSingleton());
it = value_.map_->insert(it, defaultValue);
Value& value = (*it).second;
return value;
}

how to check if unique_ptr points to this

In following peace of code, I'm trying to find another object that has the same coordinates as this. How to do it correctly?
auto& organism_vector = world->get_vector();
auto attacked_organism = find_if(begin(organism_vector), end(organism_vector), [this](const unique_ptr<Organism>& attacked_organism)
{
return this->get_coordinates() == attacked_organism->get_coordinates() && *this != *attacked_organism;
});
Another thing, when I finally manage to get this iterator, how to refer to attacked_organism class methods?
*attacked_organism.get_coordinates();
Change *this != *attacked_organism to this != attacked_organism.get():
auto& organism_vector = world->get_vector();
auto attacked_organism = find_if(begin(organism_vector), end(organism_vector),
[this](const unique_ptr<Organism>& attacked_organism)
{
return this->get_coordinates() == attacked_organism->get_coordinates() && this != attacked_organism.get();
}
);
Once you have the iterator that find_if() returns (and after you validate that it is not the end iterator), you can call methods on the Organism by first dereferencing the iterator to access the unique_ptr that is holding the Organism* pointer, and then dereferencing the unique_ptr to access the Organism itself:
auto attacked_organism = find_if(...);
if (attacked_organism != end(organism_vector))
{
(**attacked_organism).get_coordinates();
or:
(*attacked_organism)->get_coordinates();
...
}
On a side note: I would not recommend giving your iterator variable the same name as the lambda parameter. That just makes things confusing to read. The lambda is trying to find an Organism to attack, but it hasn't actually been attacked yet, so you should name the lambda parameter more appropriately, eg:
auto attacked_organism = find_if(begin(organism_vector), end(organism_vector),
[this](const unique_ptr<Organism>& candidate_organism)
{
return this->get_coordinates() == candidate_organism->get_coordinates() && this != candidate_organism.get();
}
);
For that matter, I wouldn't really suggest naming the iterator as attacked_organism, either. It is not the actual Organism, it is an iterator to the Organism, so something more like this would be more readable:
auto& organism_vector = world->get_vector();
auto found_iterator = find_if(begin(organism_vector), end(organism_vector),
[this](const unique_ptr<Organism>& candidate_organism)
{
return this->get_coordinates() == candidate_organism->get_coordinates() && this != candidate_organism.get();
}
);
if (found_iterator != end(organism_vector))
{
auto &attacked_organism = *found_iterator;
attacked_organism->get_coordinates();
...
}

How to protect app against read access violation while accessing to pointer's value?

I've created some chain-like structure, where one object has pointers to the next and previous object of a chain. The code below loops through entire chain, looks for value specified in arguments and removes matching element (if exists).
void List::removeElementByValue(int value)
{
ListMember* nextElem = this->firstValue;
while (nextElem) {
if (nextElem == NULL || nextElem == nullptr) {
break;
}
if (nextElem->value == value) {
if (nextElem->prevValue)
(nextElem->prevValue)->nextValue = nextElem->nextValue;
if (nextElem->nextValue)
(nextElem->nextValue)->prevValue = nextElem->prevValue;
delete nextElem;
this->count--;
return;
}
nextElem = nextElem->prevValue;
}
}
The problem is: I'm getting this error when I'm trying to remove non-existent value from chain.
Exception thrown: read access violation. nextElem was 0xCDCDCDCD.
Function should do nothing in that case. It happens at this line:
if (nextElem->value == value) {
As you see, I've used multiple ways to check if nextElem is correct, but I'm still getting this error. Any ways I can prevent that?
if (nextElem == NULL || nextElem == nullptr)
This will always be false when while (nextElem) is true.
nextElem = nextElem->prevValue;
This needs to use nextValue instead of prevValue.
But, most importantly, you are not updating this->firstValue if the value is found in the first element of the list, so you end up deleting the firstValue and leave it pointing at invalid memory.
Try this instead:
void List::removeElementByValue(int value)
{
ListMember* elem = this->firstValue;
while (elem) {
if (elem->value == value) {
if (elem->prevValue)
elem->prevValue->nextValue = elem->nextValue;
if (elem->nextValue)
elem->nextValue->prevValue = elem->prevValue;
// ADD THIS!!!
if (elem == this->firstValue)
this->firstValue = elem->nextValue;
delete elem;
this->count--;
return;
}
elem = elem->nextValue; // NOT prevValue!
}
}
A better solution is to not implement a linked list manually in the first place. Use the standard std::list container instead, let it do all of the hard hard for you.
#include <list>
class List
{
private:
std::list<int> values;
...
};
...
#include <algorithm>
void List::removeElementByValue(int value)
{
auto iter = std::find(values.begin(), values.end(), value);
if (iter != values.end())
values.erase(iter);
}

Iterate through a vector of objects and find a variable that matches one pulled from a text file

So I have a vector of objects
vector<Module*> moduleVector;
and I need to iterate through it and compare an attribute from the object to another attribute I'm pulling from a text file
I'm using an ifstream and getLine() to store the element that needs to be compared to the object's attribute (fileD is the opened file, markModId is the string variable)
getline(fileD, markModId, ' ');
But I am unsure of how I can refer to the object's attributes in an iterator. So my question is,
how do I compare the attribute from the file to the object using an iterator?
For reference here is my object constructor (id is the attribute I want to compare)
Module::Module(string id, string title, string lecturer, int
courseworkWeight)
{
code = id;
name = title;
lect = lecturer;
cwWeight = courseworkWeight;
exMark = 0; //ex mark initialised as 0
/*
Map to store coursework marks
*/
map<string, float> CWmarks;
//cwMarks.clear(); //cw marks map cleared
//create a map that stores
}
And exMark is the attribute that needs to be added to the object. All attributes in the Module constructor are private.
How do I compare the attribute from the file to the object using an
iterator?
Short answer: Suppose you have an iterator std::vector<Module*>::iterator iter you can access the public members of Module class like:
(*iter)->/*public member*/;
Long answer: First of all, you need a getter for private member id and one setter for exMark, by which you can get the id of each Module and compare to the id from the file and then set its exMark to some value.
std::string getId()const { return code; }
void setExMark(const double newMark) { exMark = newMark; }
If you want to change the first true instance of Module, you can use std::find_if for finding the Module:
std::string idFromFile = "two";
auto Condition = [&idFromFile](Module* element){ return element->getId() == idFromFile; };
auto iter = std::find_if(moduleVector.begin(), moduleVector.end(), Condition);
if(iter != moduleVector.end())
(*iter)->setExMark(10.0); // see this
// ^^^^^^^^^
See a sample code here
For multiple instances you can do:
for(auto iter = moduleVector.begin(); iter != moduleVector.end(); ++iter)
if ( (*iter)->getId() == idFromFile)
(*iter)->setExMark(10.0);
Note: In modern C++ you can use smart pointers, instead of raw pointers, which will delete the objects automatically as it goes out of scope.
Simply dereference the iterator to access its Module* pointer, then you can access the object using operator-> however you want, eg:
for (std::vector<Module*>::iterator iter = moduleVector.begin(), end = moduleVector.end(); iter != end; ++iter)
{
Module *m = *iter;
if (m->code == markModId)
m->exMark = ...;
}
Or, if you are using C++11 or later, let the compiler handle the iterator for you:
for (Module *m : moduleVector)
{
if (m->code == markModId)
m->exMark = ...;
}
Or, use a lambda with one of the standard iteration algorithms, eg:
std::for_each(moduleVector.begin(), moduleVector.end(),
[&](Module *m)
{
if (m->code == markModId)
m->exMark = ...;
}
);
If you are only interested in updating 1 Module, then break the loop when the the desired Module is found:
for (std::vector<Module*>::iterator iter = moduleVector.begin(), end = moduleVector.end(); iter != end; ++iter)
{
Module *m = *iter;
if (m->code == markModId)
{
m->exMark = ...;
break; // <-- add this
}
}
for (Module *m : moduleVector)
{
if (m->code == markModId)
{
m->exMark = ...;
break; // <-- add this
}
}
auto iter = std::find_if(moduleVector.begin(), moduleVector.end(),
[&](Module *m) { return (m->code == markModId); });
if (iter != moduleVector.end())
{
Module *m = *iter;
m->exMark = ...;
}

C++ how to check if an element of all objects stored in a vector have the same value?

For example I have an vector of objects and they all have attribute PointX so I want to check if all of them have the same value of PointX and if they have it should return true or false whatever.
So in a kind of pseudo-code:
IF ( Object[1].getPointX() == Object[2].getPoint(x) == Object[3].getPoint(x) ){
return true;
}
The problem is that I have more than 55 objects so there has to be a way to compare them without writting them all individually. I know there must be with a for loop but still I have no idea.
thanks in advance.
edit:
#awesomeyi your suggestion seems the easiest and more adequate to my needs (I'm not saying the others are not but I think they are too complicated for a newb like me) but it's not working, even if Xpoints are all the same or different it always returns false. here's what i have:
bool allKilled(){
auto checkpointx = Invader[0].getIfActive();
for(int i = 0; i < 55; ++i){
if(Invader[i].getIfActive() != checkpointx){
return false;}
}
}
the getIfActive() just returns if its true or false, and i want this method to return true if all Active (attribute of the object) of all objects are all false.
Something like this:
auto refx = Object[0].getPointX();
bool b = std::all_of(Object.begin(),
Object.end(),
[refx](TheTypeOfTHeElements& e)
{ return e.getPointX() == ref; });
Obviously you need to check that Objects is not empty.
For loop?
auto checkpointx = Object[0].getPointX();
for(int i = 1; i < Object.size(); ++i){
if(Object[i].getPointX() != checkpointx)
return false;
}
I'd do it something like this:
template<typename Objects, typename Comparison>
bool is_all_same( Objects&& objects, Comparison&& comp ) {
using std::begin; using std::end;
auto&& b = begin(objects);
auto&& e = end(objects);
if (b == e)
return true;
auto&& first = *b;
for( auto&& cur = std::next(first); cur != e; ++cur ) {
if (!comp( first, cur ))
return false;
}
return true;
}
use:
bool all_same_x = is_all_same( objs, []( Obj const& left, Obj const& right )->bool {
return left.getPointX() == right.getPointX();
});
where objs is some container or range containing objects of type Obj.
The above code should work on all standard containers, C style arrays, custom containers that support the new for loops, and is close to optimal performance wise.