I'm trying to create an array of size 100 filled with 0's. When I go to print out the area what prints is: 0x7fff5fbff54c. It seems to be printing out the address of the area and I am not sure why and how I should fix this so that it prints out what it is supposed to. Below is my code.
List.hpp
typedef int ElementType;
const int MAX = 100;
class List
{
public:
List();
bool Empty();
void InsertAtEnd(ElementType x);
void Delete(ElementType x);
void Display();
int Smallest();
int Largest();
int Range();
private:
int N;
ElementType listArray[MAX];
};
List.cpp
#include "List.hpp"
#include <iostream>
using namespace std;
List::List() {
listArray[99] = {0};
}
void List::Display() {
cout << listArray;
}
main.cpp
#include "List.hpp"
#include <iostream>
using namespace std;
int main() {
List list;
list.Display();
return 0;
}
That is because listArray is a pointer, you are printing the address of the pointer.. If you want to print the content you need to write a loop that will iterate through each element and print the values.
something like:
for (int i=0; i< MAX; ++i)
{
cout << listArray[i] << ", ";
}
cout << endl;
#πάνταῥεῖ is correct. Try this instead:
class List
{
public:
List();
bool Empty();
void InsertAtEnd(ElementType x);
void Delete(ElementType x);
void Display();
int Smallest();
int Largest();
int Range();
private:
int N;
ElementType listArray[MAX] = {0};
};
And remove the initialization from your constructor
Wouldn't you want a loop:
see this previous question:
loop through an array in c++
The code you have
List::List() {
listArray[99] = {0};
}
Just initializes the value of your listArray at index 99.
To initialize your array with all values as 0 you need to use the constructors initializer list:
List::List() : listArray {0} {
}
Related
I am to make a Genetic Array class in C++ and in that class I am to give it a method called shuffle that shuffles(mixes up) the elements in that Array
I am using Repl.it to compile my code and this is the link:
https://repl.it/#jamy155/Exam1
In my code, I have 3 files. My main class, My genetic array class, and one other class.
In my array class, I have this method that is supposed to shuffle the array
//Array.h//
#include <bits/stdc++.h>
using namespace std;
template <typename T>
class Array {
Element<T>*data;
int size;
public:
// sets the size of the array
Array(int size){
this->data = new Element<T>[size];
this-> size = size;
}
int length(){
return this->size;
}
// add Element to the Array
void InsertAt(int i,T value){
data[i].set(value);
}
// prints all element in Array
void print(){
for(int i = 0 ; i<this->size; i++){
cout<<*data[i].get()<<" ";
}
void shuffler(Array arr[]){
int n = this->size;
// To obtain a time-based seed
unsigned seed = 50;
// Shuffling our array
shuffle(arr, arr+n,default_random_engine(seed)); // shuffle method
cout<<"\n";
for(int i=0;i<n;++i)
cout<<arr[i].get(i)<<" ";
}
};
This is my main class.
#include <iostream>
#include "Array.h"
using namespace std;
int main() {
cout << "Hello World!\n";
Array<int> *arr = new Array<int>(7);
arr->InsertAt(0,6);
arr->InsertAt(1,1);
arr->InsertAt(2,10);
arr->InsertAt(3,3);
arr->InsertAt(4,3);
arr->InsertAt(5,5);
arr->InsertAt(6,4);
arr->print();
arr->shuffler(arr); //error
It gives me an error "exited, segmentation fault".What am I doing wrong?
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
In the class constructor, I am initializing other objects and pushing these objects to my class vector member. From what I understand, the vector create a copy of the object and stores it so that it doesn't go out of scope. However, when verifying the objects in another class function, they are not initialized anymore. Here's a example code to explain the behaviour:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
class Square {
private:
int size_ = 0;
int colour_ = 0;
public:
Square(){
size_ = 0;
colour_ = 0;
}
void init(int size, int colour) {
size_ = size;
colour_ = colour;
}
int get_size() { return size_; }
};
class SetSquares {
private:
std::vector<Square> squares_;
int number_;
public:
SetSquares(): number_(0) {}
void init(int num) {
number_ = num;
squares_.clear();
squares_.resize(num);
for (int i=0; i < num; i++) {
Square square;
square.init(i, i);
squares_.push_back(square);
}
}
void sample(int i) {
if (i >= number_) { return; }
std::cout << "Square size is: " << squares_[i].get_size() << std::endl;
}
};
int main()
{
SetSquares set_of_squares;
set_of_squares.init(7);
set_of_squares.sample(4);
return 0;
}
resize(n) will create n default constructed elements in a vector and push_back will append new elements after those n elements. Use reserve and push_back or resize and index operator as suggested in comment.
It seems the attribute test aisbn is successfully storing the data invoking setCode(), setDigit(). But The trouble starts failing while I attempt these values to store into list<test> simul
The list attribute takes the value of digit after setDigit() but the code. How can I put both code and digit into the list attribute? I can't see where the problem is. The code:
#include <iostream>
#include <stdlib.h>
#include <string>
#include <fstream>
#include <list>
using namespace std;
class test
{
private:
string code;
int digit;
public:
//constructor
test(): code(""), digit(0) { }
//copy constructor
test(const test &other):
digit(other.digit)
{
for(unsigned int i=0; i < code.length(); i++)
code[i] = other.code[i];
}
//set up the private values
void setCode(const string &temp, const int num);
void setCode(const string &temp);
void setDigit(const int &num);
//return the value of the pointer character
const string &getCode() const;
const unsigned int getDigit() const;
};
const string& test::getCode() const
{
return code;
}
const unsigned int test::getDigit() const
{
return digit;
}
void test::setCode(const string &temp, const int num)
{
if((int)code.size() <= num)
{
code.resize(num+1);
}
code[num] = temp[num];
}
void test::setCode(const string &temp)
{
code = temp;
}
void test::setDigit(const int &num)
{
digit = num;
}
int main()
{
const string contents = "dfskr-123";
test aisbn;
list<test> simul;
list<test>::iterator testitr;
testitr = simul.begin();
int count = 0;
cout << contents << '\n';
for(int i=0; i < (int)contents.length(); i++)
{
aisbn.setCode(contents);
aisbn.setDigit(count+1);
simul.push_back(aisbn);
count++;
}
cout << contents << '\n';
/*for(; testitr !=simul.end(); simul++)
{
cout << testitr->getCode() << "\n";
}*/
}
It looks like you are having issues with your for loop, you need to modify your for loop like so:
for(testitr = simul.begin(); testitr !=simul.end(); testitr++)
^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^
although, push_back does not invalidate iterators for std::list I think it is more readable to set the iterator where you are using it. Based on your response you also need to modify the copy constructor:
test(const test &other): code(other.code), digit(other.digit) {}
^^^^^^^^^^^^^^^^
how about using the vector
std::vector<test> simul;
for(int i=0; i < (int)contents.length(); i++)
{
aisbn.setCode(contents);
aisbn.setDigit(count+1);
simul.push_back(aisbn);
count++;
}
iterators, pointers and references related to the container are invalidated.
Otherwise, only the last iterator is invalidated.
When I try debugging the code, it runs into the debugging error "c++ Expression: string subscript out of range"
Pretty sure the problem was brought while calling setCode().
How do I fix the code inside setCode()?
#include <iostream>
#include <stdlib.h>
#include <string>
#include <fstream>
#include <list>
using namespace std;
class test
{
private:
string code;
int digit;
public:
//constructor
test(): code(""), digit(0) { }
//copy constructor
test(const test &other):
digit(other.digit)
{
for(unsigned int i=0; i < code.length(); i++)
code[digit] = other.code[digit];
}
//set up the private values
void setCode(const string &temp, const int num);
void setDigit(const int &num);
//return the value of the pointer character
const string &getCode() const;
const unsigned int getDigit() const;
};
const string& test::getCode() const
{
return code;
}
const unsigned int test::getDigit() const
{
return digit;
}
void test::setCode(const string &temp, int num)
{
code[num] = temp[num];
}
void test::setDigit(const int &num)
{
digit = num;
}
int main()
{
string contents = "dfskr-123";
test aisbn;
list<test> simul;
list<test>::iterator testitr;
testitr = simul.begin();
int count = 0;
cout << contents << '\n';
aisbn.setCode(contents, count);
aisbn.setDigit(count);
simul.push_back(aisbn);
count++;
/*for(; testitr !=simul.end(); simul++)
{
cout << testitr->getCode() << "\n";
}*/
}
When you create an instance of the test class, the string inside it is empty. This means that whenever you do e.g. code[something] you will be out of range. It doesn't matter what the index is.
You either need to set the string to a certain length from the start, and make sure that the index is within the range. Or to make sure that the index is within range by dynamically extending the string when needed.
You have to make sure that when this statement executes:
code[num] = temp[num];
both code and temp are at least of size num + 1.