C++ Vectors in a Class - c++

i am working on a worksheet i have for university and the question asks me to "Allow a user to enter 10 numbers from the keyboard into an array" however we have been told that we need to use classes and vectors for this task. When i run my code i get an error stating: "Expression: Vector subscript out of range"
can anyone help?
Array.h
#include <iostream>
#include <vector>
using namespace std;
class Array
{
private:
vector<int> lists;
public:
void fillArray();
void printForwards();
void halfandHalf();
void shiftArrayRight();
Array();
Array(vector<int>);
};
Array.cpp
#include "Array.h"
Array::Array()
{
lists[10];
}
Array::Array(vector<int> lists)
{
this->lists = lists;
}
void Array::fillArray()
{
for (int i = 0; i < 10; i++)
{
cin >> lists[i];
}
}
void Array::printForwards()
{
for (int i = 0; i < 10; i++)
{
cout << lists[i];
}
}
Source.cpp
#include <iostream>
#include "Array.h"
using namespace std;
int main()
{
Array list1,list2;
//fill array 1
list1.fillArray();
//fill array 2
list2.fillArray();
// print array 1
list1.printForwards();
//print array 2
list2.printForwards();
system("pause");
return 0;
}
Thanks in advance

lists[10]; is not going to create a vector of size 10. It is going to try and access the 11th element of an empty vector. If you wanted to create a vector of size 10 then you can use
Array::Array() : lists(std::vector<int>(10, 0)) {}
I would also suggest you change
Array::Array(vector<int> lists)
{
this->lists = lists;
}
To
Array::Array(vector<int> lists) lists(lists) {}
You should also change your for loops to use the vector size() instead of a hard coded value
void Array::fillArray()
{
for (int i = 0; i < lists.size(); i++) // uses size()
{
cin >> lists[i];
}
}
void Array::printForwards()
{
for (int i = 0; i < lists.size(); i++) // uses size()
{
cout << lists[i];
}
}
Or if you have C++11 or higher you can use a ranged based for loop like
void Array::fillArray()
{
for (auto& e : lists)
{
cin >> e;
}
}
void Array::printForwards()
{
for (const auto& e : lists)
{
cout << e;
}
}

Related

"malloc(): corrupted top size" when constructing vector

I'm trying to create this function:
std::vector<int> graph::getNeighbors(int n){
int i = 0; for(int el : verteces[n]) i++;
if( i != 0){
auto iter = verteces[n].begin();
std::vector<int> res = std::vector<int>{i};
for(int j=0; j<i; j++)
res[j] = *(iter++);
return res;
}
return std::vector<int>{};
}
As the name itself explain, it is supposed to get the neighbors of a vertex. The graph is made like this:
class graph {
private:
std::vector<std::forward_list<int>> verteces;
unsigned long int n;
···
};
Now, the problem is that whenever i is greater than 0, the program crashes badly with the error:
malloc(): corrupted top size
I don't understand what I am doing wrong.
EDIT
In order to make a reproducible example I am going to show all the three files.
main.cpp:
#include <iostream>
#include <set>
#include "graph/graph.h"
void greedyAlgorithm(graph &G){
std::vector<int> colors{static_cast<int>(G.getSize())};
for(int i=0; i<G.getSize(); i++)
colors[i] = -1;
for(int i=0; i<G.getSize(); i++){ // for each vertex
std::set<int> colorNeigh{};
for(auto &j : G.getNeighbors(i)){
if(colors[j] != -1)
colorNeigh.insert( colors[j] );
}
int col = 0;
for(auto &el : colorNeigh){
if(el == col) col++;
else break;
}
colors[i] = col;
}
}
int main() {
{
std::vector<int> r;
for(int i=0; i<100; i++)
r.push_back(i);
}
graph a = graph(10);
a.addEdge(2, 5);
a.addEdge(2, 5);
a.addEdge(1,2);
a.addEdge(2,3);
a.addEdge(3,4);
greedyAlgorithm(a);
return 0;
}
graph.h:
//
// Created by salvo on 11/08/21.
//
#ifndef P2_GRAPH_H
#define P2_GRAPH_H
#include <forward_list>
#include <vector>
#include <stdexcept>
class node;
// list implementation
class graph {
private:
std::vector<std::forward_list<int>> verteces;
unsigned long int n;
public:
graph();
graph(unsigned long int n); // vertex number
void addEdge(int a, int b);
std::vector<int> getNeighbors(int n);
unsigned long getSize(){return n;};
};
#endif //P2_GRAPH_H
graph.cpp:
//
// Created by salvo on 11/08/21.
//
#include <iostream>
#include <openssl/ossl_typ.h>
#include "graph.h"
graph::graph() {
// verteces call default constructor
n = 0;
}
graph::graph(unsigned long int n) {
verteces = std::vector<std::forward_list<int>>{n};
for(auto &el : verteces) el = std::forward_list<int>{};
this->n = n;
}
void graph::addEdge(int a, int b) {
if(a == b){
std::cout << " No self loop!\nexiting ";
exit(-2);
}
int m = a > b ? a : b + 1;
if(m > n){
std::cout << "The graph only contains " << n << " verteces.\n exiting.";
exit(-1);
}
// Check if the edge exist already
for(auto &el : verteces[a]){
if(el == b) return;
}
verteces[a].emplace_front(b);
verteces[b].emplace_front(a);
std::cout << verteces.size() << std::endl;
}
std::vector<int> graph::getNeighbors(int n){
std::vector<int> res{};
for(auto el : verteces[n])
res.push_back(el);
return res;
}
Output if executed:
malloc(): corrupted top size
Process finished with exit code 134 (interrupted by signal 6: SIGABRT)
I am using C++14.
Without even looking at the code, I added -D_GLIBCXX_DEBUG1 to compiler flags (to enable container bounds checks) and got this:
Error: attempt to subscript container with out-of-bounds index 1, but
container only holds 1 elements.
Then I used GDB to understand where exactly that happens:
void greedyAlgorithm(graph &G){
std::vector<int> colors{static_cast<int>(G.getSize())};
for(int i=0; i<G.getSize(); i++)
colors[i] = -1; <-- HERE
This means that the syntax you used created a vector with a single element (with value G.getSize()).
This is why you should never EVER use direct-list-initialization (i.e. with curly braces, without =) with containers. If the vector had some other element type (not a number), this would've worked, and this is exactly why you shouldn't do it.
The fix is to use parentheses:
std::vector<int> colors(static_cast<int>(G.getSize()));
1 This is libstdc++-specific flag (it only works with the GCC's standard library). Other standard library implementations have similar checks. There are also address sanitizers that could also work here.
std::vector<int> colors{static_cast<int>(G.getSize())}
Constructs a vector with one element equal to static_cast<int>(G.getSize()). You want std::vector colors(here_the_size) not with { }. std::vector colors(G.getSize()); will construct a vector with G.getSize() elements.
Because subsequent colors[i] = -1; overwrites memory without any checks, you get errors.
Use .at() instead of []. Using colors.at(i) = -1; will allow you to detect errors early on.

Cout from class method does nothing

I have a class "beaker" that represents a beaker with n-dices that have n-faces. It has a method "roll" which returns a vector with n-elements where each element represents a dice. Then I have another class "board" that for now, it only prints the values generated by beaker.roll using cout;
So I call the beaker.roll function to pass the result to print them, but it does nothing. I have no compile errors/IntelliSense warnings. What am I doing wrong?
#include <iostream>
#include <random>
#include <chrono>
#include <thread>
#include <vector>
using std::cout;
using std::vector;
class beaker {
public:
int diceCount, diceFaces;
beaker() {
diceCount = 2;
diceFaces = 6;
};
beaker(int count, int faces) {
diceCount = count;
diceFaces = faces;
};
//Dice values
vector<uint8_t> dice;
//METHODS
//RETURN DICE i VALUE
int diceValue(int d) {
return dice.at(d-1);
}
//ROLL DICE + RETURN RESULT
vector<uint8_t> roll() {
std::mt19937 mt(std::chrono::high_resolution_clock::now().time_since_epoch().count());
std::uniform_int_distribution<int> dist(1, diceFaces);
for (int i=0; i<diceCount; i++) {
dice.push_back(dist(mt));
}
return dice;
}
//RETURN LAST DICE NUMBERS
vector<uint8_t> result() {
return dice;
}
};
class board {
public:
void Print(vector<uint8_t> dice) {
for (int i=0; i<dice.size(); i++) {
cout << dice.at(i);
}
}
};
int main() {
beaker beaker;
board board;
board.Print(beaker.roll());
}
The problem is that the values in dice are of type uint8_t, which the cout::<< operator is interpreting as unsigned char, so it is printing out the values as ASCII characters. However, the values are between 1 and 6, and ASCII characters less than 32 are mostly non-printing characters, so they aren't visible in the output.
To convince the cout::<< operator to print the values as integers instead, update the code to this:
void Print(vector<uint8_t> dice) {
for (int i=0; i<dice.size(); i++) {
cout << static_cast<int>(dice.at(i));
}
cout << std::endl; // just to make sure the buffer gets flushed ASAP
}

How to pass parameters in an objects of array? in c++

class A
{
int id;
public:
A (int i) { id = i; }
void show() { cout << id << endl; }
};
int main()
{
A a[2];
a[0].show();
a[1].show();
return 0;
}
I get an error since there is no default constructor.However thats not my question.Is there a way that ı can send parameters when defining
A a[2];
A good practice is to declare your constructor explicit (unless it defines a conversion), especially if you have only one parameter. Than, you can create new objects and add them to your array, like this :
#include <iostream>
#include <string>
class A {
int id;
public:
explicit A (int i) { id = i; }
void show() { std::cout << id << std::endl; }
};
int main() {
A first(3);
A second(4);
A a[2] = {first, second};
a[0].show();
a[1].show();
return 0;
}
However, a better way is to use vectors (say in a week you want 4 objects in your array, or n object according to an input). You can do it like this:
#include <iostream>
#include <string>
#include <vector>
class A {
int id;
public:
explicit A (int i) { id = i; }
void show() { std::cout << id << std::endl; }
};
int main() {
std::vector<A> a;
int n = 0;
std::cin >> n;
for (int i = 0; i < n; i++) {
A temp(i); // or any other number you want your objects to initiate them.
a.push_back(temp);
a[i].show();
}
return 0;
}

c++ vector's member are not updating

Im trying to write a adjacency matrix representation using vectors of integer vectors , therefore vector> . However when I add members to the vector and later try and print those values nothing has changed. Most likely it has to do with "pass by value" however I have used "pass by reference" to the best of my knowledge.
Here is my header:
#ifndef GRAPH_MATRIX
#define GRAPH_MATRIX
#include <vector>
//header for graph represented via adjacency matrix with minimal functionality
class graph
{
public:
graph(int);
~graph();
void add_edge(int v1, int v2, int weight);
void print_graph();
private:
std::vector<std::vector<int>> vertex_matrix;
int num_of_vertices;
int num_of_edges;
};
#endif
the cpp implementation file:
#include <iostream>
#include "graph_matrix.h"
#include <climits>
using namespace std;
//header for graph represented via adjacency matrix with minimal functionality
graph::graph(int _num_of_vertices) : num_of_vertices(_num_of_vertices)
{
if (_num_of_vertices==0)
{
_num_of_vertices=10;
}
for (int i = 0; i < _num_of_vertices; i++)
{
vertex_matrix.push_back(vector<int> (_num_of_vertices,INT_MAX));
}
}
graph::~graph()
{
vertex_matrix.clear();
}
void graph::add_edge(int v1, int v2, int weight)
{
//vertex_matrix[v1-1][v2-1] == INT_MAX
vector<int> columnVector = vertex_matrix[v1-1];
if (columnVector[v2-1] == INT_MAX)
{
columnVector[v2-1] = weight;
}
}
void graph::print_graph()
{
for (int i=0; i< vertex_matrix.size(); i++)
{
for (int j = 0; j < vertex_matrix.size(); j++)
{
//vertex_matrix[i][j]
std::vector<int> columnVector = vertex_matrix[i];
if (columnVector[j] != INT_MAX)
{
std::cout << columnVector[j] ;
}
else
{
std::cout << "0";
}
}
std::cout << endl;
}//end for printing
}
the main entry:
#include <iostream>
#include "graph_matrix.h"
using namespace std;
int main ()
{
std::cout << " Matrix representation of graph" << std::endl;
graph _graph(4);
_graph.add_edge(1,2,1);
_graph.add_edge(2,3,1);
_graph.add_edge(3,1,1);
_graph.add_edge(3,3,1);
_graph.add_edge(3,4,1);
_graph.add_edge(4,0,0);
_graph.print_graph();
}
When I use the print function I currently getting 0's.
How can I make this proper pass by reference, and have the updated values print.
Thanks
As stated in the comments, you are creating a copy of your column and then modifying the copy. What you want to do is to make a reference to it.
vector<int>& columnVector = vertex_matrix[v1-1];
if (columnVector[v2-1] == INT_MAX)
{
columnVector[v2-1] = weight;
}
Or you can access the element directly.
if (vertex_matrix[v1-1][v2-1] == INT_MAX)
{
vertex_matrix[v1-1][v2-1] = weight;
}
In print_graph you are doing the same, but here you are not modifying anything so that works, but you are making an unnecessary copy for no reason which is not ideal.
A last point is that you are calling vertex_matrix.clear() in your destructor. This is redundant, when the vector goes out of scope it will clear itself up, so you don't need to manage that.

c++ segmentation fault trying to access vector

Im trying to create a adjacency representation of a graph.
I wrote a small program using vectors of vectors , however I keep getting "segmentation fault" but the compiler(clang++ version 5.0.1 on Windows) it seems wereever I try to access the vector vertex_matrix its giving a segmentation fault, why is it not being instantiated?
Here is the header:
#ifndef GRAPH_MATRIX
#define GRAPH_MATRIX
#include <vector>
//header for graph represented via adjacency matrix with minimal functionality
class graph
{
public:
graph(int);
~graph();
void add_edge(int v1, int v2, int weight);
void print_graph();
private:
std::vector<std::vector<int>> vertex_matrix;
int num_of_vertices;
int num_of_edges;
};
#endif
Here is the cpp implementation:
#include <iostream>
#include "graph_matrix.h"
#include <climits>
using namespace std;
//header for graph represented via adjacency matrix with minimal functionality
graph::graph(int _num_of_vertices) : num_of_vertices(_num_of_vertices)
{
if (_num_of_vertices==0)
{
_num_of_vertices=10;
}
for (int i = 0; i < _num_of_vertices; i++)
{
vertex_matrix[i]=(vector<int> (_num_of_vertices,INT_MAX));
}
}
graph::~graph()
{
vertex_matrix.clear();
}
void graph::add_edge(int v1, int v2, int weight)
{
//vertex_matrix[v1-1][v2-1] == INT_MAX
vector<int> columnVector = vertex_matrix[v1-1];
if (columnVector[v2-1] == INT_MAX)
{
columnVector[v2-1] = weight;
}
}
void graph::print_graph()
{
cout << "vertex_matrix size:" << vertex_matrix.size() << endl;
for (int i=0; i< num_of_vertices; i++)
{
for (int j = 0; j < num_of_vertices; j++)
{
//vertex_matrix[i][j]
std::vector<int> columnVector = vertex_matrix[i];
if (columnVector[j] != INT_MAX)
{
std::cout << columnVector[j] ;
}
else
{
std::cout << "0";
}
}
std::cout << endl;
}//end for printing
}
Here is the main entry:
#include <iostream>
#include "graph_matrix.h"
using namespace std;
int main ()
{
std::cout << " Matrix representation of graph" << std::endl;
graph _graph(4);
_graph.add_edge(1,2,1);
_graph.add_edge(2,3,1);
_graph.add_edge(3,1,1);
_graph.add_edge(3,3,1);
_graph.add_edge(3,4,1);
_graph.add_edge(4,0,0);
_graph.print_graph();
}
I edited the above code to use pass by reference, however the matrix still prints as 0's.
Please help with pass by reference, updates below:
Header:
#ifndef GRAPH_MATRIX
#define GRAPH_MATRIX
#include <vector>
//header for graph represented via adjacency matrix with minimal functionality
class graph
{
public:
graph(int);
~graph();
void add_edge(int v1, int v2, int weight,std::vector<std::vector<int>> & matrix);
void print_graph();
std::vector<std::vector<int>> vertex_matrix;
private:
int num_of_vertices;
int num_of_edges;
};
#endif
Cpp file:
#include <iostream>
#include "graph_matrix.h"
#include <climits>
using namespace std;
//header for graph represented via adjacency matrix with minimal functionality
graph::graph(int _num_of_vertices) : num_of_vertices(_num_of_vertices) {
if (num_of_vertices == 0) {
num_of_vertices = 10;
}
for (int i = 0; i < num_of_vertices; i++) {
std::vector<std::vector<int>>& matrix = vertex_matrix;
matrix.push_back(vector<int> (num_of_vertices, INT_MAX));
}
}
graph::~graph() {
std::vector<std::vector<int>>& matrix = vertex_matrix;
matrix.clear();
}
void graph::add_edge(int v1, int v2, int weight,std::vector<std::vector<int>> & _matrix) {
//vertex_matrix[v1-1][v2-1] == INT_MAX
vector<int> columnVector = _matrix[v1 - 1];
if (columnVector[v2 - 1] == INT_MAX) {
columnVector[v2 - 1] = weight;
}
}
void graph::print_graph() {
std::vector<std::vector<int>>& matrix = vertex_matrix;
for (int i = 0; i < matrix.size(); i++) {
for (int j = 0; j < matrix.size(); j++) {
//vertex_matrix[i][j]
std::vector<int> columnVector = matrix[i];
if (columnVector[j] != INT_MAX) {
std::cout << columnVector[j];
} else {
std::cout << "0";
}
}
std::cout << endl;
}//end for printing
}
main:
#include <iostream>
#include "graph_matrix.h"
using namespace std;
int main ()
{
std::cout << " Matrix representation of graph" << std::endl;
graph _graph(4);
std::vector<std::vector<int>>& m = _graph.vertex_matrix;
_graph.add_edge(1,2,1,m);
_graph.add_edge(2,3,1,m);
_graph.add_edge(3,1,1,m);
_graph.add_edge(3,3,1,m);
_graph.add_edge(3,4,1,m);
_graph.add_edge(4,0,0,m);
_graph.print_graph();
}
Any help will be appreciated.
Thanks
You create an empty vector and then try to access elements in it. Change your constructor to
graph::graph(size_t _num_of_vertices) :
vertex_matrix(
std::vector<std::vector<int>>(
_num_of_vertices,std::vector<int>(_num_of_vertices)
)
)
{}
to create a correctly sized vector.
Also in case _num_vertices == 0 you set it to 10 but thats after you initialized the member num_vertices so you leave the object in an inconsistent state. There are different ways to fix that, I would probably just throw an exception when the number of vertices passed is zero, or just ignore it. User wants a zero sized matrix? Why not?
Moreover the size should be unsigned not signed, there is size_t for container sizes. Even better you shouldnt have that member at all, because a vector already knows its size, the only reason to repeat that information is to introduce mistakes ;)