c++ pointer to function and void pointers iteraction resulting in wierd things - c++

Im making a little project at home about genetic algorithm. But im trying to make it generic, so i use pointers to function and void pointers. but i think it might be making some problems.
The main goal of this section of the project is to get a pointer to a function, which return a certain struct. The struct containing a void pointer
and when im trying to view the value of where it points too it isn`t quite right.I suspect that maybe the interaction between these two might be causing me some problems.
details:
struct:
struct dna_s{
int size;
void *dna;
};
population is a class contaning all the population for the process. besides, it contains 2 functions as well, init_func and fitter_func which are both pointers to functions.
pointer to function definition:
typedef dna_s (*init_func_t)();
typedef int (*fitter_func_t)(dna_s);
population class:
class population{
private:
// Parameters
int population_size;
node *pop_nodes;
// Functions
init_func_t init_func;
fitter_func_t fitter_func;
public:
population(int pop_size,init_func_t initialization_func){
// Insert parameters into vars.
this->population_size = pop_size;
this->init_func = initialization_func;
// Create new node array.
this->pop_nodes = new node[this->population_size];
for(int i = 0;i < this->population_size; i++){
dna_s curr_dna = this->init_func();
char *s = static_cast<char*>(curr_dna.dna);
cout << s << endl;
this->pop_nodes[i].update_dna(curr_dna);
}
}
};
You can see that in the constructor im inserting a pointer to function, init_func. this function is generating random words.
init_func:
dna_s init_func(){
string alphanum = "0123456789!##$%^&*ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
char init_s[STRING_SIZE+1] = {};
dna_s dna;
// Generate String
for(int i = 0; i < STRING_SIZE; i++){
init_s[i] = alphanum[rand() % alphanum.size()];
}
cout << "-->" << init_s << endl;
// Insert into struct.
dna.size = STRING_SIZE;
dna.dna = static_cast<void*>(&init_s);
// Return it
return dna;
}
the main function is not so interesting but it might be connected:
int main(){
// Init srand
srand(time(0));
// Parameters
int population_size = 10;
population pop(population_size, init_func);
}
now for the interesting part, whats the problem?
in the init_func the cout prints:
-->e%wfF
which is all good
but in the population class the cout prints:
e%Ω²(
and the wierd thing is the first 2 characters will always be the same, but the other 3 will always be this string Ω²(.
example:
-->XaYN7
XaΩ²(
-->oBK9Q
oBΩ²(
-->lf!KF
lfΩ²(
-->RZqMm
RZΩ²(
-->oNhMC
oNΩ²(
-->EGB6m
EGΩ²(
-->osafQ
osΩ²(
-->3#NQt
3#Ω²(
-->D62l0
D6Ω²(
-->tV#mu
tVΩ²(

Your code has a few lifetime issues. In your dna_S struct:
void *dna;
This is a pointer, it points to an object that exists elsewhere. Then, in your init_func:
dna_s init_func(){
...
char init_s[STRING_SIZE+1] = {};
dna_s dna;
...
dna.dna = static_cast<void*>(&init_s);
...
return dna;
}
init_s is a variable that exists inside init_func, you make dna point to that variable and then leave the function. init_s ceases to exist at this point, dna is pointing nowhere useful when the population constructor gets it, causing undefined behavior.
You could work around that by allocating memory with new char[], like you did for pop_nodes, but you are responsible for deleting that memory when it is no longer used.

Related

How to initialize an array that is private in a class using constructor at runtime?

I have made a class Graph when I have made a pointer in private access in the class named visited. In the constructor I have initialized the array with zero at all places but when I am checking if all the values are zero in another method ,It is showing garbage values in the array but when I print it in the constructor itself then it showing all zeroes.
#include<iostream>
#include<vector>
#include<list>
using namespace std;
class Graph {
private:
int vertices,edges;
vector <list<int>> graph;
vector <int> vs;
int *visited;
public:
Graph (int vertices)
{
this->vertices = vertices;
list <int>l;
for (size_t i = 0; i < vertices; i++) {
graph.push_back(l);
vs.push_back(i);
}
edges=0;
// ####### made a new array, initialized all values with zeroes and assigned it to the instance variable visited #########
int a[vertices]={0};
this->visited = a;
// ######## in the constructor it is showing correct values below #######
for (size_t i = 0; i < vertices; i++) {
std::cout << this->visited[i] << ' ';
}
std::cout << '\n';
}
virtual ~Graph ()
{
}
void showList()
{
// just printing the graph in the form of adjacency list
// it is working fine
for (size_t i = 0; i < vertices; i++)
{
list <int>::iterator p = graph[i].begin();
std::cout << i ;
for (; p != graph[i].end() ; p++)
{
std::cout << " -> " << *p ;
}
std::cout << " -> NULL" << '\n';
}
// ######## when I am checking the values here then it is printing garbage values
for (size_t i = 0; i < this->vertices; i++) {
std::cout << this->visited[i] << ' ';
}
}
void addEdge(int source, int destination)
{
graph[source].push_back(destination);
}
};
int main()
{
Graph g(6);
g.addEdge(0,1);
g.addEdge(0,2);
g.addEdge(1,0);
g.addEdge(1,3);
g.addEdge(1,4);
g.addEdge(2,0);
g.addEdge(2,4);
g.showList();
return 0;
}
when i call the showList method the it should print the adjacenct list and all zeroes(contents of array named visited)
I have made a class Graph.
Yes you have.
class Graph {
I have made a pointer in private access in the class named visited.
Yes you have.
private:
int *visited;
In the constructor I have initialized the array with zero at all places.
Yes you have.
int a[vertices]={0};
But I would note that this is a variable that is local to the constructor. It is not visible to any other methods. Also when the constructor finishes the lifespan of this object ends. Any attempt to accesses this array after its lifetime ends is undefined behavior. So accessing this by some sneaky mechanism (like savings its address in a pointer) is going to cause bad things to happen.
Here you are doing something sneaky (and very bad):
this->visited = a;
but when I am checking if all the values are zero in another method
You are accessing the array through a pointer visited. This is pointing to an array that no longer exists because the array is local to another function.
std::cout << this->visited[i] << ' '; // This is broken code.
It is showing garbage values in the array
You are very unlucky. It would have been nicer if the program had crashed and made it more obvious that something bad is happening. Unfortunately you have discovered that undefined behavior can do anything (including simply return some random values).
but when I print it in the constructor itself then it showing all zeroes.
It is still valid in the constructor so accessing it is not a problem.
So what is the solution.
In general pointers you should avoid pointers (especially when brand new). You need to get some basic concepts down first.
In this case simply replace:
int* visited;
With
std::vector<int> visited;
In the constructor fill this with the appropriate zero values.

Data don't insert into an array of pointers

I have my class CompressionAlgorithm from which classes RLE and MTF inherits. I made an array to which I am trying to add these child classes but only first class gets added.
int const size = 2;
CompressionAlgorithm * CA[size];
CA[0] = new RLE();
CA[1] = new MTF();
Both RLE and MTF get initialized but when I am trying to print their name using printall method MTF doesn't get any info printed on console or I am getting an error saying std::bad_alloc.
Print p;
p.printall(*CA, (size));
void Print::printall(CompressionAlgorithm *ca, int size)
{
for (int i = 0; i < size; i++)
{
cout << i+1 << " for ";
cout << ca[i].GetName();
cout << "\n";
}
}
Where am I making a mistake?
You need make function to accept array of pointers not just a pointer:
void Print::printall(CompressionAlgorithm *ca[], int size)
and whil calling you need to call like this:
p.printall(CA, (size));
You don't need to dereference the pointer when passing it to the function; doing so only passes the first element. Additionally the function signature needs to accept an array of pointers, which is what you have.
instead of calling *ca in the printall() call only ca as calling *ca only accesses the first element of the array when not in a loop.

Returning a string * type array from a function back into the main

I'm new to C++ and I am working on a function to shuffle strings
It takes an array of strings, shuffles them, and returns them back to the main.
I am returning a pointer to an array of strings called shuffled. The problem I have is that when I try to save that new pointer to the array to another pointer in the main, I start getting weird values that either reference to a file location in my computer or a bunch of numbers.
I'll post the entire code here but really what you want to look at is the return types, how I return it and how I save it in main. Please tell me why my pointer is not referencing the working array that is created in the function. Here's the code:
#include <cstdio>
#include <string>
#include <ctime>
#include <new>
#include <cstdlib>
using namespace std;
const char * getString(const char * theStrings[], unsigned int stringNum)
{
return theStrings[stringNum];
}
string * shuffleStrings(string theStrings[])
{
int sz = 0;
while(!theStrings[sz].empty())
{
sz++;
}
sz--;
int randList[sz];
for(int p = 0; p < sz; p++)
{
randList[p] = sz;
}
srand(time(0));//seed randomizer to current time in seconds
bool ordered = true;
while(ordered)
{
int countNumberInRandList = 0;//avoid having a sz-1 member list length (weird error I was getting)
for(int i = 0; i < sz; i++)
{
int count = 0;
int randNum = rand()%(sz+1);//get random mod-based on size
for(int u = 0; u < sz; u++)
{
if(randList[u] != randNum)
{
count++;
}
}
if(count == sz)
{
randList[i] = randNum;
countNumberInRandList++;
}
else
i--;
}
//check to see if order is same
int count2 = 0;
for(int p = 0; p < sz; p++)
{
if(randList[p] == p)
{
count2++;
}
}
if(count2 < sz-(sz/2) && countNumberInRandList == sz)
{
ordered = false;
}
}
string * shuffled[sz];
for(int r = 0; r < sz; r++) //getting random num, and str list pointer from passed in stringlist and setting that value at shuffled [ random ].
{
int randVal = randList[r];
string * strListPointer = &theStrings[r];
shuffled[randVal] = strListPointer;
}
for(int i = 0; i < sz; i++)
{
printf("element %d is %s\n", i, shuffled[i]->c_str());//correct values in a random order.
}
return *shuffled;
}
int main()
{
string theSt[] = {"a", "b", "pocahontas","cashee","rawr", "okc", "mexican", "alfredo"};
string * shuff = shuffleStrings(theSt);//if looped, you will get wrong values
return 0;
}
Strings allocate their own memory, no need to give them the "length" like you would have to do for char arrays. There are several issues with your code - without going into the details, here are a few working/non-working examples that will hopefully help you:
using std::string;
// Returns a string by value
string s1() {
return "hello"; // This implicitly creates a std::string
}
// Also returns a string by value
string s2() {
string s = "how are you";
return s;
}
// Returns a pointer to a string - the caller is responsible for deleting
string* s3() {
string* s = new string;
*s = "this is a string";
return s;
}
// Does not work - do not use!
string* this_does_not_work() {
string s = "i am another string";
// Here we are returning a pointer to a locally allocated string.
// The string will be destroyed when this function returns, and the
// pointer will point at some random memory, not a string!
// Do not do this!
return &s;
}
int main() {
string v1 = s1();
// ...do things with v1...
string v2 = s2();
// ...do things with v2...
string* v3 = s3();
// ...do things with v3...
// We now own v3 and have to deallocate it!
delete v3;
}
There are a bunch of things wrong here -- don't panic, this is what happens to most people when they are first wrapping their brains around pointers and arrays in C and C++. But it means it's hard to put a finger on a single error and say "this is it". So I'll point out a few things.
(But advance warning: You ask about the pointer being returned to main, your code does indeed do something wrong with that, and I am about to say a bunch of things about what's wrong and how to do better. But that is not actually responsible for the errors you're seeing.)
So, in shuffleStrings you're making an array of pointers-to-string (string * shuffled[]). You're asking shuffleStrings to return a single pointer-to-string (string *). Can you see that these don't match?
In C and C++, you can't actually pass arrays around and return them from functions. The behaviour you get when you try tends to be confusing to newcomers. You'll need to understand it at some point, but for now I'll just say: you shouldn't actually be making shuffleStrings try to return an array.
There are two better approaches. The first is to use not an array but a vector, a container type that exists in C++ but not in C. You can pass arrays around by value, and they will get copied as required. If you made shuffleStrings return a vector<string*> (and made the other necessary changes in shuffleStrings and main to use vectors instead of arrays), that could work.
vector<string *> shuffleStrings(...) {
// ... (set things up) ...
vector<string *> shuffled(sz);
// ... (fill shuffled appropriately) ...
return shuffled;
}
But that is liable to be inefficient, because your program is then having to copy a load of stuff around. (It mightn't be so bad in this case, because a smallish array of pointers isn't very large and because C++ compilers are sometimes able to figure out what you're doing in cases like this and avoid the copying; the details aren't important right now.)
The other approach is to make the array not in shuffleStrings but in main; to pass a pointer to that array (or to its first element, which turns out to be kinda equivalent) into shuffleStrings; and to make shuffleStrings then modify the contents of the array.
void shuffleStrings(string * shuffled[], ...) {
// ... (set things up) ...
// ... (fill shuffled appropriately) ...
}
int main(...) {
// ...
string * shuffled[sz];
shuffleStrings(shuffled, theSt);
// output strings (main is probably a neater place for this
// than shuffleStrings)
}
Having said all this, the problems that are causing your symptoms lie elsewhere, inside shuffleStrings -- after all, main in your code never actually uses the pointer it gets back from shuffleStrings.
So what's actually wrong? I haven't figured out exactly what your shuffling code is trying to do, but that is where I bet the problem lies. You are making this array of pointers-to-string, and then you are filling in some of its elements -- the ones corresponding to numbers in randList. But if the numbers in randList don't cover the full range of valid indices in shuffled, you will leave some of those pointers uninitialized, and they might point absolutely anywhere, and then asking for their c_strs could give you all kinds of nonsense. I expect that's where the problem lies.
Your problem has nothing to do with any of the stuff you are saying. As you are a beginner I would suggest not presuming that your code is correct. Instead I would suggest removing parts that are not believed to be problematic until you have nothing left but the problem.
If you do this, you should quickly discover that you are writing to invalid memory.
part two : you can't seem to decide on the type of what you are returning. Are you building a pointer to an array to return or are you returning an array of pointers.... you seem to switch between these intermittently.
part three : read #Gareth's answer, he explains about passing parameters around nicely for your instance.

Adding element to array of struct c++

Can someone explain why this code does not work? It keeps crashing when it asks for input in addCar().
I think something is wrong with copying an array, but I can't figure out what exactly. I also tried to use copy() but it didn't work either.
#include <iostream>
#include <string>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
struct Car{
string Brand;
string model;
long mileage;
};
void addCar(int *ptr, struct Car *arra){
*ptr=*ptr+1;
Car *newArr = new Car[*ptr];
memcpy(newArr, arra, (*ptr)*sizeof(Car));
cout<<"Brand ";
getline(cin,newArr[*ptr].Brand);
cout<<"Model ";
getline(cin, newArr[*ptr].model);
cout<<"mileage ";
cin>>newArr[*ptr].mileage;
arra=newArr;
};
int main(int argc, char** argv) {
int size=1;
int *ptr_size;
ptr_size=&size;
Car *tab=new Car[*ptr_size];
tab[0].Brand = "Audi";
tab[0].model = "A8";
tab[0].mileage = 14366;
addCar(*ptr_size, tab);
return 0;
}
The fail is probably here:
getline(cin,newArr[*ptr].Brand);
A bit above, you did this: *ptr=*ptr+1; and made newArr an array of *ptr elements. Arrays are origin zero. That means the first item in the array is newArr[0]. The last will be at newArr[*ptr-1], so writing into newArr[*ptr] is writing over someone else's memory. Generally a bad thing to do.
But this is also not cool:
*ptr=*ptr+1;
Car *newArr = new Car[size+1];
memcpy(newArr, arra, (*ptr)*sizeof(Car));
You increment the size of the array. That's OK.
You create a new array with the new size. That's OK.
You copy new size number of elements from the old array to the new array and over shoot the end of the old array. Not OK.
The best answer is given by Jerry Coffin and Paul McKenzie in the comments: use a std::vector. If this is not allowed... Ick.
But alrighty then.
First, memcpy literally copies a block of memory. It does not know or care what that block of memory is or what it contains. Never use memcpy unless you are copying something really, really simple like basic data type or a structure made up of nothing but basic data types. String is not basic. The data represented by a string might not be inside the string. In that case, you copy a pointer to the string and that pointer will not be valid after the death of the string. That's not a problem in your case because you don't kill the string. That leads to problem 2. Let's fix that before you get there. The easiest way (other than vector) is going to be:
for (int index = 0; index < *ptr-1; index++)
{
newArr[index] = arra[index];
}
An optimization note. You don't want to resize and copy the array every time you add to it. Consider having two integers, one size of array and the other index into array and double the size of the array every time the index is about to catch up with the size.
When you allocate any memory for data with new somebody has to clean up and put that memory back with delete. In C++ that somebody is you. so, before you arra=newArr; you need to delete[] arra;
Passing in the array index as a pointer overcomplicates. Use a reference or just pass by value and return the new index. Also, don't name a variable ptr. Use something descriptive.
void addCar(int &arrasize, struct Car *arra){
or
int addCar(int arrasize, struct Car *arra){
Next problem: int addCar(int arrasize, struct Car *arra){ passes in a pointer to arra. But you passed the pointer by value, made a copy of the pointer, so when you change the pointer inside the function, it's only the copy that got changed and the new array is not going to come back out again. So,
int addCar(int arrasize, struct Car * & arra){
Passes in a reference to the pointer and allows you to modify the pointer inside the function.
Putting all that together:
int addCar(int size, struct Car * & arra)
{
Car *newArr = new Car[size + 1];
for (int index = 0; index < size; index++)
{
newArr[index] = arra[index];
}
cout << "Brand ";
getline(cin, newArr[size].Brand);
cout << "Model ";
getline(cin, newArr[size].model);
cout << "mileage ";
cin >> newArr[size].mileage;
delete[] arra;
arra = newArr;
return size+1;
}
int main()
{
int size=1;
Car *tab=new Car[size];
tab[0].Brand = "Audi";
tab[0].model = "A8";
tab[0].mileage = 14366;
size = addCar(size, tab);
// do more stuff;
// bit of test code here
for (int index = 0; index < size; index++)
{
cout << "Car " << index << " brand =" <<tab[index].Brand << " Model=" << tab[index].model << " mileage=" <<tab[index].mileage << endl;
}
delete[] tab;
return 0;
}
When you are copying the old array to the new one you are accessing invalid memory, remember that, in that point, arra has size *ptr-1 not *ptr, so the line should be
memcpy(newArr, arra, (*ptr-1)*sizeof(Car));
also in the other lines you should insert the new value in the *ptr-1 position because the indexes in newArr go from 0 to size-1 ie *ptr-1:
cout<<"Brand ";
getline(cin,newArr[*ptr-1].Brand);
cout<<"Model ";
getline(cin, newArr[*ptr-1].model);
cout<<"mileage ";
cin>>newArr[*ptr-1].mileage;

C++ Struct defined data passing. Simple answer im sure

I am sure this is a very simple fix and I feel dumb asking it but here it goes.
I need help with a struct and passing info from a gather function to a save or set function, and then passing it again to another function for further use.
Basically, it looks like this to start. I'll just add short snips of the code. All can be provided if you would like to see it.
I right now am just looking for the proper way to pass struct defined data from get.... to set.... functions.
struct printype
{
char dots[8][15];
int unknown15; // can have values of 0..127
string serial11_14; // 8 characters 00000000...99999999
int year8; // without century, 0..99
int month7; // 1..12
int day6; // 1..31
int hour5; // 0..23
int minute2; // 0..59
};
int getunknown15(); // prototypes
int setunknown15(int);
then we have a simple main.
int main()
{
printype pt;
pt.unknown15=getunknown15();
pt.unknown15=setunknown15(12);
pt.serial11_14=getserial11_14();
pt.serial11_14=setserial11_14("12345678");
pt.year8=getyear8();
pt.year8=setyear8(44);
pt.month7=getmonth7();
pt.month7=setmonth7(11);
pt.day6=getday6();
pt.day6=setday6(12);
pt.hour5=gethour5();
pt.hour5=sethour5(12);
pt.minute2=getminute2();
pt.minute2=setminute2(23);
cout <<"-----------------------------------------------------"<<endl;
cout <<" Let's Get Started"<<endl;
cout <<"-----------------------------------------------------"<<endl;
setup(pt.dots); // sets up the array
dpinfo(pt); // prints out the final array
ftarray(pt);
spar(pt.dots);
darray(pt.dots);
}
and finally the get and set array functions.
int getunknown15()
{
printype tem;
cout <<"-----------------------------------------------------"<<endl;
cout <<" Enter the Unkown Variable (0-127): ";
cin >>tem.unknown15;
cout <<"-----------------------------------------------------"<<endl;
return tem.unknown15;
}
next is
int setunknown15(int tem)
{
printype pp;
if (tem>127||tem<0)
{
cout << "Error" << endl;
return 0;
}
else
{
pp.unknown15 = tem;
return pp.unknown15;
}
}
I hope this isn't too much to read and understand
Anyway, I know this has a really simple answer but my brain just isn't working right now.
Edit: As StilesCrisis stated, Send struct as parameter is quiet stupid in this case. better use a const reference.
Well, I am not sure if I understand your question correctly. You can simply send struct to another function as parameter, or as a pointer.
like:
void SetStruct(const printype& var);
printype GetStruct();
Is it what you are looking for?
Please use the following access to the your fields, (by reference):
struct printype *myPtr = new printype;
myPtr->day6 = 43;
When use pointer instead of a normal variable, you should use -> instead . to access your fields.
I know this is kind of old but I thought I should give it a shot, since you are using C++ and it looks like you are trying to use some OO practices (I think), you don't need to start with a struct, even though OO principles can be applied using them as well though not as elegantly.
you can define your class header file as such.
#ifndef PRINTYPE_H
#define PRINTYPE_H
#include <string>
using namespace std;
class printype
{
private: // we always want to declare our member fields private for safety/managements reasons, no one will be able to access them outside.
char dots[8][15];
int unknown15; // can have values of 0..127
string serial11_14; // 8 characters 00000000...99999999
int year8; // without century, 0..99
int month7; // 1..12
int day6; // 1..31
int hour5; // 0..23
int minute2; // 0..59
void init(); // This is the method we use to initialize our starting state.
public: // This is our public methods, how people deal with/get/set our state.
printype(); // This is our default constructor
printype(const printype& print_type); // This our copy constructor
virtual ~printype(); // This is our destructor, its virtual, making safer for inheritance.
// This is our setters/getters
void setUnknown(int unknown);
int getUnknown();
void setYear(int year);
int getYear();
void setMonth(int mont);
int getMonth();
// and well you get the idea, you can add more methods.
};
#endif
and the accompanying class source file with your functions implementation
printype::printype()
{
this->init(); // Initialize all your vatiables, safer to just define a function to this.
}
printype::printype(const printype& orig) // copy constructor
{
this->setUknown(orig.getUnknown());
this->setDay(orig.getDay());
this->setDots(orig.getDots());
// you get the idea ...
}
printype::~printype()
{
// Have anything you need to do before destroying the object.
}
void printype::init()
{
this->setUnknwon(0);
this->setyear(0);
this->setMonth(1);
char dots[8][15] = {'\0'};
this->setDots(dots);
// you get the idea, you want to initialize all your variables since, for the most part they initially hold garbage.
}
void printype::setUnknown(int unknown)
{
if (unknown >= 0 && unknown < 127)
this->unknown15 = unknown;
else
error("Expecting unknown to be between 0 and 127"); // error should probably print the error and/or exit(-1) up to u
}
int printype::setYear(int year)
{
if (year >= 1 && year <= 99)
this->year8 = year;
else
error("Expecting year between 0 and 99"); // you may want to implement an error function!
}
int printype::getYear()
{
return this->year8;
}
void printype::setDots(char dots[8][15])
{
// you may want to do some verifications
memcpy(this->dots, dots, sizeof(dots));
}
void printype::setDots(char **dots) // this is a bit unsafe, use at your own risk.
{
if (dots)
{
unsigned int index = 0;
for (index = 0; index < 8; index++)
if (dots[index])
memcpy(this->dots[index], dots[index], 15);
else
error("dots required pointer ...");
}
else
error("dots required pointer ...");
}
char **getDots() // We will be returning a copy, we don't want the internal state to be affected, from outside, by using reference or pointers.
{
char **dots = new char*[8];
unsigned int index = 0;
for (index = 0; index < 8; index++)
{
dots[index] = new char[15];
memcpy(dots[index], this->dots[index], 15);
}
return dots;
}
// and well you get the idea ...
to use your class
printype *print_type_p = new print_type();
// or
printype pront_type_p();
// use the different public method to update the internal state.
print_type_p->setYear(3);
// or
print_type.setYear(3);
print_type_p->getYear();
// and so on.