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;
}
Related
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();
...
}
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();
I'm currently creating a custom std::unordered_map declaration with my custom key:
class BASE_DLLSPEC ClientKey
{
private:
// this is always true initially until we call SetClientId
bool emptyId;
// both of these are guaranteed to be unique
QString m_connectId; // ip:port format
QString m_clientId; // {Uuid} format
// ----------
public:
ClientKey(const QString& connectId = "", const QString& clientId = "") :
emptyId(true), m_connectId(connectId), m_clientId(clientId)
{ }
void SetClientId(const QString& clientId)
{
m_clientId = clientId;
emptyId = false;
}
const QString& GetConnectId() const { return m_connectId; }
const QString& GetClientId() const { return m_clientId; }
bool operator==(const ClientKey& other) const
{
int comp1 = QString::compare(m_connectId, other.GetConnectId());
int comp2 = QString::compare(m_clientId, other.GetClientId());
return (comp1 == 0) ||
(!emptyId && comp2 == 0);
}
};
struct BASE_DLLSPEC ClientKeyHash
{
std::size_t operator()(const ClientKey& key) const
{
std::string connectId = key.GetConnectId().toStdString();
std::string clientId = key.GetClientId().toStdString();
std::size_t h1 = std::hash<std::string>()(connectId);
std::size_t h2 = std::hash<std::string>()(clientId);
return h1 ^ (h2 << 1);
}
};
struct BASE_DLLSPEC ClientKeyEqual
{
bool operator()(const ClientKey& lhs, const ClientKey& rhs) const
{
return lhs == rhs;
}
};
typedef std::unordered_map<ClientKey,
ClientPtr,
ClientKeyHash,
ClientKeyEqual> ClientMap;
I'm having difficulties finding a particular key during my iteration. For some reason my client object is never located when I pass in a key for lookup.
ClientKey key = Manager::ClientKey(connectId);
ClientManager& clientManager = Manager::ClientManager::GetInstance();
ClientMap::const_iterator clientIter = clientManager.GetClients().find(key);
Even if the key has already been inserted, clientIter is always pointing to the end iterator position. Do you think this is related to having to re-create these ClientKey values on the stack and then passing them into the map for look-up, or do I have a problem elsewhere? Thank you for the clarification and insight.
At first, some considerations to the emptyId field (do not consider invalid formats - which, by the way, is not checked by you either):
ClientKey k0("hello", "world");
ClientKey k1("hello");
k1.SetClientId("world");
Is there any particular reason that the emtpyId flag should be different for k0 and k1? I personally would say:
The flag is implemented incorrectly.
It is redundant, you get the same information via m_clientId.empty().
Now the reason for failure:
Consider again k0 and k1, but without SetClientId having been called on k1:
ClientKey k0("hello", "world");
ClientKey k1("hello");
Imagine k0 has been inserted in the map, and with k1 you try to find it. What will happen? k1 produces another hash key than k0, and the map will look at a different bucket than where k0 resides at - and will not find anything.
What I think you want to achieve is having several clients for the same connection id and being able to iterate over these for a given connection id. So you might prefer std::unordered_multimap<std::string, ClientPtr> (where the string parameter represents the connection id). You will get all clients for a given connection id via equal_range then, and your class ClientKey gets obsolete.
Your code allows that the following will return true:
ClientKey k1("hello", "world");
ClientKey k2("hello", "");
return k1 == k2;
However, your hash is based on the combination of connectId and clientId.
unordered_map::find does not do an exhaustive search of the map, instead it looks in the bucket for the given hash and compares just the entries in the bucket.
You are generating your test key with just connectId, so it is looking in the bucket for ClientKey(connectId, "") rather than the bucket for ClientKey(connectId, someOtherValue).
You should consider making the hash based exclusively on connectId.
Lastly, note your constructor:
ClientKey(const QString& connectId = "", const QString& clientId = "") :
emptyId(true), m_connectId(connectId), m_clientId(clientId)
{ }
If I write:
ClientKey ck("hello");
should emptyId really be true?
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.
The following code works in a the Marmalade simulator (I'm on OSX using x-code)
bool PictureDictionary::OnTableSelect(CTable* table, int tab){
//if something is selected, look up the item, and display it
//also change the search to the selected item
if(-1 < tab){
// if a term is selected, set the search text field to the term
CString term = m_SearchResults.GetString(tab);
if(m_currentWord != (char*)term.Get()){
m_currentWord = (char *)term.Get();
m_searchTextField->SetAttribute("text", term);
char* normalizedTerm = (char *)term.Get();
char* imagePath;
sprintf(imagePath,"images/%s.jpg", normalizedTerm);
if(m_ImageAttached){
m_Image->SetAttribute("image", (const char*)imagePath);
} else {
m_Image = CreateImage(CAttributes()
.Set("name", "picture")
.Set("x1", "0")
.Set("x2", "0")
.Set("y1", "50%")
.Set("image", (const char*)imagePath)
);
m_SearchView->AddChild(m_Image);
m_ImageAttached = true;
}
}
}
return true;
}
When I run the simulator, and select an item from the table, the image appears, and changes when I select a different item. When I go to refactor, I get a EXC_BAD_ACCESS (code=1…..) Error
bool PictureDictionary::OnTableSelect(CTable* table, int tab){
//if something is selected, look up the item, and display it
//also change the search to the selected item
if(-1 < tab){
// if a term is selected, set the search text field to the term
CString term = m_SearchResults.GetString(tab);
if(m_currentWord != (char*)term.Get()){
m_currentWord = (char *)term.Get();
m_searchTextField->SetAttribute("text", term);
char* normalizedTerm = (char *)term.Get();
char* imagePath;
sprintf(imagePath,"images/%s.jpg", normalizedTerm);
UpdatePictureView(imagePath);
}
}
return true;
}
void PictureDictionary::UpdatePictureView(char* imagePath){
if(m_ImageAttached){
m_Image->SetAttribute("image", (const char*)imagePath);
} else {
m_Image = CreateImage(CAttributes()
.Set("name", "picture")
.Set("x1", "0")
.Set("x2", "0")
.Set("y1", "50%")
.Set("image", (const char*)imagePath)
);
m_SearchView->AddChild(m_Image);
m_ImageAttached = true;
}
}
Any suggestions on how to clean up the code without getting these issues?
Edit RE Comments about uninitialized variables:
m_ImageAttached was initialized to false in the constructor, unless I'm doing something wrong. Also, changing the condition to check if m_Image!=NULL also throws the same error.
main.cpp:
PictureDictionary pictDict(myApp, &dictionary);
Constructor for PictureDictionary:
PictureDictionary::PictureDictionary(CAppPtr app,Dictionary::Dictionary* dictionary){
m_App = app;
m_Dictionary = dictionary;
m_currentWord = "";
m_ImageAttached = false;
}
imagePath is an unitialized pointer, in both snippets. Any attempt to dereference is undefined behaviour. It just appeared to work in the first snippet. Use an array or populate a std::string instead:
std::string imagePath(std::string("images/") + normalizedTerm + ".jpg");
And use std::string::c_str() if access to the underlying const char* is required.