Hi I'm a beginner at c++ and I'm having trouble solving this issue. I have a linkedlist of nodes and the node contains data of int array and a pointer pointing to the next node.
struct node {
unsigned int numbers[6];
node* next;
};
I also have a class:
private:
ticket* ticketListHead;
ticket* ticketListTail;
and in a public method:
public:
void newNode() {
int arr[6];
for(int i = 0; i < 6; ++i) {
arr[i] = ( std::rand() % 49 ) + 1;
}
node *temp = new node;
temp->numbers=arr;
temp->next=NULL;
}
The problem I believe is with the temp->numbers=arr line as I believe arrays cannot be assigned like that in C++. I'm not sure how to solve the problem in this case and I've tried looking online. Some help would be appreciated!
You're correct about your suspicion that you cannot assign arrays. You could instead use a wrapper type that allows assignment and define
using array = std::array<unsigned,6>; // convenient short hand
struct node {
array numbers;
node* next = nullptr; // ensure next defaults to null
};
when your newNode() method may look like
node* newNode() {
array arr;
for(auto&x: arr)
x = ( std::rand() % 49 ) + 1; // std::rand() cannot be recommended
auto temp = new node;
temp->numbers = arr;
return temp;
}
but you can avoid the temporary object arr altogether by directly writing into the new node's data:
node* newNode() {
auto temp = new node;
for(auto&x: temp->numbers)
x = ( std::rand() % 49 ) + 1; // std::rand() cannot be recommended
return temp;
}
Btw, you shouldn't use std::rand() (see this post and this presentation for reasons why). Instead, use the methods provided by <random>, when your code becomes (see also this answer)
template<typename Generator>
node* newNode(Generator&rng) {
std::uniform_int_distribution<unsigned> uni(1,49);
auto temp = new node;
for(auto&x: temp->numbers)
x = uni(rng); // guaranteed unbiased in [1,49] inclusive
return temp;
}
Welcome to C++, it's awesome that you're taking your first steps into a brighter world! What you'll want to look into are C++ container classes, they'll get you out of the business of managing memory on your own. The closest to your code is std::list and std::vector. I'll neglect random number seeding, that's a complex topic better discussed elsewhere.
#include <vector>
#include <list>
#include <iostream>
#include <random>
#include <limits>
using namespace std;
struct node {
node() : num(6) {
numbers.reserve(num);
for (int i = 0; i < num; ++i)
numbers.push_back(random() % numeric_limits<int>::max());
}
vector<int> numbers;
const int num;
};
int main(int argc, char** argv) {
list<node> nodes;
nodes.push_back(node()); // this replaces your newNode function
nodes.push_back(node()); // another call to better illustrate
for (auto mynode : nodes) {
for (auto mynum : mynode.numbers)
cout << mynum << " ";
cout << endl;
}
}
// Change node struct to this
struct node{
unsigned int *numbers;
node* next;
};
/*
Remember that normal arrays are
implemented through pointers. So you
can use a pointer named numbers in
your node struct and it would behave
as an array.
*/
// Change newNode() to this
void newNode() {
int * arr = new int[6]; //Dynamic memory allocation
for(int i = 0; i < 6; ++i)
{
arr[i] = ( std::rand() % 49 ) + 1;
}
node *temp = new node;
temp->numbers = arr;
temp->next = NULL;
}
U got it ?
Related
This question already has answers here:
Undefined, unspecified and implementation-defined behavior
(9 answers)
Closed 1 year ago.
The node Class is as follow:
class node
{
public:
int data; //the datum
node *next; //a pointer pointing to node data type
};
The PrintList Function is as follow:
void PrintList(node *n)
{ while (n != NULL)
{
cout << n->data << endl;
n = n->next;
}
}
If I try running it I get all three values (1,2,3) but I get an additional number as well which I'm unable to figure out what it represents, Can someone throw light on the same?
int main()
{
node first, second, third;
node *head = &first;
node *tail = &third;
first.data = 1;
first.next = &second;
second.data = 2;
second.next = &third;
third.data = 3;
PrintList(head);
}
I Know it can be fixed with
third.next = NULL;
But I am just curious what does this number represents in output, If I omit the above line
1
2
3
1963060099
As described in the comment by prapin, third.next is not initialized.
C++ has a zero-overhead rule.
Automatically initializing a variable would violate this rule as the value might be initialized (a second time) later on or never even be used.
The value of third.next is just the data that happened to live in the same memory location as third.next does now.
For this reason, it's recommended to always initialize your variables yourself.
It is better to initialize variables & it is better to use nullptr. Like that (See 1-3):
#include <iostream>
class node
{
public:
int data = 0; // 1
node* next = nullptr; // 2
};
void PrintList(node* n)
{
while (n != nullptr) // 3
{
std::cout << n->data << std::endl;
n = n->next;
}
}
int main()
{
node first, second, third;
node* head = &first;
node* tail = &third;
first.data = 1;
first.next = &second;
second.data = 2;
second.next = &third;
third.data = 3;
// third.next points to where?
PrintList(head);
}
Additional note:
I would prefer to use the STL container std::list:
#include <list>
#include <iostream>
std::list<int> int_list;
void PrintList()
{
for (auto i : int_list)
std::cout << i << std::endl;
}
int main()
{
int_list.push_back(1);
int_list.push_back(2);
int_list.push_back(3);
PrintList();
}
Or in case of list of node objects:
#include <list>
#include <iostream>
class node
{
public:
node(int data) : m_data{ data } {};
int m_data = 0;
// and maybe extra data-members
};
std::list<node> node_list;
void PrintList()
{
for (auto i : node_list)
std::cout << i.m_data << std::endl;
}
int main()
{
node_list.push_back(node(1));
node_list.push_back(node(2));
node_list.push_back(node(3));
PrintList();
}
I am creating a trie and am having trouble at the time of compiling.
The warningI get is:
"Reading invalid data from 'currNode->dict': the readable size is '104' bytes, but '388' bytes may be read."
#pragma once
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
const int SIZE = 26;
struct Node {
bool isWord;
Node* dict[SIZE];
};
class Dictionary
{
public:
Dictionary();
Dictionary(string file);
void addWord(string word);
private:
Node *root;
int numWords;
};
Dictionary::Dictionary()
{
numWords = 0;
root = new Node;
for (int i = 0; i < SIZE; i++)
root->dict[i] = nullptr;
}
Dictionary::Dictionary(string file)
{
numWords = 0;
root = new Node;
for (int i = 0; i < SIZE; i++)
root->dict[i] = nullptr;
ifstream inFile;
string word;
inFile.open(file);
while (inFile >> word) {
addWord(word);
numWords++;
}
}
void Dictionary::addWord(string word)
{
int len = word.length(); // size of word
char letter;
int pos;
Node *currNode = root;
for (int i = 0; i < len; i++) {
letter = word[i]; // takes character at position i
pos = letter - 'a'; // finds the position of the character in the array (0 through 25)
// with 'a' being 0 and 'z' being 25
if (!currNode->dict[pos]) {
currNode->dict[pos] = new Node;
currNode->isWord = false;
}
currNode = currNode->dict[pos];
}
currNode->isWord = true;
}
What could be causing this? I'm pretty sure that I'm not trying to access invalid memory. Perhaps it's the way I setup my node and class?
One mistake is that you fail to initialize Node to default values. In your Dictionary default constructor, you have code that really should be part of what Node should be doing:
root = new Node ;
for (int i = 0; i < SIZE; i++)
root->dict[i] = nullptr;
This should be Node's job, not the job of Dictionary.
Instead, you have this:
struct Node {
bool isWord;
Node* dict[SIZE];
};
So every time you do this:
if (!currNode->dict[pos]) {
currNode->dict[pos] = new Node;
You are creating an uninitialized Node object. That entire Node::dict array contains uninitialized pointers, which you later try to access.
The easiest solution is to zero-initialize the Node object.
if (!currNode->dict[pos]) {
currNode->dict[pos] = new Node(); // <-- Note the parentheses
This will automatically set the dict pointers to nullptr.
The other method is to make sure Node objects are created with default values:
#include <algorithm>
struct Node {
bool isWord;
Node* dict[SIZE];
Node() : isWord(false) { std::fill_n(dict, SIZE, nullptr); }
};
With this, even new Node; will create nodes that are initialized.
I'm trying to implement hash table with Separate chaining collision resolution and I have a problem.
This is my code (little modified to simplify, but error still same):
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
#include <cstring>
#include <string>
using namespace std;
int ascii(char character)
{
return character;
}
int hashFunction(string word, int num)
{
char* str = new char[word.length() + 1];
strcpy(str, word.c_str());
return ((3 * ascii(str[0]) + 5 * ascii(str[1]))) % num;
}
typedef struct tab
{
string data;
struct tab* next;
}Node;
typedef struct link
{
Node* head;
Node* tail;
}List;
List* createList()
{
List* list = new List();
if (list)
{
list->head = NULL;
list->tail = NULL;
}
return list;
}
void insert(List* list, string data)
{
//if list is empty
if (list->head == NULL) //!!!!!!!!!!!!!!!!ERROR OCCURE HERE !!!!!!!!!!!!!!!
{
list->head = new Node();
list->head->data = data;
list->head->next = NULL;
list->tail = list->head;
}
//if list already contains some data
else
{
list->tail->next = new Node();
list->tail->next->data = data;
list->tail = list->tail->next;
list->tail->next = NULL;
}
}
int main(int argc, char* argv[])
{
int size = 8; //Size of hash table (number of indexes)
List* table[12];
string A[8] = { "hello","world","car","notebook","science","starwars","lollypop","anything" };
//Insert elements from array A into a hash table
int index;
for (int i = 0; i < size; i++)
{
index = hashFunction(A[i], size);
if (table[index] == NULL)
table[index] = createList();
insert(table[index], A[i]);
}
return 0;
}
When I run the .exe file (or start from cmd), program ends up with message that app.exe has stopped working. I tried debug the program and got this:
http://imgur.com/a/yOhRV
Can anyone help me how to fix this? I've figured out problem must be in insert() function, probably in the condition, but I don't know what is wrong.
you derefernce a pointer without checking it: if (list->head == NULL)...
What you are doing here, is taking list and cheking if the value pointed by it is NULL, but since you haven't checked if (list) then it's possible that list == NULL and that causes segfault when dereferencing it
You are declaring List* table[12] but it is never initialized. So it does contain garbage.
You have to do the following in order to initialize it: List* table[12] = {NULL};
As a general rule you should never have uninitialized variables in your code (unless for optimization purposes when you know exactly what you are doing).
Add default contructors to your structs and make use of initialization list. Also keep you variables as local as possible (move index inside the loop).
You don't need ascii() cause char is integer type. char+char and char*int get promoted to int.
I have been trying to use pointer to pointer to perform action something similar to inorder traversal in tree. here is my code
struct node {
char c = '\0';
int freq = 0;
node *left = NULL;
node *right = NULL;
string code = "";
};
void appendones(node **n) {
if ((*n) == NULL)
;
else {
(*n)->code += "1";
appendones(&(*n)->left);
appendones(&(*n)->right);
}
}
void combinenodes(node *a, node *b, node **n) {
appendones(&a);
appendones(&b);
//(*n)=newNode('\0',a->freq+b->freq);
(*n)->c = '\0';
(*n)->freq = a->freq + b->freq;
(*n)->left = a;
(*n)->right = b;
}
int main() {
N = input();
priority_queue<node, vector<node *>, compareNodefreq> nodefreq; // function object
for (int i = 0; i < N; i++) {
char s;
int freq;
cin >> s >> freq;
node *n = newNode(s, freq);
nodefreq.push(n);
}
// printheap(nodefreq);
// perform combining nodes based on frequencies
while (nodefreq.size() > 1) {
node *a = nodefreq.top();
nodefreq.pop();
node *b = nodefreq.top();
nodefreq.pop();
node *n;
combinenodes(a, b, &n);
nodefreq.push(n);
}
}
I get segmentation fault in (*n)->code+="1"; for appendone().
I am not able to figure out the error. My understanding is that I am passing
the pointer by reference and performing the appendzero() and appendone(),
so I guess there is no error in that part. Also my a and b in
combinenodes() cannot be null because I am popping from the stack.
Could you help me figure out?
Oh, I see it. In main()'s while loop, n is pushed and used later, but is invalid because the node object itself is never allocated in combinenodes() (currently commented out). The pointer value, then, is undefined, but in this case, turning out to be non-zero, defeating the safety check.
Basically I want to print the data part of the Linked list which is basically an Integer pointer and I am assigning it an array at the time of creation, I want to print all the values of it how to do so ???
Thank you.
Here is my code
using namespace std;
struct Node{
Node *next;
int *data;
};
class DataLine{
private:
Node *first;
public:
DataLine(){
first=NULL;
}
void create_list(){
Node *temp=new Node;
int i=2;
int dat[5]={12,13,14,13,16};
temp->data=dat;
temp->next=NULL;
if(first==NULL){
//cout<<"hello 1"<<endl;
first=temp;
}
else{
Node *curr=first; //We are now doing trevercing so we are assigning the first to the node because we donot want to move the first bacuse link break if we move the first
while(curr->next!=NULL) //searching end of list
{
curr=curr->next; //Moving to the next node
}
curr->next=temp; //insert node
temp=NULL; //Making the temp enpty to use it for the new purpose
//delete temp;
}
}
void print_list()
{
Node *prnt=first; //We are now again want trevercing so we agin run the node by the new node
while(prnt!=NULL) //Checking the loop will run till it get the null in the node means its address part and data part both are nUll
{
for(int i=0;i<5;i++)
cout<<" ***** The "<<" node is "<<*(prnt->data+i)<<endl; //Printing the data
prnt=prnt->next; //Moving to the next node
}
}
};
int main(){
DataLine dl;
dl.create_list();
dl.print_list();
_getch();
return 0;
}
The idea of your void print_list(void) is correct but you can make it much cleaner, note however I changed your output to print a single node per line (change that back if you want). The structure of a for loop seems, to me, perfect for linked lists and keeps the linked list code our of the body of the loop.
void print_list(void) const
{
for (Node* p = first; p != NULL; p = p->next)
{
for (int i = 0; i < Node::unLength; ++i) std::cout << p->data[i] << ", ";
std::cout << std::endl;
}
}
However, as pointed out in some of the comments, there are other problems in your create list code. The way I would suggest to fix these (for this program) would be to redefine your structure to always hold a fixed number of integers.
struct Node
{
enum { unLength = 5 };
Node* next;
int data[unLength];
};
I have also added here a constant for the length of the array, since its bad practice to have magic numbers floating around your code, what happens if you mistype one of them?
Now in your void create_list() you can go:
void create_list()
{
Node* temp = new Node;
// Set the next node of temp
temp->next = NULL;
// Add some data to temp (we can't just assign the data pointer in C/C++)
int data[Node::unLength] = {0, 1, 2, 3, 4};
for (int i = 0; i < Node::unLength; ++i) temp->data[i] = data[i];
Node *p = first;
while (p != NULL) p = p->next;
p->next = temp;
}
There is no point setting temp to NULL since temp is deleted straight after the function returns. In your previous code you set the pointer in Node to data (temp->data=dat;, this doesn't work either since dat was deleted as soon as the function returned, you need to instead allocate memory and copy the values from dat which is what the for loop in the above code does.
For you class constructor (and destructor) I would suggest:
class DataLine
{
private:
Node* first;
public:
DataLine(void) : first(NULL) {}
~DataLine(void)
{
while (first != NULL)
{
Node *temp = first->next;
delete first;
first = temp;
}
}
You had the right idea, but there are a few subtle things about C/C++ that aren't obvious in higher level languages, such as copying arrays and the scope of variables.
If you are using C++ however, I would really suggest not worrying about linked lists, just create a std::vector, in C++ 11 something like the following might work (untested):
#include <vector>
#include <array>
int main(int argc, char** argv)
{
std::vector< std::array<int, 5> > myData;
myData.push_back({0, 1, 2, 3, 4});
myData.push_back({0, 1, 2, 3, 4});
myData.push_back({0, 1, 2, 3, 4});
for (const auto& i : myData)
{
for (int j : i) std::cout << j << ", ";
std::cout << std::endl;
}
return 0;
}