This code's only redeeming quality is that it works. Can you please help me structure it better?
if (profile.isIgnoreCase()) {
// ignore case
if (masterKey.equalsIgnoreCase((targetKey))) {
if (masterValue.equalsIgnoreCase(targetValue)) {
doOK(masterKey, masterValue);
break;
} else {
// Key is either Missing or is an Error
if (checkErrors) {
doError(masterKey, masterValue, targetValue);
break;
}
}
}
} else {
if (masterKey.equals(targetKey)) {
if (masterValue.equals(targetValue)) {
doOK(masterKey, masterValue);
break;
} else {
if (checkErrors) {
doError(masterKey, masterValue, targetValue);
break;
}
}
}
}
You can remove some of the repetition by using:
if (profile.isIgnoreCase()) {
masterKey = masterKey.toLowerCase();
masterValue = masterValue.toLowerCase();
}
if (masterKey.equals(targetKey)) {
if (masterValue.equals(targetValue)) {
doOK(masterKey, masterValue);
} else {
if (checkErrors) {
doError(masterKey, masterValue, targetValue);
}
}
}
I have also removed the breaks as I doesn't look like you need them to me
[UPDATE] Alternatively, how about writing a new method to handle the comparison
public boolean isEqual(String a, String b, boolean ignoreCase) {
if (ignoreCase) {
return a.equalsIgnoreCase(b);
} else {
return a.equals(b);
}
}
you would then update your code like so:
if (isEqual(masterKey,targetKey,profile.isIgnoreCase())) {
if (isEqual(masterValue,targetValue,profile.isIgnoreCase())) {
doOK(masterKey, masterValue);
} else {
if (checkErrors) {
doError(masterKey, masterValue, targetValue);
}
}
}
Pull out the key and value comparisons into local variables and you can eliminate the duplicated logic. This avoids modifying the strings, and as a bonus makes the if statements a bit easier on the eyes.
boolean keysMatch, valuesMatch;
if (profile.isIgnoreCase()) {
keysMatch = masterKey .equalsIgnoreCase(targetKey);
valuesMatch = masterValue.equalsIgnoreCase(targetValue);
} else {
keysMatch = masterKey .equals(targetKey);
valuesMatch = masterValue.equals(targetValue);
}
if (keysMatch) {
if (valuesMatch) {
doOK(masterKey, masterValue);
break;
} else {
// Key is either Missing or is an Error
if (checkErrors) {
doError(masterKey, masterValue, targetValue);
break;
}
}
}
You could make it shorter by replacing them with the booleans that they represent, ie: masterKey.equalsIgnoreCase((targetKey)) with true or false.Which could help make it shorter, because you would need one less if and else clause.
bool ignoreCase = profile.isIgnoreCase();
if ((ignoreCase && masterKey.equalsIgnoreCase(targetKey)) ||
(!ignoreCase && masterKey.equals(targetKey))){
if ((ignoreCase && masterValue.equalsIgnoreCase(targetValue)) ||
(!ignoreCase && masterValue.equals(targetValue))) {
doOK(masterKey, masterValue);
break;
} else
if (checkErrors) {
doError(masterKey, masterValue, targetValue);
break;
}
}
Should be quicker this way to read boolean value, if this evaluates to false the program can skip to the next evaluation sooner than running the string compare first.
don't know if you need the break there. But I believe this is completely equivalent to your code.
bool ignoreCase = profile.isIgnoreCase();
if(ignoreCase and masterKey.equalsIgnoreCase(targetKey) or !ignoreCase and masterKey.equals(targetKey)) {
if(ignoreCase and masterValue.equalsIgnoreCase(targetValue) or !ignoreCase and masterValue.equals(targetValue)) {
doOK(masterKey, masterValue);
break;
} else if(checkErrors) {
doError(masterKey, masterValue, targetValue);
break;
}
}
Or I would write the following function in masterKey and masterValue class
public bool equalsCheckCase(targetKey, ignoreCase) {
if(ignoreCase) {
return this.equalsIgnoreCase(targetKey)
} else {
return this.equals(targetKey);
}
}
So the code sample becomes more readable.
bool ignoreCase = profile.isIgnoreCase();
if(masterKey.equalsCheckCase(targetKey, ignoreCase)) {
if(masterValue.equalsCheckCase(targetValue, ignoreCase)) {
doOK(masterKey, masterValue);
break;
} else if(checkErrors) {
doError(masterKey, masterValue, targetValue);
break;
}
}
Related
Here I have the enum class:
enum class wahl {
schere , stein , papier
};
And then I overload the operator < and >
bool operator<(wahl &wahl1, wahl &wahl2) {
switch (wahl1) {
case wahl::papier: {
if (wahl2 == wahl::schere) {
return true; break;
} //papier < schere
else if (wahl2 == wahl::stein) {
return false; break;
} //papier > stein
else {
return false; break;
}
}
case wahl::schere: {
if (wahl2 == wahl::stein) {
return true; break;
} //schere < stein
else if (wahl2 == wahl::papier) {
return false; break;
} //schere > papier
else {
return false; break;
}
}
case wahl::stein: {
if (wahl2 == wahl::papier) {
return true; break;
} //stein < papier
else if (wahl2 == wahl::schere) {
return false; break;
} //stein > schere
else {
return false; break;
}
}
}
};
bool operator > (const wahl wahl1, const wahl wahl2) {
switch (wahl1) {
case wahl::papier: {
if (wahl2 == wahl::schere) {
return false; break;
}
// papier < schere
else if (wahl2 == wahl::stein) {
return true; break;
} //papier > stein
else {
return false; break;
}
}
case wahl::schere: {
if (wahl2 == wahl::stein) {
return false; break;
} //schere < stein
else if (wahl2 == wahl::papier) {
return true; break;
} //schere > papier
else {
return false; break;
}
}
case wahl::stein: {
if (wahl2 == wahl::papier) {
return false; break;
} //stein < papier
else if (wahl2 == wahl::schere) {
return true; break;
} //stein > schere
else {
return false; break;
}
}
}
};
I have another class, named player :
class player {
wahl pl_wahl;
int pl_score;
char* pl_name;
public:
player() {}
player(int score, wahl wahl, char* name) :
pl_wahl{ wahl }, pl_score{ score }, pl_name{ name } {}
wahl pl_get_wahl() {
return pl_wahl;
}
char* pl_get_name() {
return pl_name;
}
int &pl_get_score() {
return pl_score;
}
};
And here where I used the comparator :
class game {
player game_player1, game_player2, game_momentan_gewinner;
int game_score_max;
public:
game() {}
game(player player1, player player2, int score_max) :
game_player1{player1},
game_player2{player2},
game_score_max{ score_max } {}
void vergleichen() {
if (game_player1.pl_get_wahl() > game_player2.pl_get_wahl()) {
game_momentan_gewinner = game_player1;
std::cout << "Gewinner dieser Runde ist Player 1 : " <<
game_momentan_gewinner.pl_get_name() << std::endl;
}
if (game_player1.pl_get_wahl() < game_player2.pl_get_wahl()) {
game_momentan_gewinner = game_player2;
std::cout << "Gewinner dieser Runde ist Player 2 : " <<
game_momentan_gewinner.pl_get_name() << std::endl;
}
else {
std::cout << "Remis" << std::endl;
}
}
};
The problem that I have, is enum will be proceed as int. And if I ask the compare two enum variables, the result will depend on the int value rather than taking the value, that I have set with the overloaded operator.
Is there any way, that i can stop the compiler to use the int value of the enum variables, and compare the enum variables in the way I want like in the overloaded operator?
If you use correct signature, it should be ok:
bool operator<(wahl lhs, wahl rhs);
bool operator>(wahl lhs, wahl rhs);
Demo
I have the following problem already longer time. The point ist that I have read a bit on stackoverflow and I have used a typedef, but I doesnt help me.
Looking forward to get some help :)
Align_vector.h :
#include <utils/vector_2d.h>
class Vector_2d;
namespace Utils {
class Align_vector : public Vector_2d {
protected:
bool check_range(int x, int y);
public:
typedef enum {left, right, up, down} Alignment;
Align_vector(Alignment alignment);
void set_alignment(Alignment alignment);
Alignment get_alignment();
};
} /* namespace Utils */
Align_vector.cc :
#include <utils/align_vector.h>
namespace Utils {
Align_vector::Align_vector(Alignment alignment) {
this->alignment = alignment;
}
void set_alignment(Alignment alignment) {
Align_vector::alignment = alignment;
}
Alignment get_alignment() {
return Align_vector::alignment ;
}
bool check_range(int x, int y) {
switch ( Align_vector::alignment ) {
case Align_vector::left:
if (x == -1 && y == 0) {
return true;
} else {
return false;
}
break;
case Align_vector::right:
if (x == 1 && y == 0) {
return true;
} else {
return false;
}
break;
case Align_vector::down:
if (x == 0 && y == -1) {
return true;
} else {
return false;
}
break;
case Align_vector::up:
if (x == 0 && y == 1) {
return true;
} else {
return false;
}
break;
default:
return false;
break;
}
}
} /* namespace Utils */
Here is the error:
/utils/align_vector.cc:14:47: error: no matching function for call to ‘Utils::Vector_2d::Vector_2d()’
Align_vector::Align_vector(Alignment alignment) {
This code has numerous issues. First of all, you have defined an
enum called Alignment, but you did not declare a member
of that type. To do so, add this line after the definition of the enum:
Alignment alignment;
Your definitions of methods are also incorrect, the alignment is
supposed to belong to a specific object, while you are using it in
several functions as if it were a static member of the class. Here
are the fixed versions of method definitions:
namespace Utils {
Align_vector::Align_vector(Alignment alignment) {
this->alignment = alignment;
}
void Align_vector::set_alignment(Alignment alignment) {
this->alignment = alignment;
}
Align_vector::Alignment Align_vector::get_alignment() {
return this->alignment;
}
bool Align_vector::check_range(int x, int y) {
switch(this->alignment) {
case Align_vector::left:
if(x == -1 && y == 0) {
return true;
}
else {
return false;
}
break;
case Align_vector::right:
if(x == 1 && y == 0) {
return true;
}
else {
return false;
}
break;
case Align_vector::down:
if(x == 0 && y == -1) {
return true;
}
else {
return false;
}
break;
case Align_vector::up:
if(x == 0 && y == 1) {
return true;
}
else {
return false;
}
break;
default:
return false;
break;
}
}
} /* namespace Utils */
Finally, you are missing a definition of a default constructor for base
class Vector_2d (your comments suggest that you did not define that class
at all, you just declared its existance using statement class Vector_2d;).
Judging by your overall implementation, I think user #molbdnilo was correct
when suggesting you should learn more about C++ programming in general.
Hope this helps!
I am making a move function for a game and I get a expected expression error I can't figure out why, it seems legal what i did.
void Ant::move()
{
int dir=rand()%4;
if (dir==0)
{
if ((y>0) && (world->getAt(x,y-1)==NULL))
{
world->setAt(x,y-1,world->getAt(x,y));
world->setAt(x,y,NULL);
y++;
}
}
else
{
if ((x<WORLDSIZE-1) && (world->getAt(x+1,y)==NULL))
{
world->setAt(x-1,y,world->getAt(x,y));
world->setAt(x,y,NULL);
x--;
}
}
else
{
if ((x<WORLDSIZE-1) && (world-getAt(x+1,y)==NULL))
{
world->setAt(x+1,y,world->getAt(x,y));
world->setAt(x,y,NULL);
x++;
}
}
}
The problem is the second else call.
I think the problem is:
world-getAt(x+1,y)==NULL
You forgot the >
world->getAt(x+1,y)==NULL
In the second if statement.
There is an if missing after the first else. You have now
if {
...
} else { // here you need an if - or revise the structure
} else {
}
For instance try ...
void Ant::move()
{
int dir=rand()%4;
if (dir==0)
{
if ((y>0) && (world->getAt(x,y-1)==NULL))
{
world->setAt(x,y-1,world->getAt(x,y));
world->setAt(x,y,NULL);
y++;
} else
if ((x<WORLDSIZE-1) && (world->getAt(x+1,y)==NULL))
{
world->setAt(x-1,y,world->getAt(x,y));
world->setAt(x,y,NULL);
x--;
} else
if ((x<WORLDSIZE-1) && (world-getAt(x+1,y)==NULL))
{
world->setAt(x+1,y,world->getAt(x,y));
world->setAt(x,y,NULL);
x++;
}
}
}
How can we append the two string in bb10???
I m to make a calculator for blackberry but get some errors.
Please help me out.
I got error in this code:
void CalcTrial::oneButtonClicked()
{
// Change the button text when clicked
if(textf==NULL)
{
textf->setText("1");
}
else
{
textf->QString+"1";
}
}
void CalcTrial::twoButtonClicked()
{
if(textf==NULL)
{
textf->setText("2");
}
else
{
textf->QString+"2";
}
}
void CalcTrial::threeButtonClicked()
{
if(textf==NULL)
{
textf->setText("3");
}
else
{
textf->QString+"3";
}
}
void CalcTrial::fourButtonClicked()
{
if(textf==NULL)
{
textf->setText("4");
}
else
{
textf->QString+"4";
}
}
void CalcTrial::fiveButtonClicked()
{
if(textf==NULL)
{
textf->setText("5");
}
else
{
textf->QString+"5";
}
}
void CalcTrial::sixButtonClicked()
{
if(textf==NULL)
{
textf->setText("6");
}
else
{
textf->QString+"6";
}
}
void CalcTrial::sevenButtonClicked()
{
if(textf==NULL)
{
textf->setText("7");
}
else
{
textf->QString+"7";
}
}
void CalcTrial::eightButtonClicked()
{
if(textf==NULL)
{
textf->setText("8");
}
else
{
textf->QString+"8";
}
}
void CalcTrial::nineButtonClicked()
{
if(textf==NULL)
{
textf->setText("9");
}
else
{
textf->QString+"9";
}
}
void CalcTrial::zeroButtonClicked()
{
if(textf==NULL)
{
textf->setText("0");
}
else
{
textf->QString+"0";
}
}
void CalcTrial::addButtonClicked()
{
operation=1;
temp1 = QString(getchar())+textf;
textf->setText(NULL);
}
void CalcTrial::minusButtonClicked()
{
operation=2;
temp1 = QString(getchar())+textf;
textf->setText(NULL);
}
void CalcTrial::mulButtonClicked()
{
operation=3;
temp1 = QString(getchar())+textf;
textf->setText(NULL);
}
void CalcTrial::divButtonClicked()
{
operation=4;
temp1 = QString(getchar())+textf;
textf->setText(NULL);
}
void CalcTrial::equalButtonClicked()
{
temp2 = QString(getchar())+temp1;
switch (operation) {
case 1:
result=temp1+temp2;
break;
case 2:
result=temp1-temp2;
break;
case 3:
result=temp1*temp2;
break;
case 4:
result=temp1/temp2;
break;
default:
break;
}
textf->text(result);
}
To convert QString to an int:
QString strNum = "22";
int intNum = strNum.toInt();
The many repetitious switch statements seems like it needs to be DRY'd. Any suggestions? (Including doing nothing!)
AnimMapIter _iter;
_iter = _animations->find(name);
if(_iter == _animations->end()) return;
if(_curName != name) {
_curName = name;
switch(dir) {
case DIR_FORWARD_LOOPING: /* Fall through to DIR_FORWARD_NONLOOPING */
case DIR_FORWARD_NONLOOPING:
_iter->second->First();
break;
case DIR_REVERSE_LOOPING: /* Fall through to DIR_REVERSE_NONLOOPING */
case DIR_REVERSE_NONLOOPING:
_iter->second->Last();
break;
}
} else {
switch(dir) {
case DIR_FORWARD_LOOPING: /* Fall through to DIR_FORWARD_NONLOOPING */
case DIR_FORWARD_NONLOOPING:
_iter->second->Next();
break;
case DIR_REVERSE_LOOPING: /* Fall through to DIR_REVERSE_NONLOOPING */
case DIR_REVERSE_NONLOOPING:
_iter->second->Previous();
break;
}
switch(dir) {
case DIR_FORWARD_LOOPING:
if(_iter->second->IsAtEnd())
_iter->second->First();
break;
case DIR_FORWARD_NONLOOPING:
if(_iter->second->IsAtEnd())
_iter->second->Last();
break;
case DIR_REVERSE_LOOPING:
if(_iter->second->IsAtFront())
_iter->second->Last();
break;
case DIR_REVERSE_NONLOOPING:
if(_iter->second->IsAtFront())
_iter->second->First();
break;
}
}
Everything under the else should collapse into a single switch to bring the related steps closer; e.g.
case DIR_FORWARD_LOOPING:
_iter->second->Next();
if (_iter->second->IsAtEnd()) {
_iter->second->First();
}
break;
...all in that one case. Repetition of a couple of function calls is not a big deal when it makes the overall sequence of actions more clear.
Push the logic into whatever _iter->second is, along these lines (assuming the methods you've already shown exist):
class WhateverItIs
{
public:
void Start() { if (m_forward) First(); else Last(); }
void Stop() { if (m_forward) Last(); else First(); }
void Advance()
{
if (m_forward)
Next();
else
Previous();
if (IsLast())
{
if (m_loop)
Start();
else
Stop();
}
}
private:
bool IsLast() const
{
return m_forward ? IsAtEnd() : IsAtFront();
}
// Direction and looping are independent concepts.
bool m_forward;
bool m_loop;
};
Then you can write:
AnimMapIter _iter;
_iter = _animations->find(name);
if(_iter == _animations->end()) return;
if(_curName != name) {
_curName = name;
_iter->second->Start();
} else {
_iter->second->Advance();
}
Edit: Example using free functions and keeping the constants.
void Start(Strip* s, bool forward)
{ if (forward) s->First(); else s->Last(); }
void Stop(Strip* s, bool forward)
{ if (forward) s->Last() else s->First(); }
void Advance(Strip* s, bool forward, bool loop)
{
if (forward)
s->Next();
else
s->Previous();
if (IsLast(s, forward))
{
if (loop)
Start(s);
else
Stop(s);
}
}
bool IsLast(const Strip* s, bool forward) const
{
return forward ? s->IsAtEnd() : s->IsAtFront();
}
bool Projector::IsForward() const
{
return dir == DIR_FORWARD_LOOPING || dir == DIR_FORWARD_NONLOOPING;
}
bool Projector::IsLooping() const
{
return dir == DIR_REVERSE_LOOPING || dir == DIR_FORWARD_LOOPING;
}
if(_curName != name) {
_curName = name;
Start(_iter->second, IsForward());
} else {
Advance(_iter->second, IsForward(), IsLooping());
}