Assigning pointer - c++

I have been working on this for a while and cannot seem to understand what is happening. I am trying to take the values in istr, put them in a linked list and sort them alphabetically. Eventually I will print them out. I am not sure where my problem is but I thought it was in the function InsertAfter. Is this not my problem and if so do you know what may be causing my linked list to not link? The last bit of code only outputs the headObj and not all of them, so I assumed that my list wasn't linking properly in nextNodePtr in each object but I am not sure. Thank you for your help!
void WordNode::InsertAfter(WordNode* nodeLoc) {
WordNode* tmpNext = 0;
tmpNext = this->nextNodePtr; // Remember next
this->nextNodePtr = nodeLoc; // this -- node -- ?
nodeLoc->nextNodePtr = tmpNext; // this -- node -- next
return;
}
wordNode.hpp
#ifndef wordNode_hpp
#define wordNode_hpp
#include <stdio.h>
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
class WordNode {
public:
WordNode(string wordval = "", int count = 0, WordNode* nextLoc = 0);
void InsertAfter(WordNode* nodePtr);
WordNode* GetNext();
void PrWordNodeData();
string GetWord();
private:
string word;
WordNode* nextNodePtr;
int wordCount;
};
wordNode.cpp
#include "wordNode.hpp"
// Constructor
WordNode::WordNode(string wordval,int count, WordNode* nextLoc) {
this->word = wordval;
this->wordCount = count;
this->nextNodePtr = nextLoc;
return;
}
/* Insert node after this node.
* Before: this -- next
* After: this -- node -- next
*/
void WordNode::InsertAfter(WordNode* nodeLoc) {
WordNode* tmpNext = 0;
tmpNext = this->nextNodePtr; // Remember next
this->nextNodePtr = nodeLoc; // this -- node -- ?
nodeLoc->nextNodePtr = tmpNext; // this -- node -- next
return;
}
// Print dataVal
void WordNode::PrWordNodeData() {
cout << this->word <<": count=" <<this->wordCount << endl;
return;
}
// Grab location pointed by nextNodePtr
WordNode* WordNode::GetNext() {
return this->nextNodePtr;
}
//Returns word
string WordNode::GetWord()
{
return word;
}
main.cpp
#include <iostream>
#include <sstream>
#include <string>
#include "wordNode.hpp"
int main() {
WordNode* headObj = 0; // Create WordNode objects
WordNode* currObj = 0;
WordNode* nextObj = 0;
string istr ="555 999 777 333 111";
istringstream instring(istr);
string temp;
//Assigns first word to the head object
if (!instring.eof()){
instring >> temp;
headObj=new WordNode(temp,1);
}
currObj=headObj;
while (!instring.eof()){
instring >> temp;
nextObj=new WordNode(temp,1);
//swaps values if currObj is greater than the next word
if(currObj > nextObj) {
currObj->InsertAfter(nextObj);
}
currObj=nextObj;
}
// Print linked list
currObj = headObj;
while (currObj != 0) {
currObj->PrWordNodeData();
currObj = currObj->GetNext();
}
string i;
cin >> i;
return 0;
}

In the very first iteration of the loop (using the string you gave as example) you loose the reference to the head object and hence subsequent iterations will add nodes to a "headless list".
currObj=headObj;
while (!instring.eof()){
instring >> temp;
nextObj = new WordNode(temp,1);
//swaps values if currObj is greater than the next word
if(currObj->GetWord() > nextObj->GetWord()) {
currObj->InsertAfter(nextObj);
}
// And what happens if it is not greater?
currObj = nextObj; // Loose reference to head here if not greater
}
To fix your code you will either just have to add all nodes to the list and then sort it with a sorting algorithm or insert them on the fly as you intend to do now. However, to do the latter you will have to modify your insertion logic, i.e. insert node at the beginning (if new node is alphabetically lower than the first element) or at the end. I recommend reading this nice article about singly linked lists. It has examples and code for the insertions mentioned.

Related

Inserting a basic singly linked list node seems to break my c++ code?

Singly Linked List and Node classes and the start of the main function, where I wrote a brief outline of the code functionality. The issue is toward the end of the main function. I wrote '...' in place of what I believe to be irrelevant code because it simply parses strings and assigns them to the string temp_hold[3] array.
#include <bits/stdc++.h>
using namespace std;
class Node {
public:
string value;
string attr;
string tagname;
Node *next;
Node(string c_tagname, string c_attr, string c_value) {
this->attr = c_attr;
this->value = c_value;
this->tagname = c_tagname;
this->next = nullptr;
}
};
class SinglyLinkedList {
public:
Node *head;
Node *tail;
SinglyLinkedList() {
this->head = nullptr;
this->tail = nullptr;
}
void insert_node(string c_tagname, string c_attr,string c_value) {
Node *node = new Node(c_tagname,c_attr, c_value);
if (!this->head) {
this->head = node;
} else {
this->tail->next = node;
}
this->tail = node;
}
};
int main(int argc, char **argv) {
/* storage is a vector holding pointers to the linked lists
linked lists are created and the linked list iterator sll_itr is incremented when
previous line begins with '</' and the currentline begins with '<'
linked lists have nodes, which have strings corresponding to tagname, value, and attribute
*/
SinglyLinkedList *llist = new SinglyLinkedList();
vector<SinglyLinkedList*> sllVect;
sllVect.push_back(llist);
auto sll_itr = sllVect.begin();
string temp_hold[3];
// to determine new sll creation
bool prev = false;
bool now = false;
//input
int num1, num2;
cin >> num1; cin >> num2;
//read input in
for (int i = 0; i <= num1; ++i) {
string line1, test1;
getline(cin, line1);
test1 = line1.substr(line1.find("<") + 1);
//determine to create a new linked list or wait
if (test1[0] == '/') {
prev = now;
now = true;
} else {
//make a node for the data and add to current linked list
if (i > 0) {
prev = now;
now = false;
//if last statement starts with '</' and current statment starts with '<'
// then start a new sll and increment pointer to vector<SinglyLinkedList*>
if (prev && !now) {
SinglyLinkedList *llisttemp = new SinglyLinkedList();
sllVect.push_back(llisttemp);
sll_itr++;
}
}
//parse strings from line
int j = 0;
vector<string> datastr;
vector<char> data;
char test = test1[j];
while (test) {
if (isspace(test) || test == '>') {
string temp_for_vect(data.begin(),data.end());
if (!temp_for_vect.empty()) {
datastr.push_back(temp_for_vect);
}
data.clear();
} else
if (!isalnum(test)) {
} else {
data.push_back(test);
}
j++;
test = test1[j];
}
//each node has 3 strings to fill
int count = 0;
for (auto itrs = datastr.begin(); itrs!=datastr.end(); ++itrs) {
switch (count) {
case 0:
temp_hold[count]=(*itrs);
break;
case 1:
temp_hold[count]=(*itrs);
break;
case 2:
temp_hold[count]=(*itrs);
break;
default:
break;
}
count++;
}
}
cout << "before storing node" << endl;
(*sll_itr)->insert_node(temp_hold[0], temp_hold[1], temp_hold[2]);
cout << "after" << endl;
}
cout << "AFTER ELSE" << endl;
return 0;
}
And here is the line that breaks the code. The auto sll_itr is dereferenced which means *sll_itr is now a SinglyLinkedList* and we can call the insert_node(string, string, string) to add a node to the current linked list. However when I keep the line, anything after the else statement brace does not run, which means the cout<<"AFTER ELSE"<< endl; does not fire. If I remove the insert_node line, then the program runs the cout<<"AFTER ELSE"<< endl; I am unsure what the issue is.
(*sll_itr)->insert_node(temp_hold[0],temp_hold[1],temp_hold[2]);
cout << "after" << endl;
} //NOT HANGING. This closes an else statement.
cout << "AFTER ELSE" << endl;
return 0;
}
Compiled as g++ -o myll mylinkedlist.cpp and then myll.exe < input.txt And input.txt contains
8 3
<tag1 value = "HelloWorld">
<tag2 name = "Name2">
</tag2>
</tag1>
<tag5 name = "Name5">
</tag5>
<tag6 name = "Name6">
</tag6>
Your linked list isn't the problem, at least not the problem here.
A recipe for disaster in the making: retaining, referencing, and potentially manipulating, an iterator on a dynamic collection that potentially invalidates iterators on container-modification. Your code does just that. tossing out all the cruft between:
vector<SinglyLinkedList*> sllVect;
sllVect.push_back(llist);
auto sll_itr = sllVect.begin();
....
SinglyLinkedList *llisttemp = new SinglyLinkedList();
sllVect.push_back(llisttemp); // HERE: INVALIDATES sll_iter on internal resize
sll_itr++; // HERE: NO LONGER GUARANTEED VALID; operator++ CAN INVOKE UB
To address this, you have two choices:
Use a container that doesn't invalidate iterators on push_back. There are really only two sequence containers that fit that description: std::forward_list and std::list.
Alter your algorithm to reference by index`, not by iterator. I.e. man your loop to iterate until the indexed element reaches end-of-container, then break.
An excellent discussion about containers that do/do-not invalidate pointers and iterators can be found here. It's worth a read.

Hash table implementation in C++

I am trying the following code for Hash table implementation in C++. The program compiles and accepts input and then a popup appears saying " the project has stopped working and windows is checking for a solution to the problem. I feel the program is going in the infinite loop somewhere. Can anyone spot the mistake?? Please help!
#include <iostream>
#include <stdlib.h>
#include <string>
#include <sstream>
using namespace std;
/* Definitions as shown */
typedef struct CellType* Position;
typedef int ElementType;
struct CellType{
ElementType value;
Position next;
};
/* *** Implements a List ADT with necessary functions.
You may make use of these functions (need not use all) to implement your HashTable ADT */
class List{
private:
Position listHead;
int count;
public:
//Initializes the number of nodes in the list
void setCount(int num){
count = num;
}
//Creates an empty list
void makeEmptyList(){
listHead = new CellType;
listHead->next = NULL;
}
//Inserts an element after Position p
int insertList(ElementType data, Position p){
Position temp;
temp = p->next;
p->next = new CellType;
p->next->next = temp;
p->next->value = data;
return ++count;
}
//Returns pointer to the last node
Position end(){
Position p;
p = listHead;
while (p->next != NULL){
p = p->next;
}
return p;
}
//Returns number of elements in the list
int getCount(){
return count;
}
};
class HashTable{
private:
List bucket[10];
int bucketIndex;
int numElemBucket;
Position posInsert;
string collision;
bool reportCol; //Helps to print a NO for no collisions
public:
HashTable(){ //constructor
int i;
for (i=0;i<10;i++){
bucket[i].setCount(0);
}
collision = "";
reportCol = false;
}
int insert(int data){
bucketIndex=data%10;
int col;
if(posInsert->next==NULL)
bucket[bucketIndex].insertList(data,posInsert);
else { while(posInsert->next != NULL){
posInsert=posInsert->next;
}
bucket[bucketIndex].insertList(data,posInsert);
reportCol=true;}
if (reportCol==true) col=1;
else col=0;
numElemBucket++;
return col ;
/*code to insert data into
hash table and report collision*/
}
void listCollision(int pos){
cout<< "("<< pos<< "," << bucketIndex << "," << numElemBucket << ")"; /*codeto generate a properly formatted
string to report multiple collisions*/
}
void printCollision();
};
int main(){
HashTable ht;
int i, data;
for (i=0;i<10;i++){
cin>>data;
int abc= ht.insert(data);
if(abc==1){
ht.listCollision(i);/* code to call insert function of HashTable ADT and if there is a collision, use listCollision to generate the list of collisions*/
}
//Prints the concatenated collision list
ht.printCollision();
}}
void HashTable::printCollision(){
if (reportCol == false)
cout <<"NO";
else
cout<<collision;
}
The output of the program is the point where there is a collision in the hash table, thecorresponding bucket number and the number of elements in that bucket.
After trying dubbuging, I come to know that, while calling a constructor you are not emptying the bucket[bucketIndex].
So your Hash Table constructor should be as follow:
HashTable(){ //constructor
int i;
for (i=0;i<10;i++){
bucket[i].setCount(0);
bucket[i].makeEmptyList(); //here we clear for first use
}
collision = "";
reportCol = false;
}
//Creates an empty list
void makeEmptyList(){
listHead = new CellType;
listHead->next = NULL;
}
what you can do is you can get posInsert using
bucket[bucketIndex].end()
so that posInsert-> is defined
and there is no need to
while(posInsert->next != NULL){
posInsert=posInsert->next;
because end() function is doing just that so use end() function

Why this code failed to run

i want to generate a tree of siblings as under
ABCD
/ | \ \
A B C D
ABCD has four nodes i have taken a array for this *next[]. but this code does not run successfully but it produces the sequence. i have written code in main() which provide characters to the enque function. e.g. str.at(x) where x is variable in for loop.
struct node
{
string info;
struct node *next[];
}*root,*child;
string str, goal;
int dept=0,bnod=0,cl,z=0;
void enqueue(string n);
void enqueue(string n)
{
node *p, *temp;
p=new node[sizeof(str.length())];
p->info=n;
for (int x=0;x<str.length();x++)
p->next[x]=NULL;
if(root==NULL)
{
root=p;
child=p;
}
else
{
cout<<" cl="<<cl<<endl;
if(cl<str.length())
{
child->next[cl]=p;
temp=child->next[cl];
cout<<"chile-info "<<temp->info<<endl;
}
else
cout<<" clif="<<cl<<endl;
}
}
OUTPUT
Enter String: sham
cl=0
chile-info s
cl=1
chile-info h
cl=2
chile-info a
cl=3
chile-info m
RUN FAILED (exit value 1, total time: 2s)
Firstly, where does "RUN FAILED" come from? Is that specific to your compiler?
Secondly, about the line p=new node[sizeof(str.length())];, it probably won't give you what you wanted because you're taking the sizeof of an unsigned integer ( which, depending on your platform is likely to give you 4 regardless of the string length. Which is not what you're after - you want the actual length of the string ).
So - since you're already using std::string, why not use std::vector? Your code would look a lot friendlier :-)
If I take the first couple of lines as your desired output ( sorry, the code you posted is very hard to decipher, and I don't think it compiles either, so I'm ignoring it ;-) )
Would something like this work better for you?
#include <iostream>
#include <vector>
#include <string>
typedef struct node
{
std::string info;
std::vector<struct node*> children;
}Node;
Node * enqueue(std::string str)
{
Node * root;
root = new Node();
root->info = str;
for (int x = 0; x < str.length(); x++)
{
Node * temp = new Node();
temp->info = str[x];
root->children.push_back(temp);
}
return root;
}
int main()
{
Node * myRoot = enqueue("ABCD");
std::cout << myRoot->info << "\n";
for( int i = 0; i < myRoot->children.size(); i++)
{
std::cout << myRoot->children[i]->info << ", ";
}
char c;
std::cin >> c;
return 0;
}
Your code seems not full.
At least the line
p=new node[sizeof(str.length())];
seems wrong.
I guess enqueue should be something similar to the following:
struct node
{
string info;
struct node *next; // [] - is not necessary here
}*root,*child;
string str, goal;
int dept=0,bnod=0,cl,z=0;
void enqueue(string n)
{
node *p, *temp;
p = new node;
p->next = new node[str.length()];
p->info=n;
for (int x=0;x<str.length();x++)
{
p->next[x] = new node;
p->next[x]->next = 0;
p->next[x]->info = str[x];
}
if(root==NULL)
{
root=p;
child=p;
}
}
Please provide more info to give a more correct answer

singly linked chain printing c++

I am trying to pick my chain in the format {1,2,3,4,etc}. You can find the header file below which will have the layout of the nodes. I am just confused on how I should go about cycling through my list to print out Item.
Any guidance would be greatly appreciated!
set.h
using namespace std;
#include <iostream>
class Set
{
private:
struct Node
{
int Item; // User data item
Node * Succ; // Link to the node's successor
};
unsigned Num; // Current count of items in the set
Node * Head; // Link to the head of the chain
public:
// Return information about the set
//
bool is_empty() const { return Num == 0; }
unsigned size() const { return Num; }
// Initialize the set to empty
//
Set();
// Insert a specified item into the set, if possible
//
bool insert( int );
// Display the set
//
void display( ostream& ) const;
};
Here are two recommendations: 1) Sort the list first, then print all nodes; 2) Create another list (indices) to the data and sort those links (don't need data in those nodes).
Sorting List First
An often used technique is to order the nodes in the order you want them printed. This should involve changing the link fields.
Next, start at the head node and print each node in the list (or the data of each node in the list).
Using an Index list
Create another linked list without the data fields. The links in this list point to the data fields in the original list. Order the new list in the order you want the nodes printed.
This technique preserves the order of creation of the first list and allows different ordering schemes.
Changing Links
Since you're writing your own Linked List, the changing of the links is left as an exercise as I'm not getting paid to write your code. There are many examples on SO as well as the web for sorting and traversing linked lists.
You just want to do something like this:
void Set::display(ostream &out) const {
for(int i=0; i<Num; i++) {
out << Pool[i] << " ";
}
out << endl;
}
An ostream behaves as cout would.
It's hard to get your question. If you want to print the array to screen you should consider writing a display() like:
#include <iostream>
#include <iterator>
void Set::display() const {
ostream_iterator<int> out_it (cout," ");
copy(Pool,Pool+Num,out_it);
cout << endl;
}
or if you want to write to a ostream& (as it is pointed out in the answer by #alestanis)
#include <iostream>
#include <iterator>
void Set::display(ostream &out) const {
ostream_iterator<int> out_it (out," ");
copy(Pool,Pool+Num,out_it);
out << endl;
}
Without testing, I'd do something like this. (Assumes the last node has Succ set to NULL, as I would recommend it does.)
void LoopList(struct Node *head)
{
for (struct Node *p = head; p != null; p = p->Succ)
{
// Do whatever with this node
Print(p);
}
}
I think I was over thinking it. Anyway here is what I ended up doing. Now I just need to add some formatting for the commas and im all set.
Node * Temp;
Temp = new (nothrow) Node;
Temp = Head;
out << "{";
while(Temp->Succ)
{
out << Temp->Item;
Temp = Temp->Succ;
}
out << '}' << endl;
Suppose your list is cyclical, you can use this:
struct Node *n = begin;
if (n != NULL) {
//do something on it
...
for (n = begin->Succ; n != begin; n = n->Succ) {
}
}
or
struct Node *n = begin;
if (n != NULL) {
do {
//do something
...
n = n->Succ;
} while (n != begin)
}

How to add up int pointer values in a linked list in C++?

I've been working at this homework assignment for awhile and I can't figure out what I'm doing wrong. How my program is suppose to work:
User enters as many positive numbers as they so desire,
Numbers are in a linked list,
Numbers entered should be added up,
Divide by the amount of numbers entered,
Resulting in the average,
However, it's not working out as I had intended and I've been playing with this for over 3 hours now. I'd contact my teacher but she hasn't responded to my last message still and I need assistance right away. Thanks in advance.
Note: I need to traverse the list to add up all the entered numbers and count the number of nodes.
#include <iostream>
using namespace std;
int num, total, num_entries = 1;
struct number_node
{
int number;
number_node *next;
};
number_node *head_ptr;
number_node *current_ptr;
int get_number_data(int &number);
void add_node(int &number);
void move_current_to_end();
void display_avg();
void delete_list();
int main()
{
if(get_number_data(num))
{
head_ptr = new number_node;
head_ptr->number = num;
head_ptr->next = NULL;
while(get_number_data(num))
{
add_node(num);
}
display_avg();
delete_list();
}
system("pause");
return 0;
}
int get_number_data(int &number)
{
int keep_data = 1;
cout << "Enter a positive number (Enter a negative number to stop): ";
cin >> num;
if(num < 0)
{
keep_data = 0;
}
return(keep_data);
}
void add_node(int &number)
{
number_node *new_rec_ptr;
new_rec_ptr = new number_node;
new_rec_ptr->number = num;
new_rec_ptr->next = NULL;
move_current_to_end();
current_ptr->next = new_rec_ptr;
}
void move_current_to_end()
{
current_ptr = head_ptr;
num_entries++;
while(current_ptr->next != NULL)
{
current_ptr = current_ptr->next;
total = current_ptr->number + total;
}
}
void display_avg()
{
current_ptr = head_ptr;
cout << "Average = " << total / num_entries << endl;
}
void delete_list()
{
number_node *temp_ptr;
current_ptr = head_ptr;
do
{
temp_ptr = current_ptr->next;
delete current_ptr;
current_ptr = temp_ptr;
}
while(temp_ptr != NULL);
}
Right now you're mixing your data structure (linked list) with what you intend to use it for. Consider splitting your logic into:
Your I/O code.
The linked list implementation.
A function that takes a linked list, and computes the average.
You've got a lot of other stuff there and you didn't say what your code does, but I'd do something like this (untested):
int count = 0;
int total = 0;
for (ptr = head_ptr; ptr != NULL; ptr = ptr->next)
{
total += ptr->number;
count++;
}
I know this won't help you with your homework, but here is a C++ STL program that satisfies your requirements:
As many inputs as the user desires
Numbers are stored in a linked list
Numbers are added up
Calculates and displays average
Good luck with your class.
#include <list>
#include <iterator>
#include <iostream>
#include <algorithm>
#include <numeric>
int main()
{
std::list<double> l;
std::copy(std::istream_iterator<double>(std::cin),
std::istream_iterator<double>(),
std::insert_iterator<std::list<double> >(l, l.begin()));
size_t size = l.size();
if(size)
std::cout << std::accumulate(l.begin(), l.end(), 0.0) / l.size()
<< std::endl;
}
~
Apologies: would have attached a comment to ask this introductory question. But apparently you need a higher rep than i currently have to do so.
#Brandon. Can i get you to clearly state that it is these functions:
int get_number_data(int &number)
void add_node(int &number)
void move_current_to_end()
void display_avg()
and only these that you are allowed to use? (And i quote you: "I just have to have it figure out the total and and # of nodes using those functions"
If so. Why? Have they been specified by your lecturer?