I'm trying to access a structure using another structure. From the below program, element is the member of Node. At this line " temp->element *e_temp;", I couldn't link the "element" member of Node to the "elements" structure object.
compile error says "'e_temp' was not declared in this scope". What am I missing?
#include <vector>
#include <cstdlib>
using namespace std;
typedef struct Elements
{
int data;
struct Elements *next;
}elements;
typedef struct Node
{
int sno;
elements *element;
struct Node *next;
}node;
void add(int sno, vector<int> a)
{
node *temp;
temp = new node;
temp->element *e_temp;
e_temp = new elements;
temp->sno = sno;
while(a.size())
{
temp->e_temp->data = a[0];
temp->e_temp = temp->e_temp->next;
a.erase(a.begin());
}
}
int main()
{
vector<int> a{1,2,3};
int sno = 1;
add(sno, a);
return 0;
}
If you're just looking to declare a local you can do auto e_temp = new elements but what i think you want is this for that line temp->element = new elements;
and then follow up with the rest of your code to reference temp's element instead of e_temp.
temp->element->data = a[0];
temp->element = temp->element->next
Also, i'd try to get out the habit of using new and use std::shared_ptr and std::unique_ptr instead.
The correct declaration for e_temp is
elements * e_temp;
but e_temp is not use of any part of your code.
Related
I am trying to make a network application. Its class blueprint is roughly like this-
class Node
{
public:
// member functions
private:
int nodeID;
// other members
};
class NodeNetwork
{
public:
// member functions
private:
Node nodeArray[MAX_NODES];
// other members
};
Here, the Node class will deal with each node and the NodeNetwork is used to deal with the complete network.
The actual number of nodes in nodeArray can vary from 0 to MAX_NODES during runtime, i.e., it may not always be MAX_NODES, the number of nodes can be increased or decreased during runtime. Moreover, when the program starts the number will always be 0, after that it will start increasing.
I am using Node nodeArray[MAX_NODES];, but I think it's a serious wastage of space as not always I will have MAX_NODES nodes at runtime. So I am looking for ways to optimize it. I want it so that it starts with a zero-length array, but the size can be increased or decreased subjected to the above constraints based on the nodes added or removed at runtime. I researched on the internet but did not find any concrete answer.
I hope someone can help me solve this problem, thanks in advance.
You can use dynamically array allocation for this purpose:
int* arr = new int[5];
..and anytime you wish to change the number of elements:
int size = 5;
int* arr = new int[size] {};
int* new_arr = new int[size + 1];
for (int i = 0; i < size; i++)
{
new_arr[i] = arr[i];
}
delete[] arr;
arr = new_arr;
// Now arr has a storage capacity of 6 elements
..so for your case you can write:
Node* nodeArray = nullptr; // nullptr == null pointer
But this can take a lot of time for huge arrays.
So preferably, you can use std::vector:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> vec{ 1, 2, 3, 4, 5 };
vec.push_back(6); //Insert a new element
std::cout << vec[0]; // Accessing an element is the same as an array
}
..so for your case:
// {} is just for initialization, not exactly mandatory
std::vector<Node> nodeArray{};
You can use std::vector instead of array. That is, you can make the data member nodeArray to be a std::vector<Node> as shown below.
#include <iostream>
#include<vector>
class Node
{
public:
//constructor for initializing nodeID data member
Node(int pnodeID): nodeID(pnodeID)
{
}
//getter for nodeId
int getId() const
{
return nodeID;
}
private:
//always initialize built in type in local/block scope so that they don't have indeterminate value
int nodeID = 0;
// other members
};
class NodeNetwork
{
public:
// member function to add Node
void addNode(const Node& n)
{
nodeArray.push_back(n);
}
//member function to print out the current nodes
void display() const
{
std::cout<<"Network has the following nodes: "<<std::endl;
for(const Node& elem: nodeArray)
{
std::cout<<elem.getId()<<std::endl;
}
}
private:
std::vector<Node> nodeArray; //used std::vector instead of array
// other members
};
int main()
{
//create Node objects
Node node1{1};
Node node2{2};
Node node3{3};
NodeNetwork network1;
//add node1 into the network1's nodeArray data member
network1.addNode(node1);
//add node2 into the network1's nodeArray data member
network1.addNode(node2);
//display all nodes into network1
network1.display();
return 0;
}
In the above demo we have added elements into the nodeArray data member by using std::vector::push_back member function.
The output of the above program can be seen here:
Network has the following nodes:
1
2
I am trying to make a basic HashMap. I am checking to see if an element exists at an index before inserting it there. When I insert my first element, it says that an element already exists at that position. I have gone through the debugger, and all of my values are as expected, except for map[hash]. I am anticipating a nullptr, but it is not coming. map[hash] has the following value:
- map[hash] 0xcdcdcdcd {key=??? value={...} next_element=??? } HashElement *
Can someone please explain to me what I am misunderstanding here? The unexpected result is on line 21 of HashMap.cpp. Here is the relevant code:
HashMap.h
#pragma once
#include <string>
#include "HashElement.h"
class HashMap
{
private:
HashElement **map;
int size;
public:
HashMap(int);
~HashMap();
int GetHash(int);
void Put(int, std::string);
};
HashMap.cpp
#include "HashMap.h"
#include <string>
HashMap::HashMap(int _size)
{
size = _size;
map = new HashElement*[size];
}
HashMap::~HashMap()
{
}
int HashMap::GetHash(int _key){
return _key % size;
}
void HashMap::Put(int _key, std::string _value){
int hash = GetHash(_key);
if (!map[hash]){ //Anticipated to be nullptr on first Put, but it skips to else
map[hash] = new HashElement(_key, _value);
}
else{
HashElement *lastElement = map[hash];
while (lastElement->next_element){
lastElement = lastElement->next_element;
}
lastElement->next_element = new HashElement(_key, _value);
}
}
HashElement.h
#pragma once
#include <string>
class HashElement
{
private:
int key;
std::string value;
public:
HashElement(int, std::string);
~HashElement();
HashElement *next_element;
int get_key();
std::string get_value();
};
HashElement.cpp
#include "HashElement.h"
HashElement::HashElement(int _key, std::string _value)
{
key = _key;
value = _value;
}
HashElement::~HashElement()
{
}
int HashElement::get_key(){
return key;
}
std::string HashElement::get_value(){
return value;
}
map[hash] is not a nullptr because you haven't initialized it to such.
map = new HashElement*[size];
Each element in the map array will have a random value after that line.
To fix this and initialize all elements to be nullptr:
map = new HashElement*[size]();
^^
map = new HashElement*[size];
Here, you are instantiating an array of size pointers, on the heap. As I understand your question, you are assuming that all of the instantiated pointers, in this new array, will be nullptr.
That is not the case. For "plain old data", or POD, its contents are not initialized by default. You'll have to explicitly initialize them:
for (size_t i=0; i<size; ++i)
map[i]=0;
... in the constructor
I need to assign an int value to a pointer, how would I do it?
Below is a small example of what I want.
struct {
int a;
} name;
int temp = 3;
struct name *obj = NULL;
Now, I need to assign this value '3' to struct's 'a'.
With
struct {
int a;
}name;
you already define a struct variable which allocates memory for the struct (e.g. on the stack when it is a local variable inside a function). Then, with int temp = 3;, it is sufficient to assign to the struct member like
name.a = temp;
If you want to declare a struct type only, then use
struct name {
int a;
};
Then you can define any number of struct variables based on this type, like
struct name theName;
and do the same assignment to theName members as above:
theName.a = temp;
Or, you can define a pointer to a struct and then have to allocate the memory yourself:
struct name *namePtr;
namePtr = malloc(sizeof(struct name));
namePtr->a = temp;
Note also that you have tagged your question both with C and C++ - especially with structs, you should decide which language to take - see Differences between struct in C and C++.
Declaring a pointer to a struct doesn't reserve memory for it, so first you have to do that. For example:
obj = malloc(sizeof(*obj));
Now you can assign the value:
obj->a = temp;
Note that the program as it currently stands does not define "struct name", it defines a variable called "name" that holds a struct. This is probably not what you intended.
The basic problem with the code is name is not the name of the structure but an object or a variable of the structure whose name you have already defined.
If u don't want to name the structure, even then still it need memory to be allocated.
struct
{
int a;
}name, *obj;
int temp = 3;
int main()
{
obj=&name; // 'obj' is pointing to memory area of 'name' : Keep this in mind throughout the code
obj->a=temp;
printf("%d %u %d",temp,&temp,obj->a);
return 0;
}
Best option is to put a name to the structure then use its pointer after allocating memory
typedef struct
{
int a;
}name;
int temp = 3;
name *obj = NULL;
int main()
{
obj = (name *)malloc(sizeof(name));
obj->a=temp;
printf("%d %u %d",temp,&temp,obj->a);
return 0;
}
EDIT (thanks Andreas):
Properly, your struct should be declared like so:
struct name {
int a;
};
void foo() {
struct name n; // allocate space for 'struct name' and call it n
struct name *obj; // a pointer to a 'struct name'
int temp = 3;
obj = &n; // make obj point to n
n.a = temp; // direct assignment to a
obj->a = temp; // assignment to a via pointer dereference
// a is now 3 in any case
}
Here is another, annotated, version of your code. Ran this on Eclipse/Microsoft C compiler, this is NOT C++ code.
#include <stdio.h>
main()
{
// define a structure as a data type
typedef struct
{
int *a;
} name;
// allocate storage for an integer and set it to 3
int temp = 3;
// allocate storage for the name structure
name obj;
// set the value of a in name to point to an integer
obj.a = &temp;
// dereference the integer pointer in the name structure
printf("%d\n", *obj.a);
}
obj->a = temp;
just have a try!
I have tried looking around and tried all the solutions but I cannot seem to fix my problem. I know i get the segmentation fault on the push_front line but I am just lost. Here is the code-
#include <iostream>
#include <fstream>
#include <sstream>
#include <list>
using namespace std;
typedef std::list<int> hSlots; //the list
typedef hSlots* hTable; //an array of lists
class HashTable
{
private:
int p; //p=number of slots in the hash table
hTable tmpPtr;
hTable *table;
public:
HashTable(int p1);
int h1(int k);
~HashTable();
void chainedHashInsert(int x);
};
HashTable::HashTable(int p1)
{
p=p1;
hTable tTable[p];
//initializing to empty lists
for (int i=0; i<p; i++)
{
tmpPtr = new hSlots;
tTable[i] = tmpPtr;
}
table = tTable;
}
//destrcutor
HashTable::~HashTable()
{
delete table;
delete tmpPtr;
}
void HashTable::chainedHashInsert(int x)
{
tmpPtr = table[h1(x)];
cout<<"hashed"<<endl;
tmpPtr->push_front(x); //segmentation fault
}
int HashTable::h1(int k)
{
int z = k%p;
return z;
}
I have not used a lot of lists so I'm not too sure
Maybe this could be a proper answer after all.
Your problems arise from doing memory management (wrong) manually, when really there is no need to, in C++.
Here's my take on it using direct automatic memory management in C++:
#include <vector>
#include <list>
using namespace std;
template <typename T, typename hSlots = std::list<T> >
class HashTable
{
private:
int p; //p=number of slots in the hash table
std::vector<hSlots> table;
int getbucket(int k) { return k%p; }
public:
HashTable(int p1) : p(p1), table(p1) {}
void chainedHashInsert(int x)
{
auto& tmpPtr = table[getbucket(x)];
tmpPtr.push_front(x);
}
};
int main()
{
HashTable<int> table(37);
}
since tTable is local variable to HashTable, it disappears when HashTable method returns and leaves table as a dangling pointer.
So to get rid of that do as below; create a space for table using new.
HashTable::HashTable(int p1)
{
p=p1;
table = new ttTable[p];
//initializing to empty lists
for (int i=0; i<p; i++)
{
tmpPtr = new hSlots;
table[i] = tmpPtr;
}
}
table = tTable;
This line is the problem (or at least one of them).
You're stashing a pointer to an automatic object into a member variable, then dereferencing (and deleting!) it later, once the object has been destroyed.
I have defined a vector like this in the header file
class entry
{
public:
int key;
int next;
};
std::vector<entry *> TB;
in the cpp file, I wrote:
int s1, val;
s1 = 10; val = 2;
gh = (TB.size() % s1);
However when I want to write something to it, I get segmentation fault
TB[gh]->key = val;
What is the problem with the assignment?
The vector has no elements. Use push_back() or insert() to add elements to the vector:
entry* e = new entry();
e->key = val;
e->next = 0;
TB.push_back(e); // Append to vector.
TB.insert(TB.begin(), e); // Insert at beginning of the vector.
When destroying the vector TB you must iterate over the elements and delete each individually (or use a smart pointer as the element type, such as boost::shared_ptr<entry> or std::unique_ptr<entry>).
You could provide a constructor(s) for entry to make the addition of an entry to TB more concise:
class entry
{
public:
entry(int a_key, int a_next = 0) : key(a_key), next(a_next) {}
int key;
int next;
};
TB.push_back(new entry(val));
TB.insert(TB.begin(), new entry(val));
The TB vector is empty, until you fill it with some pointers.
E.g. TB.resize(100);.
The points in TB should point to valid addresses, i.e. some valid entry instances. E.g. TB[0] = new entry();.
So:
std::vector<entry *> TB(1);
TB[0] = new entry();
TB[0]->key = 42;