Array of structs declaration - c++

I am trying to write this C++ function in which I am trying to set each Sequence in the array of Sequences, however when I follow the code on debug I notice that the array is not changing. In particular:
compressed.data[compressedDataCounter].c = pic.data[i];
compressed.data[compressedDataCounter].times = counter+1;
don't seem to add any new variables to the array, just override the first one.
I am thinking that the root of the problem is the declaration:
CompressedPic compressed;
compressed.data = new Sequence[pic.height * pic.width];
This is the portion of the code:
struct Sequence
{
char c;
int times;
};
struct CompressedPic
{
int height;
int width;
Sequence* data;
};
struct Picture
{
int height;
int width;
char* data;
};
CompressedPic compressThePicture(Picture pic) {
CompressedPic compressed;
compressed.data = new Sequence[pic.height * pic.width];
compressed.height = pic.height;
compressed.width = pic.width;
int compressedDataCounter=0;
for(int i=0; i<(pic.height * pic.width)-1; i++)
{
int counter = 0;
while(pic.data[i] == pic.data[i+1])
{
i++;
counter++;
}
compressed.data[compressedDataCounter].c = pic.data[i];
compressed.data[compressedDataCounter].times = counter+1;
compressedDataCounter++;
}
compressed.data[compressedDataCounter].times = -1;
return compressed;
}
It would be great if someone could figure out why this is happening.

You might want to change:
compressed.data[compressedDataCounter].c = counter+1;
to:
compressed.data[compressedDataCounter].times = counter+1;
So you can change the .times member otherwise you will be overriding your .c member. Right now you are setting .c to 'a' for example. Then you set .c to 103 (counter+1). Which is an int and likely with your archetecture the high bytes are aligning with .c and setting it to 0 as well.
So .c is getting 0'd and .times is never set

Related

How to affect memory allocated by new and casted to an array od class objects?

I had hard time describing it in the title, but basically I have to turn some code from C based on structures into C++ one based on objects. At the beginnig it was more or less (I'll try to simplify since it's a part of a big library-like project):
typedef struct Thing{
int param;
char* name;
void* data; //Either some arrays or more structures, hence void*
};
Thing* Initialise(void){
Thing* thing;
thing = (Thing*)malloc(sizeof(*thing));
param = 0;
name = NULL;
data = NULL;
return thing;
}
Thing* thing1 = malloc(bytesofdata);
Thing** smallthings = (Thing**) thing1->data; //Basically if "data" is a structure of other things
for ( i = 0; i < numberofsmallthings; i++ ) {
size_t k;
for ( k = 0; k < fieldsperthing; k++ ) {
smallthings[i*fieldsperthing+k] = Initialise();
}
}
Then I turned the structure into a class and the function into its method which resulted in:
class Thing{
private:
int param;
char* name;
void* data; //Either some arrays or more structures, hence void*
public:
int Initialise(void);
};
int Thing::Initialise(void){
this->param = 0;
this->name = NULL;
this->data = NULL;
}
thing1->data = new Thing;
this->data = new char [bytesofdata];
Thing** smallthings = (Thing**)this->data;
for (i = 0; i < numberofsmallthings; i++) {
size_t k;
for (k = 0; k < fieldsperthing; k++) {
smallthings[i*fieldsperthing + k]->Initialise();
}
}
And in this version, no matter if I try initialising the memory of not I am greeted by "access violation".
Is there any way to make this work? Casting to structure seemed to work fine so my guess is that something about objects makes it not work but I have no idea how to potentially bypass this. I would like to avoid making more objects since due to this part being buried pretty deep in functions, deleting those would be quite hard (especially since it's supposed to be a data reading function so exact structure of "data" might be not known).
When you do this:
smallthings[i*fieldsperthing + k]->Initialise();
You're attempting to dereference an unintialized pointer. You first need to assign something to it, then you can initialize it:
smallthings[i*fieldsperthing + k] = new Thing;
smallthings[i*fieldsperthing + k]->Initialise();
Better yet, change Initialise to a constructor. Then you won't have to do creation and initialization in separate steps. So now you have:
int Thing::Thing(){
this->param = 0;
this->name = NULL;
this->data = NULL;
}
...
thing1 = new Thing();
this->data = (void *)new Thing *[numberofsmallthings];
Thing** smallthings = (Thing**)this->data;
for (i = 0; i < numberofsmallthings; i++) {
size_t k;
for (k = 0; k < fieldsperthing; k++) {
smallthings[i*fieldsperthing + k] = new Thing();
}
}

Segmentation fault error with structures

I have no idea where the segmentation error is coming from ... Any ideas?
I am working with structures for an assignment
TestResult testResultFactory(std::string name, double mark)
{
//creating an object of TestResult
TestResult car;
car.name = name;
car.mark = mark;
return car;
}
Student studentFactrory(std::string name)
{
//Creating an object of student
Student house;
house.name = name;
house.testResults = 0;
house.numTestResults = 0;
return house;
}
void addTestResult(Student * student, std::string testName, double testMark)
{
//First we need to create a new array
(student->numTestResults)+=1;
TestResult *newTestArray = new TestResult[(student->numTestResults)];
//Now we loop through the old array and add it to the new one
int index = (student->numTestResults);
for (size_t i = 0; i < (index-1); i++)
{
newTestArray[i] = testResultFactory((student->testResults[i].name),(student->testResults[i].mark));
}
//Now we need to add the new student to the end of the array
newTestArray[index] = testResultFactory(testName, testMark);
(student->testResults) = newTestArray;
}
string studentBest(Student const * student)
{
//create variables as temps
string highestName;
double highestMark;
int index = (student->numTestResults);
//Setting the two variables to the first value
highestName = (student->testResults[0].name);
highestMark = (student->testResults[0].mark);
//Using a while loop to compare and get the best
for (size_t i = 0; i < index; i++)
{
if((student->testResults[i].mark)> highestMark)
{
highestMark = (student->testResults[i].mark);
highestName = (student->testResults[i].name);
}
}
//returning the string they want
string send = (highestName)+ " "+ doubleToString(highestMark)+ "%";
return send;
}
double studentAverage(Student const * student)
{
//Variables used as temps
double average = 0;
double counter = 0.0;
double running = 0;
int index = (student->numTestResults);
//Now we need to loop through each one and add to running and counter
for (size_t i = 0; i < index; i++)
{
counter++;
running += (student->testResults[i].mark);
}
//calculating the average;
average = (running)/counter;
return average;
}
void destroyStudent(Student * student)
{
delete [] (student->testResults);
(student->testResults)=0;
}
Subject subjectFactory(std::string name)
{
//Creating an object to use in subject factory
Subject lamp;
lamp.name = name;
lamp.numStudents = 0;
lamp.studentsAllocated = 0;
lamp.students = 0;
return lamp;
}
MY guess is that the error occurs because of an out of bounds array or an pointer not worked with correctly .
int getStudentIndex(Subject const * subject, std::string studentName)
{
int index;
int count = (subject->numStudents);
//loop to find the names and set index
for (size_t i = 0; i < count; i++)
{
if(studentName == ((subject->students[i].name)))
{
index = i;
}
else index = -1;
}
return index;
}
void addStudent(Subject * subject, std::string studentName)
{
//Variables as temps
Student *pointer =0;
int index = getStudentIndex(subject,studentName);
if(index != -1)
{
//Now we need to see if they are large enough
if((subject->studentsAllocated)==0)
{
//Set the allocated to 2
(subject->studentsAllocated) = 2;
pointer = new Student[2];
//Figure this out later
pointer[1] = studentFactrory(studentName);
(subject->students) = pointer;
}
else
{
//increase SA with 1.5
(subject->studentsAllocated) = (subject->studentsAllocated) * 1.5;
pointer = new Student[(subject->studentsAllocated)+1];
int count = (subject->studentsAllocated);
//Now we need to put all the other students in
for (size_t i = 0; i < count-1; i++)
{
pointer[i] = (subject->students[i]);
}
pointer[(subject->studentsAllocated)+1] = studentFactrory(studentName);
(subject->studentsAllocated) += 1 ;
}
//Once done just seet one equal to
(subject->students) = pointer;
}
else return;
}
void removeStudent(Subject * subject, std::string studentName)
{
//First get temps
int index = getStudentIndex(subject ,studentName);
int number = (subject->studentsAllocated);
int i = index;
//delete student
if(index == -1) return;
destroyStudent(&(subject->students)[index]);
//loop to shift the things
while (i<(number -1))
{
(subject->students)[i] = (subject-> students[i+1]);
}
//Removing the last one
(subject->numStudents) -= 1;
}
bool addTestResult(Subject * subject, std::string studentName, std::string testName, double testMark)
{
int index = getStudentIndex(subject ,studentName);
if(index != -1)
{
addTestResult(&(subject->students [index]),testName,testMark);
return true;
}
else
return false;
}
void printSubjectSummary(Subject const * subject)
{
cout<<(subject->name)<< ": with "<<(subject->numStudents)<<" students"<<endl;
//Variables to use in the loop
size_t indexLoop = subject->numStudents;
int i=0;
while (i< indexLoop)
{
cout<<(subject->students[i].name)<<" Average: "<<studentAverage(&(subject->students[i]))<<", Best: "<<studentBest(&(subject->students[i]))<<endl;
}
}
void destroySubject(Subject * subject)
{
//Variables
size_t indexLoop = subject->numStudents;
for (size_t i = 0; i < indexLoop; i++)
{
destroyStudent(&(subject->students[i]));
}
delete [] subject->students;
subject->students =0;
}
I can not seem to find where the segmentation error is coming from. Even restarted the whole assignment from scratch and still seem to get errors.
Can someone please help or indicate where the fault could be coming from.
Over here we have the structs.h file that is included in my code above
#ifndef STRUCTS_H
#define STRUCTS_H
struct TestResult{
double mark;//the test mark as a percentage
std::string name;//the test name
};
struct Student{
std::string name;
TestResult * testResults;//an arry of TestResults
size_t numTestResults;//the number of results for this student (also the size of the array)
};
struct Subject{
std::string name;
Student * students;//an array of Students
size_t numStudents;//the number of students added to the subject
size_t studentsAllocated;//the size of the Student arry(must never be smaller that numStudents)
};
#endif
There are so many logical errors in there that the root cause (or causes; there are quite a few candidates) could be pretty much anywhere.
getStudentIndex returns -1 unless the student is the last one in the array, and an indeterminate value for the first one you add, so adding the first student to a subject is undefined.
addStudent only adds a student if they're already taking the subject.
It also (for some inexplicable reason) allocates an array of two Students, leaving the first element uninitialised.
Using this first element is, of course, undefined.
In the other branch, it first claims that the number of allocated students is * 1.5, but then only allocates + 1.
This will undoubtedly lead to problems.
There is a recursion in addTestResult that will never terminate.
There are most likely other problems as well – this was just a quick glance.
Start with fixing these.
And do learn about constructors and destructors so you can get rid of those "factory" and "destroy" functions.

How to Copy Data from One Array to Another Without Names? (C++)

I'm working on an assignment right now and have run into a roadblock. The assignment is an array list in C++ that dynamically expands by a factor of 2 every time it runs out of room to store new elements (initially starts with room for 2 elements). Here is the code I'm working on (some of it is included in a separate .h file provided by the professor, I won't post everything in order to keep this compact).
#include "array_list.h"
//initial size to create storage array
static const unsigned int INIT_SIZE = 2;
//factor to increase storage by when it gets too small
static const unsigned int GROW_FACTOR = 2;
unsigned int growthTracker = 1;
array_list::array_list()
{
m_storage = new unsigned int[INIT_SIZE];
m_capacity = INIT_SIZE;
m_current = -1;
m_size = 0;
}
array_list::~array_list()
{
delete m_storage;
}
void array_list::clear()
{
delete m_storage;
m_storage = new unsigned int[INIT_SIZE];
m_capacity = INIT_SIZE;
m_current = -1;
m_size = 0;
}
unsigned int array_list::size() const
{
return m_size;
}
bool array_list::empty() const
{
bool A = 0;
if(m_size == 0)
{
A = 1;
}
return A;
}
void array_list::insert(const unsigned int val)
{
m_storage[m_size++] = val;
m_current = m_size;
}
void array_list::grow_and_copy()
{
if(m_size == m_capacity)
{
new unsigned int[INIT_SIZE * (GROW_FACTOR ^ growthTracker)];
growthTracker++;
m_capacity = m_capacity * 2;
}
m_storage[m_size++] = val;
}
Now, my problem is trying to figure out how to copy the values of the old, smaller array into the new, larger one. If I wasn't using dynamic unnamed arrays, this would be very easy to do with a loop, a simple case of "for a certain range, arrayA[i] = arrayB[i]." However, because the arrays are just defined as new unsigned int[], I'm not sure how to go about this. There are no names, so I can't figure out how to tell C++ which array to copy into which. And since the grow_and_copy could be called multiple times, I'm fairly sure I can't give them names, right? Because then I would end up with multiple arrays with the same name. Can anyone point me in the right direction here? Thanks so much.
array_list::growList(int increase = GROW_FACTOR)
{
unsigned int* temp = m_storage;
m_storage = new unsigned int[m_capacity * increase];
for (int i = 0; i < m_capacity; i++)
m_storage[i] = temp[i];
m_capacity *= increase;
delete temp;
}
I don't know if there are other variables you want to change, but this should basically do what you are asking.

How do I pass a pointer to an array of pointers as an argument to a function?

I'm trying to code a robot, and I'm having a confusing situation. I need to pass an array of pointers to objects to a constructor of a class. I can't, however, populate the array before I pass it into the constructor. To solve this I want to pass a pointer to said array, and access its elements from the pointer. The problem is that I'm new to C++, and so I'm not sure of the syntax. Could you guys help me out?
Code for the main file
class RobotDemo : public SimpleRobot
{
Joystick stick;
JoystickOne joyOne;
Victor *victors [8];
public:
RobotDemo(void):
stick(1),
joyOne(&stick)// these must be initialized in the same order
// as they are declared above.
/*It doesnt seem like I can do anything but initialize things here*/
{
/*Populate array with pointers to victors. Will need to update channels*/
for (int x = 1; x <= 7; x++) {
victors[x] = new Victor(x);
}
/*And I don't think I can initialize anything here*/
myRobot.SetExpiration(0.1);
}
/**
* Drive left & right motors for 2 seconds then stop
*/
void Autonomous(void)
{
}
/**
* Runs the motors with arcade steering.
*/
void OperatorControl(void)
{
myRobot.SetSafetyEnabled(true);
while (IsOperatorControl())
{
joyOne.testForActions(); /*Check joystick one for actions*/
Wait(0.005); // wait for a motor update time
}
}
/**
* Runs during test mode
*/
void Test() {
}
};
START_ROBOT_CLASS(RobotDemo);
Here's the code for the JoystickInput class, which the JoystickOne class extends
//the .h
#ifndef JOYSTICKINPUT_H
#define JOYSTICKINPUT_H
#include "WPILib.h"
class JoystickInput {
public:
JoystickInput(Joystick*);
JoystickInput(Joystick*, Victor* [8]);
Joystick * joystick;
bool buttons [10];
Victor** victors [8];
bool buttonClicked(int id);
virtual void testForActions();
};
#endif
//and the .cpp
#include "JoystickInput.h"
JoystickInput::JoystickInput(Joystick * joy) {
joystick = joy;
for (int x = 0; x < 10; x++) {
buttons[x] = false;
}
}
JoystickInput::JoystickInput(Joystick * joy, Victor* vicArray [8]) {
joystick = joy;
for (int x = 0; x < 10; x++) {
buttons[x] = false;
}
for (int n = 0; n <=7; n++) {
*victors[n] = vicArray[n];
}
}
bool JoystickInput::buttonClicked(int id) {
if (buttons[id] == false and joystick->GetRawButton(id) == true) {
buttons[id] = true;
return true;
} else if (buttons[id] == true and joystick->GetRawButton(id) == false) {
buttons[id] = false;
return false;
} else {
return false;
}
}
void JoystickInput::testForActions() {
}
What I'm asking you guys to help me do is rework the constructor of JoystickInput() so that it also takes a pointer to an array of pointers (to Victors), and performs methods on elements of the array. Googling it hasnt turned up anything useful. I'd research it more myself, but its been a few days and I'm still hung up on this.
Thanks for the help (and if not that, then at least reading my post)!
You should be able to use:
JoystickInput(Joystick*, Victor**, int);
and just pass vicArray into the constructor. If victors can be anything else than an array of length 8, then you should also pass the length as an argument because c++ cannot find the length of an array from a pointer.
Whenever types get complicated (functions or arrays), use a typedef:
typedef char char_buffer_type[8]; //char_buffer_type is an array
typedef char (*char_buffer_ptr)[8]; //char_buffer_ptr is a pointer to an array
typedef char (&char_buffer_ref)[8]; //char_buffer_ref is a reference to an array
typedef int main_type(int, char**); //main_type is a "int(int, char**)" function
typedef Victor*(array_of_ptr)[8]; //array_of_ptr is an array of 8 Victor*
Also, you should name the values 8 and 10.
class JoystickInput {
public:
static const int victor_count = 8;
static const int button_count = 10;
typedef Victor*(array_of_victor_ptr)[victor_count];
JoystickInput(Joystick*){}
JoystickInput(Joystick*, array_of_victor_ptr& vicArray);
bool buttonClicked(int id){return true;}
virtual void testForActions(){}
Joystick * joystick;
bool buttons [button_count];
array_of_victor_ptr victors; //that's simpler
};
//then pass this one by reference
JoystickInput::JoystickInput(Joystick * joy, array_of_victor_ptr& vicArray) {
joystick = joy;
for (int x = 0; x < button_count; x++) {
buttons[x] = false;
}
for (int n = 0; n < victor_count; n++) {
victors[n] = vicArray[n]; //don't have to dereference here anymore
}
}
Proof of compilation. Typedefs are wonderful. Use them.

Creating a new object and storing that object in a new class' vector, attributes disappear

Bit of a long title so I am sorry with that. But I do have a bit of a problem with my code at the moment. It should be pretty general and there is quite a bit going on in the code so I won't post it all but I do have this one problem. Here it is:
Sentence newSentence(currentSentence, this, sentenceCount);
this->sentencesNonP.push_back(newSentence);
Now, newSentence has an attribute called words which is of type std::vector<Word *>, Word is also another class within the project.
When I am debugging and checking the attributes of newSentence it shows that words is populated with a length of 4, however when I check sentencesNonP, which is a std::vector<Sentence>, the words vector length is 0. I am checking the first point at sentencesNonP because it is the first the first value being pushed in so it's not that I'm looking at the wrong location of the sentencesNonP vector.
Any reason why my data is being lost in the conversion process?
EDIT: I have implemented both a = operator overload and a copy operator. However, words is still empty in sentencesNonP.
EDIT2:
Sentence.h (excluding include's)
class Word;
class Document;
class Sentence {
public:
//Take out Document * document
Sentence();
Sentence(std::string value, Document * document = NULL, int senNum = 0);
Sentence(const Sentence& newSent);
//Sentence(std::string value);
~Sentence(void);
Sentence & operator=(const Sentence newSent);
Document * getDocument(void);
void setDocument(Document * document);
//__declspec(property(get = getDocument, put = setDocument)) Document * document;
std::string getSentence(void);
void setSentence(std::string word);
//__declspec(property(get = getSentence, put = setSentence)) std::string str;
void setSentenceNumber(unsigned int i);
Word * operator[] (unsigned int i);
unsigned int wordCount(void);
unsigned int charCount(void);
unsigned int sentenceNumber(void);
std::vector<Word *> getWordsVector(void);
private:
std::string sentence;
std::vector<Word *> words;
std::vector<Word> wordNonP;
Document * myd;
unsigned int senNum;
};
Ignore the commented out declspec
EDIT3: Here is my copy constructor:
Sentence::Sentence(const Sentence& newSent) {
this->sentence = newSent.sentence;
this->myd = newSent.myd;
this->senNum = newSent.senNum;
for (int i = 0; i < newSent.wordNonP.size(); i++) {
this->wordNonP.push_back(newSent.wordNonP[i]);
this->words.push_back(newSent.words[i]);
}
}
for (int i = 0; i < newSent.wordNonP.size(); i++) {
this->wordNonP.push_back(newSent.wordNonP[i]);
this->words.push_back(newSent.words[i]);
}
If wordNonP is empty you won't copy any words at all. Write either:
for (int i = 0; i < newSent.wordNonP.size(); i++)
this->wordNonP.push_back(newSent.wordNonP[i]);
for (int i = 0; i < newSent.words.size(); i++)
this->words.push_back(newSent.words[i]);
Or even simpler:
this->wordNonP = newSent.wordNonP;
this->words = newSent.words;