I wrote the following C++ code to iterate over a vector of vectors of objects. I want to iterate over every object in the vector of vectors. The code below works but it has one peculiarity I don't understand.
The line "int types_size=types->size();" is a hack employed in iterator.hpp. I don't really know the language very well so I don't know if I've found a compiler bug or if this a bug in my code. The variable "types_size" shouldn't be needed. It is used in two lines
first line:
while(s<types_size && (s<0 || (*types)[s]->size()==0 || object==&( ((*types)[s])->end()))){
second line:
if(s<types_size){
If "types_size" is replaced with "types->size()" in the first line the code will seg fault when it runs. Making the same replacement but only in the second line does not result in a seg fault. I don't understand what is going on. Any comments on the rest of this code will be appreciated.
#ifndef _iterator_hpp_
#define _iterator_hpp_
#include <vector>
using namespace std;
typedef double Object;
typedef vector<Object> ObjectVector;
class Region{
public:
vector<ObjectVector*> types;
};
class ObjectIterator{
private:
int s;
vector<ObjectVector*> *types;
protected:
public:
Object *object;
bool finished;
ObjectIterator operator++(){
if (s>=0) object++; // increments to next object
int types_size=types->size(); // this is a hack that fixes a seg fault (compiler bug??)
// *types is a vector<ObjectVector*>. (*types)[s] is the "sth" ObjectVector*.
// &(*iterator) gives a pointer to the object pointed to by iterator.
//((*types)[s])->end()) is an iterator that points past the end of
// the ObjectVector* ((*types)[s])->end())
while(s<types_size && (s<0 || (*types)[s]->size()==0 || object==&(* ((*types)[s])->end()))){
//need to increment to next non-empty types
s++;
if(s<types_size){
object=&((*(*types)[s])[0]);
}else{finished=true;}
}
return (*this);
}
/*---------------------constructor--------------------------------------------------------
start with s=-1 and increment to first object */
ObjectIterator(vector<ObjectVector*> *typesarg):finished(false) {
types=typesarg;s=-1;++(*this);
};
};
#endif
--------------------------------main--------------------------------
// it.cpp
// g++ it.pp
#include <iostream>
#include <vector>
#include "iterator.hpp"
using namespace std;
int num_types=3;
int main(){
Region region;
int num_objects[num_types];
num_objects[0]=1;
num_objects[1]=3;
num_objects[2]=5;
// create an ObjectList for each type
for(int s=0;s<num_types;s++){
ObjectVector *objectlist = new ObjectVector;
for(int i=0;i<num_objects[s];i++){
objectlist->push_back((double)2*(i+1)*(s+1));
}
region.types.push_back(objectlist);
}
cout <<"types.size="<< region.types.size()<<endl;
for(ObjectIterator OI(®ion.types); !OI.finished ; ++OI)
{
cout <<*(OI.object)<<endl;
}
}
size() returns an unsigned integer so this:
while(s<types->size()
will not behave the same if s is -1 (its initial value). -1 is turned into a large unsigned integer and the comparison is false. See Signed/unsigned comparisons for more information.
Related
I am new in C++. I created a cpp and a header file. Here is the header file:
class LISCH{
public:
class lisch_entry{
public:
bool valid;
int link;
int data;
lisch_entry(){
valid = false;
}
};
vector<lisch_entry> data_vec;
public:
LISCH(int);
void insert(int);
};
In cpp file , i need to access that data_vec vector in insert function but i couldn't do it because it's my first time coding in C++. Here is the cpp file:
#include "lisch.h"
#include <iostream>
using namespace std;
LISCH::LISCH(int table_size){
table_size=10;
int x=5;
}
void LISCH::insert(int new_data){
lisch_entry entry;
int add=new_data%11;
if(LISCH.data_vec[add] == NULL) //here i need to acces data_vec
{
}
data_vec.insert(add,new_data); //and also here
}
How can i manage to do that? I need to check if a specific position of the vector is empty or not.
There are quite a few of things wrong with code, probably for lack of planning or formulating the desired effect.
using namespace std; // never do this in real programs.
// Even some tests may fail accidently.
LISCH::LISCH(int table_size){
table_size=10; // those are local variables, why assigning values to them?
int x=5;
}
data_vec is defined as a vector of lisch_entry:
vector<lisch_entry> data_vec;
The you out of blue access element of type lisch_entry with index add. Did you allocate that many elements already? It may not exist at all, the program would crash:
if(LISCH.data_vec[add] == NULL)
An instance lisch_entry cannot be equal, cannot be compared to NULL as far as you had defined it. The check itself looks suspicious, what had you wanted to do?
data_vec.insert(add,new_data);
insert receives an iterator as first parameter. An integer value isn't an iterator. An iterator of add-th element's iterator value is data_vec.begin() + add. It looks like have to check the documentation on std::vector.
You can find shorthanded documentation here: https://en.cppreference.com/w/cpp/container/vector
If you're trying to learn C++ on your own, this may be helpful: https://isocpp.org/faq
#include<iostream>
#include <list>
using namespace std;
class Euler {
private:
int korifes = 0;
int akmes = 0;
int* pinakas[];
public:
void print() { cout << *pinakas[0]; return; }
Euler(int korifess, int akmess);
~Euler() { delete[] *pinakas; }
void addAkmes(int kor1, int kor2);
};
Euler::Euler(int korifess, int akmess) : akmes(akmess), korifes(korifess) {
*pinakas = new int(korifes);
*pinakas[0] = 89;
}
int main() {
Euler e(2, 1);
e.print();
}
Run-Time Check Failure #2 - Stack around the variable 'e' was corrupted. occurred...i can not find where i am wrong in my code.
There are a number of errors in your code, all related to the nature of the pinakas member variable. As it stands, you are declaring this as an array of pointers (to int), and, furthermore, you are using a non-standard syntax for 'flexible' arrays (the empty []).
I don't normally just paste 'fixed' code as an answer but, in this case, that code (with the added \\\ comments where I've made changes) is likely to be the most succinct way to help you.
Although, as many here will no doubt point out, it is far better to avoid the use of 'raw' pointers and the new and delete operators, and use the std::vector container, instead.
#include <iostream>
#include <list>
//using namespace std;/// This is considered 'bad practice' by many programmers
using std::cout;/// Just use the aspect of the STL that you need!
class Euler {
private:
int korifes = 0;
int akmes = 0;
int* pinakas;/// This will point an 'array' of integers
public:
void print() {
cout << pinakas[0]; return;/// No longer any need for the dereference (*)
}
Euler(int korifess, int akmess);
~Euler() {
delete[] pinakas;/// No need for the dereference (*)
}
// void addAkmes(int kor1, int kor2);/// You haven't provided an actual definition for this, but your never use it!
};
Euler::Euler(int korifess, int akmess) : akmes(akmess), korifes(korifess)/// NOTE: Members are initialized in DECLARATION order!
{
pinakas = new int[korifes];/// Use "[]" (not "()") to allocate an array!
pinakas[0] = 89;/// No need for the dereference (*)
}
Feel free to ask for any further clarification and/or explanation.
I am new to c++ but not to programming, and I am having a very baffling problem. I have class which in its constructor creates a list.
As you can see, I am printing out the final value of the list two different ways, which generally agree with each other: one using list::end, and the other using list::back. Then I call the constructor to this class in my main function, access the list that was created, and try to print the final value. The sample code is given below.
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <typeinfo>
#include <list>
#include <algorithm>
#include <queue>
using namespace std;
class Process{
public:
Process(int CB);
int CB;
};
Process::Process(int c){
CB = c;
}
class Event{
public:
Event(Process *process);
Process *process;
};
Event::Event(Process *ps){
process = ps;
}
typedef list<Event> EventList;
class DES{
public:
DES(string originFile);
EventList events;
};
DES::DES(string originFile){
ifstream infile (originFile.c_str());
string str;
while (getline(infile, str)) {
// output the line
//cout << str << endl;
istringstream iss(str);
int AT,TC,CB,IO;
if (!(iss >> AT >> TC>>CB>>IO)) {
cout<<"breaking out of while loop \n";
break;
}
Process p(CB);
Event evt(&p);
this->events.push_back(evt);
}
int cb = this->events.back().process->CB;
EventList::iterator inserter2 = this->events.begin();
EventList::iterator inserter3 = this->events.end();
//inserter3--;
//cout<<"CB after while loop using List<>::end(): " <<inserter3->process->CB<<endl;
//cout<<"CB after while loop using LIST<>::back "<<cb<<endl;
infile.close();
}
int main (int argc, char* argv[]) {
string inputFileName = argv[1];
DES des(argv[1]);
EventList::iterator b = des.events.end();
b--;
cout<<"CB at back of list in main: "<<b->process->CB<<endl;
return 0;
}
So here is where I get confused. The print statement in main should match the output of the print statements in teh constructor, since they are all simply printing the field ->process->CB of the last element of the list. However, for some reason this only works when I uncomment the line //EventList::iterator inserter2 = this->events.begin(); in my constructor. Similarly, if I keep that line and instead comment out the line EventList::iterator inserter3 = this->events.end();, it also doesn't work. Only when I construct an iterator on BOTH the end and beginning of the list does the correct value get printed out in main.
Can anyone shed some light on this odd behavior? I know it must be some simple misunderstanding due to my lack of familiarity with c++, but I have to admit this behavior seems a bit unnatural to me.
EDIT: here is the output with one of the iterators in the constructor commented out:
CB after while loop using List<>::end(): 10
CB after while loop using LIST<>::back 10
CB at back of list in main: 306496
And here is the output with both of the iterators in the constructor:
CB after while loop using List<>::end(): 10
CB after while loop using LIST<>::back 10
CB at back of list in main: 10
-Paul
You're using / storing the address of a local here:
Process p(AT,TC,CB,IO);
Event evt(AT,&p,CREATED,READY);
Once the code block that declares p is exited, any referral to that pointer results in undefined behavior.
Since Process contains a simple int, you could just store copies of Process instead of using pointers.
class Process{
public:
Process(int CB);
int CB;
};
class Event{
public:
Event(const Process& process);
Process process;
};
Event::Event(const Process& ps) : process(ps) {}
Then the first block of code would look like this:
Process p(CB);
Event evt(p);
or simply:
Event evt(Process(CB));
This should at least rid you of the inconsistent results.
If you really do need a pointer, consider smart pointers such as std::unique_ptr or if deemed necessary, std::shared_ptr instead of using raw pointers.
#include <cstdlib>
#include <string>
#include <iostream>
#define S 10
using namespace std;
struct List
{
string name;
bool male;
int year;
string addr;
string diag;
bool hosp;
};
main()
{
struct List *l=NULL;
int n=0;
for(int i=0;i<10000;i++)
{
if(!(n%S))
{
l=(List*)realloc(l,(n/S+1)*S*sizeof(struct List));
cout<<"realloc ok\n";
};
l[n].male=rand()%2;
l[n].year=1900+rand()%100;
l[n].hosp=rand()%2;
//!l[n].name="abc";
n++;
cout<<l[rand()%n].male<<" "<<l[rand()%n].year<<" "<<l[rand()%n].hosp<<endl;
}
}
If l[n].name="abc" remarked then program works fine.
If i try put string value to this field the programm compiled without warnings nay, but crash with error code -1 after first realloc.
Any way to solve it?
Since your structure is non-trivial - it contains members of class type, std::string, which need to be initialised by calling their constructors - you can't simply allocate raw memory and pretend that contains a valid object.
The simplest solution is to use a type-aware dynamic array
std::vector<List> l;
which can be resized, perserving its contents, with
l.resize((n/S+1)*S);
Tip! Using "new" operator to allocate this structure will automatically create string object for each field.
List *l=new struct List[S];
It fix this issue, l[n].name="abc" will works, but it not implements reallocation functional.
I am attempting to change a value in a vector which is a variable in a class using a function of a class. When I compile, i get the following errors pointing to the "check[c] = cval;" line:
error C3867: 'acc::check': function call missing argument list; use '&acc::check' to create a pointer to member
error C2109: subscript requires array or pointer type
Note: I have already initialized C to be 0 elsewhere in the program. It might be throwing an error because I am giving the address a variable instead of an integer, but when I substitute the variable with an integer, I still get the same errors.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstring>
using namespace std;
class acc
{
public:
void add_Cval(double cval);
private:
vector<double> check(); //vector of all checks
int c; //loop marker for cvals
};
void acc::add_Cval(double cval)
{
check[c] = cval;
c++;
}
vector<double> check(); isn't what you think it is. You just declared a function named check that returns a vector<double>. Get rid of the parenthesis like so vector<double> check;.
Also, your vector<double> is empty, you need to give it some space if you want to do check[c] = cval; (or use check.push_back(cval); instead), allocate the space in the constructor (use "initialization lists" as that is what they are for):
Example:
acc(int vecsize) : check(vecsize), c(0) {}
You might also want to make sure check[c] is a valid position in the vector before assigning anything to it.
check is a method, not a data member, so you need to invoke it - check().
void acc::add_Cval(double cval)
{
check()[c] = cval;
c++;
}
or make it a data member:
class acc
{
public:
void add_Cval(double cval);
private:
vector<double> check; //vector of all checks
int c; //loop marker for cvals
};
The compiler is looking for a function called check() that returns a vector of type double.
private:
vector<double> check(); // A private function that returns a vector of type <double>
Needs to be:
private:
vector<double> check; // A private data member