Access private struct within class c++ - c++

Trying to implement an adjacency matrix graph and practice OOP. I've been stuck on implementing the inserNode(string ) method.
My troubles are with accessing the private data fields. What am I completely missing?
Some of the errors:
Graph.cpp:30:26: error: unknown type name 'node'
graph[id] = new node;
^
Graph.cpp:35:10: error: use of undeclared identifier 'numnodes'
numnodes++;
Graph.cpp:34:19: error: expected ';' at end of declaration
graph[id]->nodename = name;
Graph.cpp:34:15: error: decomposition declaration '[id]' requires an initializer
graph.h
#include <iostream>
using namespace std;
class Graph {
public:
Graph();
int insertNode(string name);
private:
static const int vertices = 20;
int nodeCount;
struct node {
int nodeid; // node position in graph[]
string nodename; // username
};
// pointers to the graph nodes
node *graph[vertices];
// adjacency matrix for graph. True if edge is going from node i to j.
bool edges[vertices][vertices];
};
#endif
graph.cpp
#include "Graph.h"
Graph::Graph() {
for (int i = 0; i < vertices; i++) {
graph[i] = 0;
for (int j = 0; j < vertices; j++ )
edges[i][j] = 0;
}
}
/* create node and insert pointer in first available graph position. Returns id value, -1 if unsuccessful. */
int insertNode(string name) {
int id = 0;
while (id < vertices) {
if (graph[id] == NULL) {
graph[id] = new node;
if (!graph[id])
return -1;
graph[id]->nodeid = id;
graph[id]->nodename = name;
numnodes++;
return id;
}
id++;
}
return -1;
}

The insertNode you've defined is not the same way you declared in Graph. You've just made a free function called insertNode, which isn't a member of Graph and therefore can't access Graph. You need to define it like so:
int Graph::insertNode(string name)
{
}

Related

How to fix binary operators errors?

I have to write code that represent the graph using an adjacency list. I tried setting up my code to use a std::list but now that gives me errors saying
Error C2679 binary '=': no operator found which takes a right-hand operand of type 'int' (or there is no acceptable conversion) on multiple lines of my code. I'm confused on how I get my code to use an adjacency list without having all these issues.
#include "GraphInterface.h"
#include <string>
#include <fstream>
#include <iostream>
#include <vector>
#include<list>
#ifndef GRAPH_TWO
#define GRAPH_TWO
template<class LabelType>
class GraphTwo : public GraphInterface<LabelType>
{
private:
// Define maximum number of nodes
static const int size = 10;
std::list <int> adj[size][size];
std::list<bool>visited[size];
public:
GraphTwo();
// Get the number of vertices
int getNumVertices() const;
// Get the number of the edges
int getNumEdges() const;
// Creates an undirected edge in this graph between two vertices
// that have the given labels.If such vertices do not exist, creates
// themand adds them to the graph before creating the edge
bool add(LabelType start, LabelType end, int edgeWeight);
// Removes an edge from this graph. If a vertex has no other edges,
// it is removed from the graph since this is a connected graph.
bool remove(LabelType start, LabelType end);
// Gets the weight of an edge in this graph.
int getEdgeWeight(LabelType start, LabelType end) const;
// Performs a depth - first search of this graph beginning at the given
// vertex and calls a given function once for each vertex visited.
void depthFirstTraversal(LabelType start, void visit(LabelType&));
// Performs a breadth - first search of this graph beginning at the given
// vertex and calls a given function once for each vertex visited.
void breadthFirstTraversal(LabelType start, void visit(LabelType&));
};
template<class LabelType>
GraphTwo<LabelType>::GraphTwo()
{}
template<class LabelType>
int GraphTwo<LabelType>::getNumVertices() const
{
return size;
}
template<class LabelType>
int GraphTwo<LabelType>::getNumEdges() const
{
int edgeCount = 0;
for (int i = 0; i < size; ++i)
for (int j = 0; j < size; ++j)
if (adj[i][j] != 0)
++edgeCount;
return edgeCount / 2;
}
template<class LabelType>
bool GraphTwo<LabelType>::add(LabelType start, LabelType end, int edgeWeight)
{
adj[start][end] = edgeWeight; //error here
adj[end][start] = edgeWeight; //error here
return true;
}
template<class LabelType>
bool GraphTwo<LabelType>::remove(LabelType start, LabelType end)
{
adj[start][end] = 0; // error here
adj[end][start] = 0; // error here
return true;
}
template<class LabelType>
int GraphTwo<LabelType>::getEdgeWeight(LabelType start, LabelType end) const
{
return adj[start][end];
}
template<class LabelType>
void GraphTwo<LabelType>::depthFirstTraversal(LabelType start, void visit(LabelType&))
{
// Visit the current node
visit(start);
// Mark the current node as visited
visited[start] = true;
// For all other nodes
for (int i = 0; i < size; ++i) {
if (adj[start][i] != 0 && (!visited[i]))
depthFirstTraversal(i, visit);
}
}
template<class LabelType>
void GraphTwo<LabelType>::breadthFirstTraversal(LabelType start, void visit(LabelType&))
{
// Vector that contains the adjacent nodes
std::vector<LabelType> alist;
alist.push_back(start);
// Mark current node as visited
visited[start] = true; // error here
int check;
while (!alist.empty()) {
check = alist[0];
// Print node
visit(check);
alist.erase(alist.begin());
// Every vertex adjacent
for (int i = 0; i < size; ++i) {
if (adj[check][i] != 0 && (!visited[i])) {
// Add node to the queue
alist.push_back(i);
// Mark next node as visited
visited[i] = true; // error here
}
}
}
// Reset visited as all false
for (int i = 0; i < size; ++i)
visited[i] = false; // error here
}
#endif
std::list <int> adj[size][size];
This is not what you think it is. adj is an array of size arrays of size lists.
This makes adj[start][end] have type std::list<int>. The same applies to all your lists. Go find a good documentation on how to use std::list and don't try to guess the C++ syntax, learn it.

Passing an integer pointer to a constructor and getting runtime memory error

I'm trying to create a vector of a class-name vertex. The value of "n" is not known at compile-time so I'll be using new to create to create the "path" array. But the problem occurs when I create the input array in a function and push it in the vector.
int n;
class vertex {
public:
int *path;
int visited = 0;
vertex(int *y) {
path = new int(n);
for (int i = 0; i < n; i++)
path[i] = y[i];
}
};
void inp(vector<vertex> graph) {
int t1[] = { 0,1,0,0 };
int t2[] = { 0,0,1,0 };
int t3[] = { 0,0,0,1 };
int t4[] = { 0,0,0,0 };
graph.push_back(vertex(t1));
graph.push_back(vertex(t2));
graph.push_back(vertex(t3));
graph.push_back(vertex(t4));
}
int main() {
n=4;
vector<vertex> graph;
inp(graph);
_getch();
}
For simplicity I've created t1 to t4 as static arrays. But still it shows some error at runtime
1:try use: path = new int [n], rather than path = new int(n);
2:if you want to push elements to graph, you should change your function inp to void inp(vector<vertex>& graph)

Unable to Access Struct Members within Template

I decided to make my HashTable class a template so I could practice making templates, but I've run into a problem. Within my HashTable<T> template, I have a data member array, called items of Buckets, which is a struct within the HashTable<T> class. After initializing items, I am unable to access the members of Bucket elsewhere in the template's code.
I have tried putting typename and template<class T> before the struct and variable definitions, but was unable to make it work.
Here is a snippet of code that gives me the error 'keyValue': undeclared identifier
#ifndef HASH_TABLE_
#define HASH_TABLE_
using namespace std;
#include <iostream>
template<class T>
class HashTable
{
public:
HashTable(int numItems) {
if (numItems <= 0) {
throw std::invalid_argument("Invalid HashTable size");
}
currItems = 0;
//B must be the next prime after 2 * numItems
B = 1000;
items = Bucket[B]; //allocate array of Buckets
items[0].keyVal; //ERROR: undeclared identifier
}
bool insert(T* newItem, int key) {
bool retVal = false;
if (currItems < B && newItem != NULL) { //cannot insert to full HashTable
int index = 0;
items[index].dataPtr = newItem; //ERROR:undeclared
items[index].keyVal = key; //ERROR:undeclared
retVal = true;
currItems++;
}
return retVal;
}
private:
struct Bucket {
T* dataPtr = NULL;
int keyVal = -1;
};
Bucket * items; //array of buckets
int B; //size of itemArray
int currItems; //track number of items in HashTable
};
#endif
Why does items[x] not access a Bucket, such that items[x].keyVal or items[x].dataPtr cannot be used? I've tried different types of initializations, such as items = new Bucket[B], but that hasn't worked either, so I am assuming my errors lie in the template side of things.
I appreciate any guidance!
You have to declare Bucket before you use it.
template<class T>
class HashTable
{
struct Bucket {
T* dataPtr = NULL;
int keyVal = -1;
};
public:
HashTable(int numItems) {
if (numItems <= 0) {
throw std::invalid_argument("Invalid HashTable size");
}
currItems = 0;
//B must be the next prime after 2 * numItems
B = nextPrime(numItems * 2);
items = new Bucket[B]; // <-- you forgot the 'new'
items[0].keyVal; //ERROR: undeclared identifier
}
bool insert(T* newItem, int key) {
bool retVal = false;
if (currItems < B && newItem != NULL) { //cannot insert to full HashTable
int index = getOpenBucket(key);
items[index].dataPtr = newItem; //ERROR:undeclared
items[index].keyVal = key; //ERROR:undeclared
retVal = true;
currItems++;
}
return retVal;
}
private:
Bucket * items; //array of buckets
int B; //size of itemArray
int currItems; //track number of items in HashTable
};
ps. do not do this: using namespace std; in header files - ever.
It is evil and antisocial as it poisons the global namespace of every cpp file that includes your header. It's a guaranteed way to ensure that no-one will ever use your library.

Typedef array referencing?

Hello I have a question regarding the usage of typedef in C++. I am trying to create my own graph class where I can perform DFS and BFS. I have attached what I have for the class so far. But every time I try to compile I run into certain errors that I just do not know how to fix. I am sure the error has something to do with the variable vertexList that I use to hold all the vertices.
#include <iostream>
#include <stack>
class myGraph{
public:
typedef struct Vertex{
char label;
bool visited;
}Vertex;
myGraph(int);
void AddVertex(char);
void addEdge(int, int);
int adjUnvisited(int);
void displayVertex(int);
void dfs();
private:
Vertex* vertexList;
int** adjMatrix;
int size;
int vertices;
int count;
};
myGraph::myGraph(int size){
count = 0;
size = size;
vertices = size;
vertexList = new Vertex[vertices];
adjMatrix = new int*[size];
for(int i=0; i<size; i++){
adjMatrix[i] = new int[vertices];
}
for(int i=0; i<vertices; i++){
for(int j=0; j<vertices; j++){
adjMatrix[i][j] = 0;
}
}
}
void myGraph::AddVertex(char label){
Vertex* myVertex = new Vertex();
myVertex->label = label;
myVertex->visited = false;
vertexList[count++] = myVertex;
}
void myGraph::addEdge(int a, int b){
adjMatrix[a][b] = 1;
adjMatrix[b][a] = 1;
}
int myGraph::adjUnvisited(int index){
for(int i=0; i<vertices; i++){
if(adjMatrix[i][index]==1 && vertexList[i]->visited==false){
return i;
}
}
return -1;
}
void myGraph::displayVertex(int index){
std::cout << "Current vertex: " << vertexList[index]->label << std::endl;
}
void myGraph::dfs(){
std::stack<int> myStack;
int temp = 0;
vertexList[temp]->visited = true;
myStack.push(temp);
int unvisitedVertex;
while(!myStack.empty()){
unvisitedVertex = adjUnvisited[myStack.top()];
if(unvisitedVertex!=-1){
myStack.push(unvisitedVertex);
displayVertex(unvisitedVertex);
vertexList[unvisitedVertex]->visited = true;
}else{
myStack.pop();
}
}
}
The error message that I get is this:
no viable overloaded '=' vertexList[count++] = myVertex;
Along with a note:
candidate function (the implicit copy assignment
operator) not viable: no known conversion from 'struct Vertex *' to
'const myGraph::Vertex' for 1st argument; dereference the argument with *
struct Vertex{
And some other error messages which are (I'm sure these are very minor and I can figure them out):
member reference type 'struct Vertex' is not a
pointer; maybe you meant to use '.'?
if(adjMatrix[i][index]==1 && vertexList[i]->visited==false){
reference to non-static member function must be called
unvisitedVertex = adjUnvisited[myStack.top()];
Now I am not sure what exactly I am doing wrong and was wondering if someone here could help me out.
Thank you very much for all your help!
You've declared vertexList as a pointer-to-Vertex - which is fair enough, since it's going to be an array. But that means that each element of that array is a Vertex structure - yet you're accessing each array element as though it was a pointer.
Either:
Replace all the ->s with .s and do something different in AddVertex()
Declare vertexList as a Vertex ** (like adjMatrix)

expected constructor, destructor, or type conversion before '(' token

I am new to programming. I just learned concepts of c++ and some data structures.
I am trying to code a graph representation using adjacency list.
I am using codeblocks as my compiler. However, whenever I try to compile my program i get the following error...
C:\Users\Garg\Desktop\try\Stack.cpp|22|error: variable or field 'initialize_graph' declared void|
C:\Users\Garg\Desktop\try\Stack.cpp|22|error: expected primary-expression before ',' token|
C:\Users\Garg\Desktop\try\Stack.cpp|22|error: expected primary-expression before 'int'|
C:\Users\Garg\Desktop\try\Stack.cpp|23|error: variable or field 'read_graph' declared void|
C:\Users\Garg\Desktop\try\Stack.cpp|23|error: expected primary-expression before ',' token|
C:\Users\Garg\Desktop\try\Stack.cpp|23|error: expected primary-expression before 'int'|
C:\Users\Garg\Desktop\try\Stack.cpp|24|error: variable or field 'insert_edge' declared void|
C:\Users\Garg\Desktop\try\Stack.cpp|24|error: expected primary-expression before ',' token|
C:\Users\Garg\Desktop\try\Stack.cpp|24|error: expected primary-expression before 'int'|
C:\Users\Garg\Desktop\try\Stack.cpp|24|error: expected primary-expression before 'int'|
C:\Users\Garg\Desktop\try\Stack.cpp|24|error: expected primary-expression before 'int'|
C:\Users\Garg\Desktop\try\Stack.cpp|25|error: variable or field 'print_graph' declared void|
C:\Users\Garg\Desktop\try\Stack.cpp|25|error: expected primary-expression before ')' token|
C:\Users\Garg\Desktop\try\Stack.cpp||In function 'int main()':|
C:\Users\Garg\Desktop\try\Stack.cpp|32|error: 'read_graph' was not declared in this scope|
C:\Users\Garg\Desktop\try\Stack.cpp|33|error: 'print_graph' was not declared in this scope|
C:\Users\Garg\Desktop\try\Stack.cpp|36|error: variable or field 'initialize_graph' declared void|
C:\Users\Garg\Desktop\try\Stack.cpp|36|error: 'g' was not declared in this scope|
C:\Users\Garg\Desktop\try\Stack.cpp|36|error: expected primary-expression before 'int'|
C:\Users\Garg\Desktop\try\Stack.cpp|46|error: variable or field 'read_graph' declared void|
C:\Users\Garg\Desktop\try\Stack.cpp|46|error: 'g' was not declared in this scope|
C:\Users\Garg\Desktop\try\Stack.cpp|46|error: expected primary-expression before 'int'|
||=== Build finished: 21 errors, 0 warnings ===|
Here is my program:
#include<iostream>
#define MAXV 1000 /* maximum number of vertices */
using namespace std;
struct node
{
int y; /*adjacency info*/
int weight; /* edge weight, if any */
struct node *next; /* next edge in list */
} edgenode;
struct graph{
node *edges[MAXV+1]; /* adjacency info */
int degree[MAXV+1]; /* outdegree of each vertex */
int nvertices; /* number of vertices in graph */
int nedges; /* number of edges in graph */
int directed; /* is the graph directed? */
} graph;
void initialize_graph (graph *, int);
void read_graph (graph *, int);
void insert_edge (graph *, int, int, int);
void print_graph (graph *);
int main()
{
struct graph *g = NULL;
cout << "Now reading graph";
read_graph(g, 1);
print_graph(g);
return 0;
}
void initialize_graph(graph *g, int directed)
{
int i;
g -> nvertices = 0;
g -> nedges = 0;
g -> directed = directed;
for (i=1; i<=MAXV; i++) g->degree[i] = 0;
for (i=1; i<=MAXV; i++) g->edges[i] = NULL;
}
void read_graph(graph *g, int directed)
{
int i;
int m;
int x, y; /* vertices in edge (x,y) */
initialize_graph(g, directed);
cout << "Enter the number of vertivces and edges";
cin >> g->nvertices;
cin >> m;
cout << "Enter the vertices for the edge and the weight of the edge";
for (i=1; i<=m; i++) {
cin >> x;
cin >> y;
insert_edge(g,x,y,directed);
}
}
void insert_edge(graph *g, int x, int y, int directed)
{
struct node *p;
p = malloc(sizeof(struct node));
p->weight = NULL;
p->y = y;
p->next = g->edges[x];
g->edges[x] = p; /* insert at head of list */
g->degree[x] ++;
if (directed == 0)
insert_edge(g,y,x,1);
else
g->nedges ++;
}
void print_graph(graph *g)
{
int i; /* counter */
edgenode *p; /* temporary pointer */
for (i=1; i<=g->nvertices; i++) {
cout << i;
p = g->edges[i];
while (p != NULL) {
cout << p->y;
p = p->next;
}
cout << "\n";
}
}
Moreover, when i define the functions before main then i get the following result:
C:\Users\Garg\Desktop\try\Stack.cpp|23|error: expected constructor, destructor, or type conversion before '(' token|
C:\Users\Garg\Desktop\try\Stack.cpp|33|error: expected constructor, destructor, or type conversion before '(' token|
||=== Build finished: 2 errors, 0 warnings ===|
#include<iostream>
#define MAXV 1000 /* maximum number of vertices */
using namespace std;
struct node
{
int y; /*adjacency info*/
int weight; /* edge weight, if any */
struct node *next; /* next edge in list */
} edgenode;
struct graph{
node *edges[MAXV+1]; /* adjacency info */
int degree[MAXV+1]; /* outdegree of each vertex */
int nvertices; /* number of vertices in graph */
int nedges; /* number of edges in graph */
int directed; /* is the graph directed? */
} graph;
initialize_graph(graph *g, int directed)
{
int i;
g -> nvertices = 0;
g -> nedges = 0;
g -> directed = directed;
for (i=1; i<=MAXV; i++) g->degree[i] = 0;
for (i=1; i<=MAXV; i++) g->edges[i] = NULL;
}
read_graph(graph *g, int directed)
{
int i;
int m;
int x, y; /* vertices in edge (x,y) */
initialize_graph(g, directed);
cout << "Enter the number of vertivces and edges";
cin >> g->nvertices;
cin >> m;
cout << "Enter the vertices for the edge and the weight of the edge";
for (i=1; i<=m; i++) {
cin >> x;
cin >> y;
insert_edge(g,x,y,directed);
}
}
insert_edge(graph *g, int x, int y, int directed)
{
struct node *p;
p = malloc(sizeof(struct node));
p->weight = NULL;
p->y = y;
p->next = g->edges[x];
g->edges[x] = p; /* insert at head of list */
g->degree[x] ++;
if (directed == 0)
insert_edge(g,y,x,1);
else
g->nedges ++;
}
print_graph(graph *g)
{
int i; /* counter */
edgenode *p; /* temporary pointer */
for (i=1; i<=g->nvertices; i++) {
cout << i;
p = g->edges[i];
while (p != NULL) {
cout << p->y;
p = p->next;
}
cout << "\n";
}
}
int main()
{
struct graph *g = NULL;
cout << "Now reading graph";
read_graph(g, 1);
print_graph(g);
return 0;
}
Any pointers to what wrong am I doing?
you have both a struct and a variable called graph. Don't do that.
When you declare those functions the compiler tries to use the variable...
I think the code
struct node
{
int y; /*adjacency info*/
int weight; /* edge weight, if any */
struct node *next; /* next edge in list */
} edgenode;
is missing a typedef before the struct. Try adding it to both struct definitions.
Without the typedef, it says: here is a structure, and by the way create a variable of this type. With the typedef, you are actually creating the types edgenode and graph.
Forgetting to declare the return type for your functions? For instance, in your last bunch of code initialize_graph should be
void initialize_graph(graph *g, int directed);
Update:
Your declaration of a variable graph shadows the struct with the same name. Hence, when you declare your functions taking graph* as an argument you are referring not to a type but to a variable.
Another Update:
You declare a pointer to graph and initialize it to NULL. You then try to dereference such null pointer from within your functions. You have to make the pointer point to a valid graph, for instance by assigning to it new graph();