I'm getting some weird behavior with a vector in C++ I was hoping someone could help me out. I have a vector like so:
vector<Instruction*> allInstrs;
the struct for Instruction is as follows:
struct Instruction : simple_instr
{
InstrType type;
Instruction(const simple_instr& simple) : simple_instr(simple)
{
type = Simple;
loopHeader = false;
loopTail = false;
}
int Id;
bool loopHeader;
bool loopTail;
};
the problem I'm having is this:
I need to iterate through each instruction and pull out specific fields and use those to do some analysis on the instructions in the vector. To do that, I was basically doing
VariableList Variables;
void GenerateVariableList()
{
for (int i = 0; i < allInstrs.size(); i++)
{
Variables.Add(allInstrs[i]);
}
Variables.RemoveDuplicates();
}
Variable List is defined as
struct VariableList
{
void Add(simple_instr* instr)
{
PrintOpcode(instr);
switch(instr->opcode)
{
case STR_OP:
case MCPY_OP:
Add(instr->u.base.src1);
Add(instr->u.base.src2);
break;
case LDC_OP:
Add(instr->u.ldc.dst);
break;
case BTRUE_OP:
case BFALSE_OP:
Add(instr->u.bj.src);
break;
case CALL_OP:
cout << "CALL OP" <<endl;
break;
case MBR_OP:
Add(instr->u.mbr.src);
break;
case RET_OP:
if (instr->u.base.src1 != NO_REGISTER)
Add(instr->u.base.src1);
break;
case CVT_OP:
case CPY_OP:
case NEG_OP:
case NOT_OP:
case LOAD_OP:
Add(instr->u.base.dst);
Add(instr->u.base.src1);
break;
case LABEL_OP:
case JMP_OP:
break;
default:
Add(instr->u.base.dst);
Add(instr->u.base.src1);
Add(instr->u.base.src2);
break;
}
}
void Add(Variable var)
{
variableList.push_back(var);
}
void RemoveDuplicates()
{
if (variableList.size() > 0)
{
variableList.erase(unique(variableList.begin(), variableList.end()), variableList.end());
currentID = variableList.size();
}
}
VariableList()
{
currentID = 0;
}
VariableList(VariableList& varList, bool setLiveness = false, bool LiveVal = false)
{
currentID = 0;
for (int i = 0; i < varList.size(); i++)
{
Variable var(varList[i]);
if (setLiveness)
{
var.isLive = LiveVal;
}
variableList.push_back(var);
}
}
Variable& operator[] (int i)
{
return variableList[i];
}
int size()
{
return variableList.size();
}
vector<Variable>::iterator begin()
{
return variableList.begin();
}
vector<Variable>::iterator end()
{
return variableList.end();
}
protected:
int currentID;
vector<Variable> variableList;
void Add(simple_reg* reg, bool checkForDuplicates = false)
{ cout << "Register Check" <<endl;
if (reg == null)
{
cout << "null detected" << endl;
return;
}
if (reg->kind == PSEUDO_REG)
{
if (!checkForDuplicates || (checkForDuplicates && find(variableList.begin(), variableList.end(), reg->num) != variableList.end()))
{
cout << "Adding... Reg " << reg->num << endl;
Variable var(reg->num, currentID);
variableList.push_back(var);
currentID++;
}
}
}
};
When I do this though, every instruction goes to the default case statement, even though I knwo for a fact some instructions shouldn't. If I change GenerateVariableList to
void GenerateVariableList()
{
for (int i = 0; i < allInstrs.size(); i++)
{
PrintOpcode(allInstrs[i]);
Variables.Add(allInstrs[i]);
}
Variables.RemoveDuplicates();
}
so that there is now a second PrintOpCode in addition to the one in Variables.Add, the program behaves correctly. I can't understand why adding a second PrintOpcode makes it work correctly. All print Opcode is is a function with a switch statement that just prints out a specific string depending on what the value of one of simple_instr's fields is.
VariableList Variables is contained inside of a separate struct called CFG
If you need more information/code i can provide it. If the answer is obvious I apologize, I don't program in C++ very often
EDIT:
One of the answers left, deleted now though, got me the fix.
Previously I was doing
static vector<Instruction*> ConvertLinkedListToVector(simple_instr* instructionList)
{
vector<Instruction*> convertedInstructions;
int count = 0;
for (simple_instr* current = instructionList; current; count++, current = current->next)
{
//Instruction* inst = new Instruction(*current);
Instruction inst = Instruction(*current);
inst.Id = count;
convertedInstructions.push_back(&inst);
}
return convertedInstructions;
}
to make the vector, but after reading that answer I changed it back to using "new" and it works correctly now. Thanks for the help, sorry for the dumb question heh
Most likely the const simple_instr& simple passed to your constructor goes out of scope, and you keep an invalid reference/pointer to a simple_instr.
Possibly not related your problem, but certainly a potential source of strange behaviour: Your Instruction(const simple_instr& simple) constructor may be getting called when you don't intend it. Mark it explicit...
explicit Instruction(const simple_instr& simple) ...
If that causes compiler errors, then that's progress :-) You might need to write a copy constructor to make them go away, and explicitly call the old constructor where you need to.
So, there are several suspicious observations:
In your definition of VariableList you use a type called Variable - how is that type defined?
Iterating over a container should be done using an iterator:
for (vector<Intruction *>::iterator it = allInstrs.begin();
it != allInstrs.end();
++it) {
Variables.Add(*it);
}
You should consider using a vector of boost::shared_ptr, or a boost::ptr_vector instead of a vector of pointers.
I can give you a huge general overview of "don'ts" relating to your code.
You are right in this case to use classes "deriving" from simple_instr but you are doing it wrong, given that later on you do a switch statement based on type. A switch-statement based on type (rather than state) is an anti-pattern. You should be calling some virtual method of your base class.
You almost certainly do not want your derived class to copy from the base class. You want to construct it with the parameters to construct its base-class.
You want a vector of the base class pointers? And to manage lifetime probably shared_ptr
const-correctness. Some of your methods like size() should certainly be const. For others you might want two overloads.
Related
First of all sorry for too much code
Here there is a vector (teamNum) with type class, the class contain a vector (player) with type struct, it is a little complicated, but here in this function I need to check if there is a player in teamNum which contain tName equal to _tname (function parameter) contain (the player) pID equal to _pID (function parameter)
bool thereIsSimilarID(string _tname, int _pID)
{
for (int i = 0; i < teamNum.size(); i++)
{
if (teamNum[i].tName == _tname)
{
for (int j = 0; j < teamNum[i].player.size(); j++)
{
if (teamNum[i].player[j].pID == _pID)
return true;
}
}
else if (i == (teamNum.size() - 1))
{
return false;
}
}
}
And in the main
int main()
{
cout << "\n" << thereIsSimilarID("Leverpool", 1) << endl;
}
The output is 24 !!!!!
(good note that this happen just when the team (Leverpool) is the last team in the vector teamNum)
Again sorry for too much code but I need to know the bug not only fix the problem I need to learn from you
You encountered undefined behaviour.
If you take the if (teamNum[i].tName == _tname)-branch on the last element, but find no player with the correct pID, you don't return anything. Which means, that the return value is whatever random value is currently in the memory location that should hold the return value. In your case it happens to 24. But theoretically, everything could happen.
The same problem occurs when teamNum is empty.
The solution is to make sure to always return a value from a function (except if it has return type void of course):
bool thereIsSimilarID(string _tname, int _pID)
{
for (int i = 0; i < teamNum.size(); i++)
{
// In this loop return true if you find a matching element
}
// If no matching element was found we reach this point and make sure to return a value
return false;
}
You should take a look at your compiler settings and enable all the warnings. And often it's good to let it treat certain warnings as errors.
i am trying to add a developer mode in my program. since duty of car defers every month,i want give my user permission to change every single variables in my program alike duty lccost yen2taka freight
#include <iostream>
using namespace std;
class A
{
public:
int carbid,duty;
void Input()
{
cout<<"please insert the car price you want to bid for(in yen): ";
cin>>carbid;
cout<<"duty of the car: ";
cin>>duty;
}
int Exportcost()
{
int exportcost;
int servicechrg=10;
int freight=20;
exportcost=servicechrg+freight+carbid;
return exportcost;
}
int Yen2taka()
{
int yen2taka;
int taka2dollarrate=10;
int dollar2yen=1;
yen2taka=((Exportcost())/dollar2yen)*taka2dollarrate;
return yen2taka;
}
int Importcost()
{
int importcost;
int lccost=10;
int cnfcost=20;
importcost=lccost+cnfcost;
return importcost;
}
int Totalcosting()
{
int total;
int myprofit=10; //80000
total=myprofit+Importcost()+Yen2taka();
cout<<total;
return total;
}
void summary()
{
cout<<
}
};
int main()
{
x:
A ob;
ob.Input();
ob.Exportcost();
ob.Yen2taka();
ob.Importcost();
ob.Totalcosting();
int ch;
cout<<"press 1 to see the summery of the costing or 2 to restart costing again"<<endl;
cin>>ch;
switch(ch)
{
case 1:
ob.summary();
break;
case 2:
goto x;
}
}
At first, you should collect these parameters in a separate class:
class Configuration // maybe you find a better name...
{
int m_servicechrg = 10; // default
int m_freight = 20;
// ...
public:
int servicechrg() { return m_servicechrg; }
void servicechrg(int value); { /* check some limits? */ m_servicechrg = value; }
int freight() { return m_freight; }
void freight(int value); { /* check some limits? */ m_freight = value; }
// ...
};
// will allow you to do:
// C c; std::cout << c;
ostream& operator<<(ostream& s, Configuration const& c)
{
// which ever formatting is appropriate...
s << c.servicechrg() << ' ' << c.freight();
return s;
}
The setters could alternatively return bool to indicate invalid values.
Now you can use this class within main:
Configuration c;
A a;
int cost = a.exportCost(c); // you'd have to adjust signatures...
int value;
switch(ch)
{
case 4:
if(stc::cin >> freight) // catches invalid user input!
// one ALWAYS should do, otherwise you might end up in
// your program not working any more
{
c.freight(value);
// or, if you have:
if(!c.freight(value))
{
// some appropriate error message
// (it's better not to output in the setter, you are more flexible this
// way – maybe you want different messages at different occasions?)
}
}
else
{
// appropriate error handling
}
break;
default:
// handling invalid user input
// again, you always should; but stream state is not in error state,
// so you just can print appropriate error message
break;
}
See this answer for how to correctly handle stream errors.
If you wonder about the differences in error handling: First case is met if user enters non-numerical input, such as ss, second case, if input is numerical, but out of valid range (77).
Now if you don't want to pass the configuration as parameter all the time, you could make a global variable from (but careful, there are some dangers with global variables, use them as sparely as possible) or implement the singleton pattern.
Side notes: goto can be a fine tool sometimes, but it is a dangerous one (and the label's name x isn't a good one, prefer a name that clearly shows intention, such as REENTRY_POINT, LOOP_START, ...). If you can get along without unreasonable effort, prefer such variants:
bool isRunning = true;
do
{
// ...
case 2:
isRunning = false;
break;
}
while(isRunning);
Sure, an additional variable, an additional check; unfortunately, you cannot use break to exit a (pseudo-) endless loop (for(;;)) (but don't apply this pattern for nested loops, then it gets more and more unreadabla – and ineffcient: bool isExit = false; for(int i = 0; !isExit && i < n; ++i) { for(j = 0; j < n; ++j) { isExit = true; break; } } – see what I mean?). A variant might be:
for(;;)
{
switch(ch)
case 1:
// ...
//break; <- replace
continue;
case 2:
//
break;
} // end of switch
break; // break the surrounding for(;;) loop
}
But that's not really nice either.
A pretty nice variant allowing to exit the loop in the given case, as there isn't anyhting to do afterwards:
for(;;)
{
switch(ch)
{
case 2:
// maybe yet some cleaning up here
return 0;
default:
// ...
break;
}
}
Drawback: The function's exit point possibly is deeply nested inside the code.
There are yet other tricks to allow this pattern, like packing sub-sections of code in a lambda having a return inside and call that one directly. But that now really starts going beyond the scope...
Finally, if you insist on goto, my variant would rather be:
for(;;)
{
switch(ch)
{
case 2:
// ...
goto LOOP_EXIT;
default:
// ...
break;
}
}
LOOP_EXIT:
return 0; // e. g. main
(void)0; // if there isn't anything to do in the function any more
// (labels require an instruction afterwards!)
There won't be a hidden loop now and it is more obvious what you actually are doing. Currently, not really an issue, but if your code grows, the hidden loop gets more and more difficult to spot.
In such cases, I clearly mark the gotos so that another coder can immediately spot the critical code points:
///////////////////////////////////////////////////
// possibly some comment why applying this pattern
goto SOME_LABEL;
///////////////////////////////////////////////////
One could do the same with deeply nested function exit points (return).
so you have a collection and you want to see if NONE of the items in it pass a test. doing the if ANY pass test is easy, and would look something like this:
for (int i = 0; i < collectionSize; i++)
{
if(ItemPasses(collection[i]))
{
// do code for if any pass
break;
}
}
but to do the opposite, if NONE pass test, I cant think of a truly neat way to do it, here are the ways I can come up with:
// nice to look at but uses an unecessary variable 'anItemPassed'
bool anItemPassed = false;
for (int i = 0; i < collectionSize; i++)
{
if(ItemPasses(collection[i]))
{
anItemPassed = true;
break;
}
}
if (!anItemPassed)
{
//...
}
//---------------------------------------------------------------------------------
// as efficient as possible but uses gotos.. nobody likes gotos.. lable stuff really isnt that neat.
for (int i = 0; i < collectionSize; i++)
{
if (ItemPasses(collection[i]))
{
goto ItemPassed;
}
}
//...
ItemPassed: { }
//-------------------------------------------------------------------------
// as efficient as possible and doesnt use the rarely used (and usually poorly supported in IDEs) goto/lable stuff, but doesnt use any nice loop construct, does it all manually
int i = 0;
for (; ; )
{
if (i >= collectionSize)
{
//...
break;
}
if (ItemPasses(collection[i]))
{
break;
}
i++;
}
I dont really like any of those, I've always wondered why there was never a construct like:
for (int i = 0; i < collectionSize; i++)
{
if (ItemPasses(collection[i]))
{
break;
}
}
finally //executed if the loop terminates normally, not via breaks.
{
//...
}
so in short my question is: Is there are truly neat way to do 'if none in collection' test? if not, is there a reason why the above wouldn't be a good language feature?
EDIT:
I instantly regret putting c++ in the tags. I know there are nice functions to do this, but assuming the boost libraries or whatnot, were also written in c/c++ presumably they encountered the same problem I have. even if these functions are built in to the language, saying 'just call this function' isn't the answer I was looking for in this case.
so maybe I will focus on the last part of my question: Is there a reason why the above wouldn't be a good language feature?
in my view not having it would be like not having the 'else' keyword to go with 'if'
For C++ it's pretty trivial (C++11 with none_of, C++14 with the auto lambda)
bool noneExist = std::none_of(std::begin(collection), std::end(collection), [](auto &item){
return item.matchesCondition(); // any evaluation can go here, or you could just supply an existing functor instead of a lambda
});
I assign to a bool here, but you could as easily wrap it in an if statement (this assumes an existing function or functor object named MatchCondition, a lambda would work, but that's a lot to read in an if condition):
if(std::none_of(std::begin(collection), std::end(collection), MatchCondition)){
//run your "if none of the above matched" code here.
}
And the old C++98 method for completion:
if(std::find_if(collection.begin(), collection.end(), MatchCondition) == collection.end()){
//run your "if none of the above matched" code here.
}
"Truly neat" sounds a bit opinion based but here are a few options:
#include <iostream>
#include <algorithm>
#include <vector>
bool itemPasses(int i) {
return i > 10;
}
void printIfNonePass1(const std::vector<int>& collection) {
if (std::none_of(collection.cbegin(), collection.cend(), itemPasses))
std::cout << "None pass\n";
}
void printIfNonePass2(const std::vector<int>& collection) {
auto iter = collection.cbegin();
for(; iter != collection.cend(); ++iter) {
if (itemPasses(*iter))
break;
}
if (iter == collection.cend())
std::cout << "None pass\n";
}
void printIfNonePass3(const std::vector<int>& collection) {
size_t i = 0;
for(; i != collection.size(); ++i) {
if (itemPasses(collection[i]))
break;
}
if (i == collection.size())
std::cout << "None pass\n";
}
bool checkIfNonePass(const std::vector<int>& collection) {
for(int item : collection) {
if (itemPasses(item))
return false;
}
return true;
}
void printIfNonePass4(const std::vector<int>& collection) {
if (checkIfNonePass(collection))
std::cout << "None pass\n";
}
int main() {
std::vector<int> collection{4,2,10,3};
printIfNonePass1(collection);
printIfNonePass2(collection);
printIfNonePass3(collection);
printIfNonePass4(collection);
}
I like to achieve this by performing the no-match scenario by comparing the iterator against the max.
int i;
for (i = 0; i < collectionSize; i++)
{
if (ItemPasses(collection[i]))
{
// do code for if any pass
break;
}
}
if (i == collectionSize)
{
// perform no-match operations
}
There is no need for c++14, or c++11. Something like this should do what you want.
if (find_if(collection.begin(), collection.end(), ItemPasses) == collection.end()) {
//code if none passes
}
edit: Adding c++11 solution as response to comment.
if (none_of(collection.begin(), collection.end(), ItemPasses)) {
//code if none passes
}
2:nd edit: Answer the question.
I think you are interested the internal realization of the algorithm but not applying standard algorithms.
Usually the loop is written the following way
CollectionType::size_type i = 0;
while ( i < collectionSize && !ItemPasses(collection[i]) ) ++i;
return ( i == collectionSize );
The same can be written with iterators
while ( first != last && !ItemPasses( *first ) ) ++first;
return ( first == last );
This approach can be applied also in C programs.
In my opinion, there is no orthgonality in control structures in many languages C included.
The need is obvious, and the language should simplify the work of the programmer, albeit no much will for work and/or change is done in that direction on the side of control structures.
In 1992, I had done a complete proposal and implementation of an orthogonal set of control structures, that could be used in many languages, and the construct you request was included, that is just to confirm the recurrency of the argument and the validity of the need.
The functions of C++ while permit an elegant solution, do not solve the need any way.
An alternative solution to what you already presented is to put the code you need inside the for construct. So the code would become as bellow while the function finalizationCode() should return false.
for (int i = 0; i < collectionSize ? true : finalizationCode(); i++)
It may be better to put the || construct instead of the if ( ? : ).
So in that case:
for(int i=0 ; i < collectionSize || finalizationCode() ;i++)
It is anyway guaranted that finalizationCode will be executed only when the condition i<collectionSize
is false.
I'm creating a library. I want to make a fixed-length string class.
#include <string>
#include <iostream>
#define OK 0
#define TOO_LONG 1
#define UNALLOWED_CHARACTERS 2
struct MyString {
MyString(int l)
: m_length(l) { }
struct exception {
exception(int t, MyString *p)
: type(t), ptr(p) { }
int type;
MyString *ptr;
};
int set(const std::string& name);
void set2(const std::string& name) throw(exception);
std::string m_str;
int m_length;
};
int MyString::set(const std::string& s)
{
if(s.size() > 64) {
return TOO_LONG;
} else if(s.find('~') != std::string::npos) {
return UNALLOWED_CHARACTERS;
} else {
m_str = s;
return OK;
}
}
void MyString::set2(const std::string& s) throw(exception)
{
if(s.size() > m_length) {
throw exception(TOO_LONG, this);
} else if(s.find('~') != std::string::npos) {
throw exception(UNALLOWED_CHARACTERS, this);
} else {
m_str = s;
}
}
int main()
{
using namespace std;
//OPTION 1
{
MyString s1(10);
MyString s2(10);
int code;
code = s1.set("abcdefghijX");
switch(code) {
case TOO_LONG:
//handle <--
break;
case UNALLOWED_CHARACTERS:
//handle
break;
default:
//ok!
break;
}
code = s2.set("abcdefghi~");
switch(code) {
case TOO_LONG:
//handle
break;
case UNALLOWED_CHARACTERS:
//handle <--
break;
default:
//ok!
break;
}
}
//OPTION 2
{
MyString s1(10);
MyString s2(10);
try {
s1.set2("abcdefghijX");
s2.set2("abcdefghi~");
} catch(MyString::exception &e) {
cerr << "MyString::exception: ";
auto p = e.ptr;
if(p == &s1) cerr << "s1 ";
else if(p == &s2) cerr << "s2 ";
switch(e.type) {
case TOO_LONG: cerr << "too long"; break;
case UNALLOWED_CHARACTERS: cerr << "unallowed characters"; break;
}
cerr << endl;
}
}
}
I don't know which version of MyString::set() I should use. What is the convention in such cases? I used STL in this example for demonstration purposes.
It is a good idea to mimic the behavior of the standard library functions unless one has a specific reason not to. BTW, since tr1, STL has a fixed-length string class built in. Lets see what it does. The only example implementation I have handy is Visual C++ 2010.
std::tr1::array<int,5> arry;
arry[10] = 42; // Oopsie. There is no element 10.
When compiled and run as the "Debug" version, I get an assert failure. When compiled for "Release" the offensive statement quietly does ... NOTHING. It is optimized right out of existence. Okay, maybe that is not always what one would want. Forget what I said about mimicking the STL, or at least Microsoft's implementation. Train of consciousness continues...
I think it is fair to say that if the program tries to set an out of range cell, that is a logic error in the program. In mission-critical software it might be a good idea to have code in place to deal with a situation like that and recover from it, while trying like heck to make sure it can never, never happen.
So the answer is, throw an exception of type std::out_of_range.
So there.
In general in C++ it's recommended to use exceptions to indicate errors unrecoverable in the current context. But it depends on purpose. You may want to compile your library in an embedded environment using no exceptions (for sake of efficiency), then you have to go with return codes.
Its easy to wrap an API using return codes to one that uses exceptions, but no way vice versa.
EDIT:
Some more reasoning why it may make sense not to use exception handling:
Exception handling usually introduces additional information about try/catch blocks necessary to be placed in the call stack + some performance penalty to build and check these informations.
See also: performance of C++0x exceptions
I am trying to use STL list in a project but i have the following problem.
I want my list to store a struct. For example this one
struct mystruct
{
int x;
int y;
};
Then i am using an iterator to access every struct in the list like this.
list<mystruct> L;
list<mystruct>::iterator lit;
for(lit=L.begin();lit!=L.end();lit++)
{
if(lit->x==1) cout << "<NUM," << lit->x << "> ";
if(lit->y==2) cout << "<ID," << lit->y << "> ";
}
This works but i want to get one struct at a time so i made this func
mystruct Myclass::next(void)
{
if(lit!=L.end())
{
lit++;
}
return *lit;
}
but i get an error after running it and i cannot understand why this happens.
Any ideas what is going wrong?
mystruct Myclass::next(void)
{
if(lit!=L.end())
{
lit++;
}
return *lit;
}
You increment unless you already are at the end, but the dereferencing happens every time, regardless of if you are at the end or not. To help around that problem, consider returning a pointer, and then a 0 pointer if you are at the end.
mystruct* Myclass::next(void)
{
if(lit!=L.end() && ++lit != L.end())
{
// dereference to get the struct, and then return the address of the struct
return &*lit;
}
return 0;
// or nullptr in C++0x
}
And then check agains 0 (or nullptr) in the code where you use Myclass::next.
If you're writing next() that returns an object (rather than pointer), then I think you also need to write has_next() function which you should call to inspect if there is item in the list or not, before calling next(). Something like this:
bool has_next()
{
list<mystruct>::iterator temp = lit;
return ++temp != L.end();
}
mystruct Myclass::next(void)
{
if( !has_next())
{
throw "end of the list is reached";
}
++lit;
return *lit;
}
//usage
while(myClassInstance.has_next())
{
mystruct s = myClassInstance.next();
//work with s
}
Or if you decide to return pointer to mystruct from next(), then has_next() is not so needed. You can write this:
mystruct * Myclass::next(void)
{
++lit;
if( lit == L.end() )
return NULL;
return &(*lit);
}
The problem is here :
mystruct Myclass::next(void)
{
if(lit!=L.end())
{
lit++;
}
return *lit;
}
First how is lit defined?
Second, if lit is equal to L.end() you should return some default value, not dereference it, because if you do, you are causing an undefined behaviour. If you are lucky, your program will crash.