glibc detected error, possible memory leak? - c++

Header File (IntegerSet.h)
#include<iostream>
#include<string>
using namespace std;
class IntegerSet{
public:
unsigned int set[15];
unsigned int empty_set[15];
IntegerSet();
IntegerSet(int[],int);
IntegerSet unionOfsets(IntegerSet);
IntegerSet intersectionOfSets(IntegerSet);
void insertElement(int);
void deleteElement(int);
void printSet();
bool isEqualTo(IntegerSet);
void emptySet();//Set all elements of set to 0
void inputSet();//Reads values from the user into set
bool validEntry(int);//Determines a valid entry to the set
};
Implementation File (IntegerSet.cpp)
//Class implementation file
#include "IntegerSet.h"
using namespace std;
IntegerSet::IntegerSet(){
for(int i=0;i<100;i++){
empty_set[i]=0;
}
}
IntegerSet::IntegerSet(int arr[],int size){
int min;//Use to hold the value for the sorting algorithm
int counter;//Used to count how many values need to be removed from the new array
for(int i=0;i<size-1;i++){//Nested for loop used to sort the array in ascending order
min=arr[i];
if(arr[i]<0||arr[i]>100){//If statement used to count how many numbers are <0 or >100
counter++;
}
for(int k=i+1;k<size;k++){
if(arr[k]<min){
arr[i]=arr[k];
arr[k]=min;
min=arr[i];
}
}
}
int *newSet=new int[size-counter];
for(int j=0;j<size;j++){
if(arr[j]>100||arr[j]<0){
//Do nothing
}else{
newSet[j]=arr[j];
}
}
delete newSet;
}
bool IntegerSet::validEntry(int a){
if(a<0||a>100){
return false;
}
return true;
}
void IntegerSet::inputSet(){
int a;
for(int i=0;i<100;i++){
cout<<"Enter an element(-1 to end)";
cin>>a;
if(a==-1){
cout<<"Entry complete";
return;
}
this->set[i]=a;
}
}
void IntegerSet::emptySet(){
for(unsigned int i=0;i<sizeof(this->set);i++){
this->set[i]=0;
}
}
IntegerSet IntegerSet::unionOfsets(IntegerSet a){
unsigned int *Union=new unsigned int[sizeof(this->set)+sizeof(a.set)];
for(unsigned int i=0;i<sizeof(this->set);i++){
*(Union+i)=this->set[i];
for(unsigned int h=0;h<sizeof(this->set);h++){
*(Union+(h+i))=a.set[h];
}
}
for(unsigned int j=0;j<sizeof(*Union);j++){
for(unsigned int z=j+1;z<sizeof(*Union);z++){
if(*(Union+j)==*(Union+z)){
*(Union+z)=0;
}
}
}
unsigned int newUnion[sizeof(*Union)];
for(unsigned int y=0;y<sizeof(*Union);y++){
if(*(Union+y)!=0&&y<sizeof(newUnion)){
newUnion[y]=*(Union+y);
}
}
IntegerSet c;
for(unsigned int w=0;w<sizeof(*Union);w++){
c.set[w]=newUnion[w];
}
delete Union;
return c;
}
IntegerSet IntegerSet::intersectionOfSets(IntegerSet a){
unsigned int *Intersect=new unsigned int[sizeof(this->set)+sizeof(a.set)];
int counter=0;
for(unsigned int i=0;i<sizeof(this->set);i++){
for(unsigned int j=0;j<sizeof(a.set);j++){
if(this->set[i]==a.set[j]){
*(Intersect+counter)=a.set[j];
counter++;
}
}
}
IntegerSet c;
for(unsigned int w=0;w<sizeof(*Intersect);w++){
c.set[w]=*(Intersect+w);
}
delete Intersect;
return c;
}
void IntegerSet::printSet(){
unsigned int min;
for(unsigned int i=0;i<sizeof(this->set)-1;i++){
min=this->set[i];
for(unsigned int k=i+1;k<sizeof(this->set);k++){
{
if(this->set[k]<min){
this->set[i]=this->set[k];
this->set[k]=min;
min=this->set[i];
}
}
}
cout<<"{";
for(unsigned int h=0;h<3;h++){
if(h==sizeof(this->set)-1){
cout<<this->set[h]<<"}";
}else{
cout<<this->set[h]<<",";
}
}
}
bool IntegerSet::isEqualTo(IntegerSet a){
unsigned int counter=0;
if(sizeof(a.set)==sizeof(this->set)){
for(unsigned int i=0;i<sizeof(this->set);i++){
for(unsigned int f=0;f<sizeof(a.set);f++){
if(this->set[i]==a.set[f]){
counter++;
}
}
}
}else{
return false;
}
if(counter==sizeof(this->set)){
return true;
}
return false;//Used to make sure this method always has something to return
}
void IntegerSet::insertElement(int a){
unsigned A=(unsigned)a;
if(!this->validEntry(a)){
cout<<"Invalid Insertion Attempt!";
}
unsigned int Inserted[sizeof(this->set)+1];
Inserted[sizeof(this->set)]=A;
for(unsigned int w=0;w<sizeof(Inserted);w++){
this->set[w]=Inserted[w];
}
}
void IntegerSet::deleteElement(int a){
unsigned A=(unsigned) a;
unsigned int *Delete=new unsigned int[sizeof(this->set)-1];int test=0;
if(!this->validEntry(a)){
cout<<"No value of: "<<a<<" exists in the set";
}
for(unsigned int z=0;z<sizeof(this->set);z++){
if(this->set[z]==A){
test++;
}
}
if(test==0){
cout<<"No value of: "<<a<<" exists in the set";
}
for(unsigned int i=0;i<sizeof(this->set)-1;i++){
*(Delete+i)=this->set[i];
}
for(unsigned int w=0;w<sizeof(*Delete);w++){
this->set[w]=*(Delete+w);
}
delete Delete;
}
And then there is my tester file, which is what allowed me to find the error
(IntSet.cpp)
//Driver program for class IntegerSet
#include <iostream>
using namespace std;
#include "IntegerSet.h"
int main(){
IntegerSet a,b,c,d;
cout<<"Enter set A:\n";
a.inputSet();
cout<<"\nEnter set B:\n";
b.inputSet();
c=a.unionOfsets(b);
d=a.intersectionOfSets(b);
cout<<"\nUnion of A nd B is:\n";
c.printSet();
cout<<"Intersection of A nd B is:\n";
d.printSet();
//Test if set A is equal to set B
if(a.isEqualTo(b)){
cout<<"Set A is equal to set B\n";
}else{
cout<<"Set A is not equal to set B\n";
}
//test insertion
cout<<"\nInserting 77 into set A...\n";
a.insertElement(77);
cout<<"Set A is now:\n";
a.printSet();
const int arraySize=10;
int intArray[arraySize]={25,67,2,9,99,105,45,-5,100,1};
//Use construct that receive an array of ints
//and the size of that array to create a set object
IntegerSet e(intArray,arraySize);
cout<<"\nSet e is:\n";
e.printSet();
cout<<endl;
}
Personally I feel like what caused this error was some sort of memory leak, although the glib c error isn't exactly telling me where it would be coming from like the compiler does. Also this error occurs right after the function b.inputSet() exits.
What the error says (it alternates between two messages I've noticed):
***glibc detected*** ./a.out: free(): invalid next size (normal):
***glibc detected*** ./a.out: double free or corruption (!prev):

You're doing lots of bad here.
Here's your definition of empty_set.
unsigned int empty_set[15];
And your default constructor accesses outside these bounds.
IntegerSet::IntegerSet(){
for(int i=0;i<100;i++){
empty_set[i]=0;
}
}
Your other constructor doesn't actually change anything inside the class.
Also this code
IntegerSet IntegerSet::unionOfsets(IntegerSet a){
unsigned int *Union=new unsigned int[sizeof(this->set)+sizeof(a.set)];
looks remarkably suspicious as sizeof(set) is not the number of elements in set, but the array length in bytes (15*sizeof(float)) - but if you switch to a variable length array it wont even be that... You'll need to track the set length separately. Or use a std::vector<int>, or better yet - why reinvent the wheel and use std::set<int>?

Related

Returning arrays from functions (C++)

My program is supposed to take the names and 5 marks each for 10 students and output their corresponding average marks and grade. My functions avgmarks and avg_grade are supposed to calculate and return these, as arrays, to the main function. Using the statements return avg[10] and return gr[10] does not work. I know pointer variables can be used here, but i don't know how to implement them to make my program work correctly.
#include <iostream>
#include <string>
using namespace std;
void readnames(string p[]);
int readmarks(int p[10][5]);
int avgmarks(int p[10][5]);
char avg_grade(int p[10]);
void displayresults(string n[], int m[], char g[]);
int main()
{
string names[10];
readnames(names);
int marks [10][5];
readmarks(marks);
int avg_marks[10];
avg_marks[10]=avgmarks(marks);
char grade[10];
grade[10]=avg_grade(avg_marks);
displayresults(names, avg_marks, grade);
}
void readnames(string p[])
{
for (int i=0;i<10;i++)
{
cout<<"Enter student "<<i+1<<"'s name:\n";
cin>>p[i];
}
}
int readmarks(int p[10][5])
{
for (int i=0;i<10;i++)
{
cout<<"Enter student "<<i+1<<"'s marks:\n";
for (int j=0;j<5;j++)
{
cin>>p[i][j];
}
}
}
int avgmarks(int p[10][5])
{
int avg[10];
int sum;
for (int i=0;i<10;i++)
{
sum=0;
for (int j=0;j<5;j++)
{
sum=sum+p[i][j];
}
avg[i]=(sum/5);
}
return avg[10];
}
char avg_grade(int p[10])
{
char gr[10];
for (int i=0;i<10;i++)
{
if (p[i]>=90)
{
gr[i]='A';
}
if ((p[i]>=80)&&(p[i]<90))
{
gr[i]='B';
}
if ((p[i]>=70)&&(p[i]<80))
{
gr[i]='C';
}
if ((p[i]>=60)&&(p[i]<70))
{
gr[i]='D';
}
if ((p[i]>=50)&&(p[i]<60))
{
gr[i]='E';
}
if ((p[i]>=40)&&(p[i]<50))
{
gr[i]='F';
}
}
return gr[10];
}
void displayresults(string n[], int m[], char g[])
{
float ct;
float sum=0;
cout<<endl;
for (int i=0;i<10;i++)
{
cout<<"Name: "<<n[i]<<" Average Marks: "<<m[i]<<" Grade: "<<g[i];
cout<<endl;
}
for (int i=0;i<10;i++)
{
sum=sum+m[i];
}
ct=sum/10;
cout<<"The class average is "<<ct<<endl;
}
Arrays cannot be returned from functions. It's one good reason to use vectors instead of arrays (there are many more).
But if you want to carry on with arrays you should use pointers to simulate returning an array from your function.
In this example avg is a pointer to an array that will recieve the returned value
void avgmarks(int p[10][5], int* avg)
{
int sum;
for (int i=0;i<10;i++)
{
sum=0;
for (int j=0;j<5;j++)
{
sum=sum+p[i][j];
}
avg[i]=(sum/5);
}
}
You use it like this
int avg_marks[10];
avgmarks(marks, avg_marks);
PS. You seem to have the common (but to me bizarre) newbie misunderstanding that if you have an array of size 10 (say) then array[10] can be used to refer to the whole array. Please don't think that, if you have an array of size 10, then array[10] is just an error, because the valid indexes for an array of size 10 are 0 to 9.
This example changed every c-style array to std::array. Keep in mind, that it is the same code as yours with the arrays, so every programming error is still in there. And also arrays are returned by value, means that they are copied. Try to understand how to use std::array and you will get a better programmer.
#include <iostream>
#include <string>
#include <array>
using namespace std;
void readnames(std::array<string, 10>& p);
void readmarks(std::array<std::array<int,5>, 10>& p);
std::array<int,10> avgmarks(std::array<std::array<int,5>, 10>& p);
std::array<char,10> avg_grade(std::array<int,10>& p);
void displayresults(std::array<string, 10> n, std::array<int,10> m, std::array<char,10> g);
int main()
{
std::array<string, 10> names;
readnames(names);
std::array<std::array<int,5>, 10> marks;
readmarks(marks);
std::array<int,10> avg_marks;
avg_marks = avgmarks(marks);
std::array<char,10> grade;
grade = avg_grade(avg_marks);
displayresults(names, avg_marks, grade);
}
void readnames(std::array<string, 10>& p)
{
for (int i=0;i<10;i++)
{
cout<<"Enter student "<<i+1<<"'s name:\n";
cin>>p[i];
}
}
void readmarks(std::array<std::array<int,5>, 10>& p)
{
for (int i=0;i<10;i++)
{
cout<<"Enter student "<<i+1<<"'s marks:\n";
for (int j=0;j<5;j++)
{
cin>>p[i][j];
}
}
}
std::array<int,10> avgmarks(std::array<std::array<int,5>, 10>& p)
{
std::array<int,10> avg;
int sum;
for (int i=0;i<10;i++)
{
sum=0;
for (int j=0;j<5;j++)
{
sum=sum+p[i][j];
}
avg[i]=(sum/5);
}
return avg;
}
std::array<char,10> avg_grade(std::array<int,10>& p)
{
std::array<char,10> gr;
for (int i=0;i<10;i++)
{
if (p[i]>=90)
{
gr[i]='A';
}
if ((p[i]>=80)&&(p[i]<90))
{
gr[i]='B';
}
if ((p[i]>=70)&&(p[i]<80))
{
gr[i]='C';
}
if ((p[i]>=60)&&(p[i]<70))
{
gr[i]='D';
}
if ((p[i]>=50)&&(p[i]<60))
{
gr[i]='E';
}
if ((p[i]>=40)&&(p[i]<50))
{
gr[i]='F';
}
}
return gr;
}
void displayresults(std::array<string, 10> n, std::array<int,10> m, std::array<char,10> g)
{
float ct;
float sum=0;
cout<<endl;
for (int i=0;i<10;i++)
{
cout<<"Name: "<<n[i]<<" Average Marks: "<<m[i]<<" Grade: "<<g[i];
cout<<endl;
}
for (int i=0;i<10;i++)
{
sum=sum+m[i];
}
ct=sum/10;
cout<<"The class average is "<<ct<<endl;
}
I think this will work:
#include <iostream>
#include <string>
using namespace std;
void readnames(string p[]);
void readmarks(int p[10][5]);
int* avgmarks(int p[10][5]);
char* avg_grade(int p[10]);
void displayresults(string n[], int m[], char g[]);
int main()
{
string names[10];
readnames(names);
int marks [10][5];
readmarks(marks);
int *avg_marks;
avg_marks=avgmarks(marks);
char *grade;
grade=avg_grade(avg_marks);
displayresults(names, avg_marks, grade);
}
void readnames(string p[])
{
for (int i=0;i<10;i++)
{
cout<<"Enter student "<<i+1<<"'s name:\n";
cin>>p[i];
}
}
void readmarks(int p[10][5])
{
for (int i=0;i<10;i++)
{
cout<<"Enter student "<<i+1<<"'s marks:\n";
for (int j=0;j<5;j++)
{
cin>>p[i][j];
}
}
}
int* avgmarks(int p[10][5])
{
static int avg[10];
int sum;
for (int i=0;i<10;i++)
{
sum=0;
for (int j=0;j<5;j++)
{
sum=sum+p[i][j];
}
avg[i]=(sum/5);
}
return avg;
}
char* avg_grade(int *p)
{
static char gr[10];
for (int i=0;i<10;i++)
{
if (p[i]>=90)
{
gr[i]='A';
}
if ((p[i]>=80)&&(p[i]<90))
{
gr[i]='B';
}
if ((p[i]>=70)&&(p[i]<80))
{
gr[i]='C';
}
if ((p[i]>=60)&&(p[i]<70))
{
gr[i]='D';
}
if ((p[i]>=50)&&(p[i]<60))
{
gr[i]='E';
}
if ((p[i]>=40)&&(p[i]<50))
{
gr[i]='F';
}
}
return gr;
}
void displayresults(string n[], int m[], char g[])
{
float ct;
float sum=0;
cout<<endl;
for (int i=0;i<10;i++)
{
cout<<"Name: "<<n[i]<<" Average Marks: "<<m[i]<<" Grade: "<<g[i];
cout<<endl;
}
for (int i=0;i<10;i++)
{
sum=sum+m[i];
}
ct=sum/10;
cout<<"The class average is "<<ct<<endl;
}
Basically, to return an array from a function in C/C++, you declare it as "static", and you make the function return the pointer.
EDIT: As many others have noted, this won't work in multi-threaded programs.

Segmentation fault: 11 in C++ IntVector

I'm attempting to implement an intvector in C++ and am getting a "Segmentation fault: 11" error. I understand this has something to do with memory management, and considering how new I am to C++ it could definitely be a pretty minor mistake. I debugged the code with valgrind and was given messages such as the following:
Use of uninitialized value of size 8, Invalid read of size 4,Conditional jump or move depends on uninitialized value(s).
My best guess is it has something to do with how I'm implementing the arrays. I originally had the arrays stored on the heap but changed it to the stack and still got the same error. I've already implemented an intvector in java, so I was attempting to use similar logic here, which perhaps is part of the issue.
#include <iostream>
#include "IntVector.h"
#include <cmath>
using namespace std;
int num_elements = 0;
int array_size = 0;
int expansion_factor;
void IntVector::expandArray(){
int tempArr[array_size*2];
for(int i =0;i<array_size;i++){
tempArr[i] = array[i];
}
array = tempArr;
array_size = array_size * 2;
}
void IntVector::add(int val){
int tempArr[array_size];
if(array_size == num_elements){
expandArray();
array[num_elements] = val;
}
else{
for(int i = 0;i<array_size;i++){
tempArr[i] = array[i];
}
tempArr[num_elements] = val;
array = tempArr;
}
num_elements++;
}
void IntVector::remove(int index){
}
int IntVector::get(int index) const{
return index;
}
void IntVector::removeLast(){
}
void IntVector::set(int index, int val){
}
std::string IntVector::toString()const {
return "";
}
IntVector::IntVector(int initial_size){
int* array = new int[initial_size];
}
IntVector:: ~IntVector(){
delete[] array;
}
int main(){
IntVector v(0);
v.add(5);
}
#ifndef INTVECTOR_H_
#define INTVECTOR_H_
using std::cout;
class IntVector {
private:
int* array;
int num_elements;
int array_size;
int expansion_factor;
void expandArray();
public:
void add(int val);
void remove(int index);
int get(int index) const;
void removeLast();
void set(int index, int val);
std::string toString() const;
IntVector(int initial_size);
~IntVector();
};
#endif
As mention in the comments, there are definitely some holes in your understanding of C++. Really when dealing with header files you should have a main.cpp, someotherfile.h, someotherfile.cpp. That just best practices to avoid redefinition errors.
There was quite a bit wrong with the way you accessed the private variable. If a class has a private( or even public) variable you don't have to redeclare it each time you want to change its value.
There were one or two major flaws with the way you expanded the vector. If the vector size is initialized to 0 then 0*2 is still 0 so you never actually increased the size. Secondly, when you set the original array = to the new array the new array was just a local array. This means that the memory wasn't actually allocated permanently, once the function ended the temparr was destroyed.
I know this was probably a lot but if you have any question feel free to ask.
main.cpp
#include "IntVector.h"
int main()
{
IntVector v;
IntVector x(10);
v.push(5);
v.push(5);
v.push(5);
v.push(5);
v.push(5);
v.print();
cout << endl;
x.push(5);
x.push(5);
x.push(5);
x.push(5);
x.push(5);
x.print();
return 0;
}
IntVector.h
#include <string>
#include <iostream>
using namespace std;
class IntVector {
private:
int *array;
int num_elements;
int array_size;
//int expansion_factor =; you would only need this if you plan on more than double the vector size
void expandArray(); //normally c++ array double in size each time they expand
public:
//Constructors
IntVector(); //this is a contructor for if nothing is called
IntVector(int initial_size);
//setters
void push(int val); //add
void pop(); //removelast
void remove(int index); //remove
void at(int index, int val); //set
//Getters
int at(int index);
//std::string toString(); I'm changing this to print
void print(); //will print the contents to the terminal
//Deconstructor
~IntVector();
};
IntVector.cpp
#include "IntVector.h"
//constructors
IntVector::IntVector() //no arguments given
{
array = new int[0];
num_elements = 0;
array_size = 0;
}
IntVector::IntVector(int initial_size)
{
array = new int[initial_size];
num_elements = 0;
array_size = initial_size;
}
void IntVector::expandArray()
{
int *tempArr;
if(array_size == 0){
array_size = 1;
tempArr = new int[1];
} else {
//make sure to allocate new memory
//you were creating a local array which was destroy after the function was completed
//using new will allow the array to exist outside the function
tempArr = new int[array_size * 2];
}
for (int i = 0; i < array_size; i++)
{
tempArr[i] = array[i];
}
//make sure to delete the old array otherwise there is a memory leak.
//c++ doesn't have a garbage collector
delete[] array;
array = tempArr;
array_size = array_size * 2;
}
void IntVector::push(int val)
{
num_elements++;
//checking if vector needs to increase
if (array_size <= num_elements)
{
expandArray();
array[num_elements-1] = val;
}
else
{
array[num_elements-1] = val;
}
}
void IntVector::remove(int index)
{
//not sure how to implment this becuase each element has to be a number.
}
int IntVector::at(int index)
{
return array[index];
}
void IntVector::pop()
{
num_elements = num_elements-1; //not really removing it from the "vector" but it won't print out again
}
void IntVector::at(int index, int val)
{
array[index] = val;
}
void IntVector::print()
{
for (int i = 0 ; i < num_elements; i++)
{
cout << array[i] << " ";
}
cout << endl;
}
IntVector::~IntVector()
{
delete[] array;
}
output
5 5 5 5 5
5 5 5 5 5
Hopefully, the comments help. I changed the name of the functions to better match the actual vecter class the already exists in C++. I think it's good to pick apart already defined functions like this because you get a better understanding of how they actually work and not just how to use them.
If you got any questions just leave a comment

Array of Structures:No matching function to call to and taking user input

I have written a code for Knapsack problem.The code is working perfectly when i hardcode the inputs but now i want to take the inputs from the user in the array of structures but it is showing error.How can i achieve this?
original code:
#include<iostream>
#include<algorithm>
using namespace std;
struct Item{
int value;
int weight;
Item(int value,int weight):value(value),weight(weight){
}
};
bool cmp(struct Item a,struct Item b){
float r1=(float)a.value/a.weight;
float r2=(float)b.value/b.weight;
//cout<<r1<<" "<<r2<<endl;
return r1>r2;
}
void knapsack(int m,int n,struct Item arr[]){
sort(arr,arr+n,cmp);
/* for(int i=0;i<n;i++){ //new sorted array
cout<<arr[i].value<<" "<<arr[i].weight<<" ";
}*/
cout<<endl;
float result[n];
for(int i=0;i<n;i++){
result[i]=0.0;
}
int rem=m;
int j=0;
for(j=0;j<n;j++){
if(arr[j].weight>rem){
break;
}
else{
result[j]=1;
rem=rem-arr[j].weight;
}
}
if(j<n){
result[j]=(float)rem/arr[j].weight;
}
for(int k=0;k<n;k++){
cout<<result[k]<<" ";
}
}
int main(){
struct Item arr[]={{25,18},{24,15},{15,10}};
knapsack(20,3,arr);
return 0;
}
Now i want to take user input in the array of structures but it shows an error "no matching function to call to"
#include<iostream>
#include<algorithm>
using namespace std;
struct Item{
int value;
int weight;
Item(int value,int weight):value(value),weight(weight){
}
};
bool cmp(struct Item a,struct Item b){
float r1=(float)a.value/a.weight;
float r2=(float)b.value/b.weight;
//cout<<r1<<" "<<r2<<endl;
return r1>r2;
}
void knapsack(int m,int n,struct Item arr[]){
sort(arr,arr+n,cmp);
/* for(int i=0;i<n;i++){ //new sorted array
cout<<arr[i].value<<" "<<arr[i].weight<<" ";
}*/
cout<<endl;
float result[n];
for(int i=0;i<n;i++){
result[i]=0.0;
}
int rem=m;
int j=0;
for(j=0;j<n;j++){
if(arr[j].weight>rem){
break;
}
else{
result[j]=1;
rem=rem-arr[j].weight;
}
}
if(j<n){
result[j]=(float)rem/arr[j].weight;
}
for(int k=0;k<n;k++){
cout<<result[k]<<" ";
}
}
int main(){
struct Item arr[10];
int n,m;
cin>>m>>n;
for(int i=0;i<n;i++){
cin>>arr[i].value>>arr[i].weight;
}
knapsack(m,n,arr);
return 0;
}
Check below code:
struct Item{
int value;
int weight;
Item(int value,int weight):value(value),weight(weight){
}
};
There is no default constructor. So the below line fails:
struct Item arr[10];
But the following line works:
struct Item arr[]={{25,18},{24,15},{15,10}};
Solution[1]: Provide a default constructor or remove the explicit constructor.
[1] There may be more problems in the code, but I looked into the one you pointed in your question.
You have provided parameterized constructor Item(int value,int weight), so compiler won't generate default constructor by itself.
You have to define the default constructor explicitly to make the below statement work since it needs default constructor.
struct Item arr[10];
But the below line of code uses the parameterized constructor you have provided.
struct Item arr[]={{25,18},{24,15},{15,10}};

How is memory allocated to instances of class with array member?

In my understanding, under usual conditions, array is being allocated memory at compile time, but what happens when array is a member variable, and there is pretty much nothing to allocate memory to during compilation. Does it get implicitly dynamically-allocated, when instance of that class is created?
class Arr{
public:
int arr[10];
};
Arr doSomething(Arr &arg){
return arg; //copy of arg created; 'copy=new int[10]' at this point?
}
int main(){
Arr temp;
doSomething(temp);
//if returned object's array was dynamically initialized
//will it result the array in temp being released twice?
}
UPD. In my case, situation rises when I try to subract A-B where B>A. In these cases I can access array to read from it, but modifying its values leads to garbage. Moreover, final output in main is fine. Here's full code:
#include <iostream>
using namespace std;
const int MAX_ARRAY_SIZE=256;
char* getOperatorIndex(char* equationString);
bool isOperator(char characterDec);
int* toIntArray(char* firstInA, char* lastInA, int* firstInB);
class Number{
int* firstInNumber;
int* lastInNumber;
int number[MAX_ARRAY_SIZE];
public:
Number();
~Number();
bool operator<(Number& b);
int& operator[](int index);
Number operator-(Number& b);
void print();
int length(){return lastInNumber-firstInNumber;}
int*& lastPtr(){return lastInNumber;}
int*& firstPtr(){return firstInNumber;}
};
Number::Number(){
firstInNumber=number;
lastInNumber=number;
}
Number::~Number(){
cout<<"number destroyed"<<endl;
}
int& Number::operator[](int index){
return number[index];
}
bool Number::operator<(Number& b){
if(length()>b.length())return false;
if(length()<b.length())return true;
for(int a=0;a<length();++a){
if(number[a]>b[a])return false;
if(number[a]<b[a])return true;
}
return false;
}
void Number::print(){
for(int a=0; a<=length(); ++a){
cout<<number[a];
}
cout<<endl;
}
Number Number::operator-(Number& b){
Number result;
if(*this < b)
{
result=b-*this;
cout<<*result.lastPtr()<<endl;
result.print();
*result.lastPtr()*=-1; // GARBAGE HERE
cout<<*result.lastPtr()<<endl;
return result;
}
result[0]=0;
for(int q=0; q<=length(); ++q)
{
if(b.length()-q >= 0)
{
result[q]+=(*this)[length()-q]-b[b.length()-q];
if(result[q] < 0)
{
result[q]+=10;
result[q+1]=-1;
}
else
{
result[q+1]=0;
}
}
else
{
result[q]+=(*this)[length()-q];
}
++result.lastPtr();
}
do{
--result.lastPtr();
}while(!*result.lastPtr());
return result;
}
int main(){
char equationArray[MAX_ARRAY_SIZE*2+1]; // operandA(<=256) operator(1) operandB(<=256)
Number a,b;
cin>>equationArray;
char* operatorPtr=getOperatorIndex(equationArray);
a.lastPtr()=toIntArray(equationArray, operatorPtr, a.firstPtr());
b.lastPtr()=toIntArray(operatorPtr+1, operatorPtr+strlen(operatorPtr), b.firstPtr());
a.print();
b.print();
Number c;
switch(*operatorPtr){
case '-':
c=a-b;
break;
}
c.print();
}
char* getOperatorIndex(char* equationString){
while(!isOperator(*++equationString));
return equationString;
}
bool isOperator(char characterDec){
if(characterDec>='*' & characterDec<='/')return true;
return false;
}
int* toIntArray(char* firstInA, char* lastInA, int* firstInB){
while(lastInA-firstInA>0){
*firstInB=*firstInA-'0';
++firstInB;
++firstInA;
}
return --firstInB;
}
All data members of a class have the same storage-duration as the class' object created. Hence in:
int main(){
Arr temp;
doSomething(temp);
}
The data member temp.arr which is of type int[10]; also has automatic storage-duration.. (or what is inappropriately known as "stack object")
Arr doSomething(Arr &arg){
return arg; //copy of arg created; 'copy=new int[10]' at this point?
}
No, there is no heap allocation here. rather a member-wise copy by the implicit copy constructor. See How are C++ array members handled in copy control functions?

in c++ expected primary expression before ']'

Here is my code for quick sort. I am a beginner kindly please help.
#include<iostream>
using namespace std;
class quick
{
private:
int n,left,right,i,j;
float a[55];
public:
void getdata();
void sort(float[],int,int);
void putdata();
};
void quick::getdata()
{
cout<<"Enter how many elements you want to enter:";
cin>>n;
for(int k=0;k<n;k++)
{
cout<<"Enter percentage of students:"<<k+1<<":";
cin>>a[k];
}
left=0;
right=n-1;
}
void quick::putdata()
{
for(int k=0;k<5;k++)
{
cout<<"\nSorted marks are:"<<a[k]<<endl;
}
}
void quick::sort(float a[],int left,int right)
{
if(left<right)
{
int i=left;
int j=right+1;
float pivot=a[left];
do{
do{
i++;
}while((a[i]<pivot)&& left<right);
do{
j--;
}while(a[j]>pivot);
if(i<j)
swap(a[i],a[j]);
}while(i<j);
a[left]=a[j];
a[j]=pivot;
sort(a,left,j-1);
sort(a,j+1,right);
}
}
int main()
{
quick obj;
obj.getdata();
obj.sort(a[],left,right);
obj.putdata();
return (0);
}
It is giving me error in int main() function:
a is not declared in this scope.
expected primary expression before ']'.
As the answer is given by #Shubham Khatri. Here is the corrected code.
#include<iostream>
using namespace std;
class quick
{
public: int n,left,right,i,j;
float a[55];
public:
void getdata();
void sort(float[],int,int);
void putdata();
};
void quick::getdata()
{
cout<<"Enter how many elements you want to enter:";
cin>>n;
for(int k=0;k<n;k++)
{
cout<<"Enter percentage of students:"<<k+1<<":";
cin>>a[k];
}
left=0;
right=n-1;
}
void quick::putdata()
{
for(int k=0;k<n;k++)
{
cout<<"\nSorted marks are:"<<a[k]<<endl;
}
}
void quick::sort(float a[],int left,int right)
{
if(left<right)
{
int i=left;
int j=right+1;
float pivot=a[left];
do{
do{
i++;
}while((a[i]<pivot)&& left<right);
do{
j--;
}while(a[j]>pivot);
if(i<j)
swap(a[i],a[j]);
}
while(i<j);
a[left]=a[j];
a[j]=pivot;
sort(a,left,j-1);
sort(a,j+1,right);
}
}
int main()
{
quick obj;
obj.getdata();
obj.sort(obj.a,obj.left,obj.right);
obj.putdata();
return (0);
}
As it mentions you have not declared a as a variable inside the int main(). Rather it is an object of quick. In a function you don't pass array like a[] rather as a only .since a, left, right are a private variable of a class you can't access it from the object directly. Declare it as public and use it as obj.a, obj.left, obj.right inside sort function.
Complete code:
#include<iostream>
using namespace std;
class quick
{
public:
int n,left,right,i,j;
float a[55];
void getdata();
void sort(float[],int,int);
void putdata();
};
void quick::getdata()
{
cout<<"Enter how many elements you want to enter:";
cin>>n;
for(int k=0;k<n;k++)
{
cout<<"Enter percentage of students:"<<k+1<<":";
cin>>a[k];
}
left=0;
right=n-1;
}
void quick::putdata()
{
for(int k=0;k<5;k++)
{
cout<<"\nSorted marks are:"<<a[k]<<endl;
}
}
void quick::sort(float a[],int left,int right)
{
if(left<right)
{
int i=left;
int j=right+1;
float pivot=a[left];
do{
do{
i++;
}while((a[i]<pivot)&& left<right);
do{
j--;
}while(a[j]>pivot);
if(i<j)
swap(a[i],a[j]);
}while(i<j);
a[left]=a[j];
a[j]=pivot;
sort(a,left,j-1);
sort(a,j+1,right);
}
}
int main()
{
quick obj;
obj.getdata();
obj.sort(obj.a,obj.left,obj.right);
obj.putdata();
return (0);
}