No errors, but output is not right. Pointer issue possibly - c++

Im reading strings from a file and inserting them into a LinkedList in alphabetical order (C++). I have made the node and list classes but something is wrong with them. I have done this in Java and it works 100% without any problems. This leads me to believe that I must have messed up with pointers somewhere. This is also only the second time I use the '->' symbol. So I may have used it erroneously somewhere. Some helpful tips are appreciated. Thanks in advance.
//NODE CLASS
#include <string>
#include <iostream>
using namespace std;
class Node {
string word;
int count;
Node* next;
public:
Node (string aWord) {
word = aWord;
count = 1;
}
Node (string aWord, Node* theNext) {
word = aWord;
next = theNext;
}
void increaseCount() {
count++;
}
string getWord() {
return word;
}
int getCount() {
return count;
}
Node* getNext() {
return next;
}
void setNext(Node* theNext) {
next = theNext;
}
};
//LIST CLASS
#include<iostream>
using namespace std;
class LinkedList {
Node* head;
public:
LinkedList() {
head = new Node(" ");
}
void insert(string word) {
Node* temp = head;
Node* previous = head;
while (temp != NULL && temp->getWord() < word) {
previous = temp;
temp = temp->getNext();
}
if (temp == NULL) {
Node* node= new Node(word);
previous-> setNext(node);
} else {
if (temp-> getWord() == word) {
temp->increaseCount();
} else if (temp->getWord() > word) {
Node* node = new Node(word, temp);
previous->setNext(node);
}
}
}
void print() {
Node* temp = head->getNext();
while (temp != NULL) {
cout<< temp;
temp=temp->getNext();
}
}
};
//MAIN
#include <iostream>
#include <iostream>
#include <fstream>
#include "Node.h"
#include "LinkedList.h"
using namespace std;
int main(int argc, const char * argv[]) {
ifstream inFile("WordsStatisticData1.txt");
if (!inFile.is_open())
cout<< "Could not open the file"<< endl;
else {
string readData;
LinkedList list = *new LinkedList(); //Probably a problem here
while (inFile >> readData) {
list.insert(readData);
inFile.close();
list.print();
}
}
}
I may be declaring things totally wrong within the main as well.
My output looks like an address '0x' with random characters.

You're printing out temp where temp is a Node*. A pointer is just the address of an object, hence why you're getting an address in your output.
Seems like you want to get the string that the Node contains. If so, you want:
cout << temp->getWord();
Another problem you have is that you close your file and print the list inside the loop, which means it'll happen right after the first word has been read. You probably mean to do this after the loop, so all of the words in the file can be read.
You also have problem with the line you marked as such. Using the new keyword will dynamically allocate an object. These objects need to be later deleted with delete. However, you dereference the dynamically allocated object (with *) and copy it, losing any reference to the dynamically allocated object - this is a classic memory leak. The dynamic allocation here is completely unnecessary. Just do:
LinkedList list;

Related

Root node should have an assigned node, but remains NULL. Why can't I assign a node to my root?

I'm writing a binary tree in object-oriented format. I've had experience with binary trees before, but it's been a while since I've touched on this. My problem is that I'm unable to assign a node to my root. Every time I check in debugging mode, the root remains NULL. While this is happening, the cur node contains all the information it's assigned.
I've tried making my root private and changing this->root = NULL; to root-> = NULL;. I've also tried making all of my functions public, but it didn't make a difference. I tried declaring root's children to NULL values and name to an empty string as well.
main.cpp
#include <iostream>
#include <string>
#include <fstream>
#include "Friends.h"
using namespace std;
int main() {
string line;
ifstream file;
file.open("friends.txt");
Friends f;
while (getline(file, line)) {
f.insert(f.root, line);
}
f.print(f.root);
system("pause");
return 0;
}
Friends.cpp
#include "Friends.h"
#include <iostream>
#include <string>
using namespace std;
Friends::Friends() {
this->root = NULL;
}
Friends::node* Friends::createNode(string& val) {
node* newNode = new node();
newNode->left = NULL;
newNode->right = NULL;
newNode->name = val;
return newNode;
}
Friends::node* Friends::insert(node* cur, string& val) {
if (!cur) {
cur = createNode(val);
}
else if (val < cur->name) {
insert(cur->left, val);
return cur;
}
else if (val > cur->name) {
insert(cur->right, val);
return cur;
}
return NULL;
}
void Friends::print(node* cur) {
if (!cur) {
return;
}
print(cur->left);
cout << cur->name << endl;
print(cur->right);
}
Friends.h
#ifndef FRIENDS_H
#define FRIENDS_H
#include <string>
using namespace std;
class Friends {
private:
struct node {
string name;
node* left;
node* right;
};
public:
node* root;
node* insert(node* cur, string&);
void print(node* cur);
Friends();
node* createNode(string&);
};
#endif
The root node should have a node, but has keeps showing up as a NULL value. It doesn't run with any errors either. It just remains as NULL.
change from:
node* insert(node* cur, string&);
to :
node* insert(node* &cur, string&);
should fix
Of course the implementation header should also be changed

Why does this code crash using pointers in map c++ in this implementation of Trie?

#include <iostream>
#include <vector>
#include <map>
#include <utility>
#include <iterator>
using namespace std;
class Node
{
public:
map<char,Node*> characters;
bool endOfWord = false;
Node()
{
}
Node(bool endOfWordBool)
{
this->endOfWord = endOfWordBool;
}
};
class Trie
{
public:
Node* root = nullptr;
Trie()
{
this->root = new Node();
}
This function is the problem here.
Using next node that i set in each iteration crashes does the map stl doesn't support having pointers to object inside?
void insertWord(string word)
{
Node* currentNode = this->root;
for(unsigned int i = 0; i < word.length(); i++)
{
/// character is not in the map
if(currentNode->characters.find(word[i]) !=
currentNode->characters.end())
{
cout << "before create" << endl;
Node* nextNode = new Node();
currentNode->characters.insert(pair<char,Node*>(word[i],
nextNode));
currentNode = currentNode->characters.find(word[i])->second;
}
/// character is in the map
else
{
currentNode = currentNode->characters.find(word[i])->second;
}
}
currentNode->endOfWord = true;
}
};
int main()
{
Trie* t = new Trie();
string s = "ahmed";
t->insertWord(s);
return 0;
}
It crashes in the insertion using the set next Node. any Help? And is it a better convention to use pointers in this case or to put the object in the map?
The issue is that your code does the wrong comparison to see if the element in the map exists.
This:
if (currentNode->characters.find(word[i]) != currentNode->characters.end())
should be:
if (currentNode->characters.find(word[i]) == currentNode->characters.end())
By using the wrong comparison, you wind up using an uninitialized pointer.
This also demonstrates that comments can lie what the code does -- the only thing that is the truth is the code. I'm referring to this comment right before the incorrect code:
/// character is not in the map
and of course the code does not determine if the character is not in the map. It actually tests if the character is in the map.

Find all matching nodes in linked list c++ [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm writing a function to find all occurrences of a node in a linked list, the function will return the number of occurrences to the main function which will then display those occurrences. The program does compile but the it just freezes and nothing seems to happen when I enter the correct name to look for, if I enter the wrong name, which is not in the list, the findall function returns 0 and the rest of the program works fine. Please take a look.
main.cpp
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
#include "List.h"
void extra(list &);
/***********************************
* Main
* Test function - DO NOT CHANGE
***********************************/
void main()
{
list a;
extra(a);
}
/***********************************
* Extra Credit
* Test function - DO NOT CHANGE
***********************************/
void extra(list &a)
{ int i,n;
node_ptr map[4];
string first,last;
// Find node
cout << endl;
cout << "Enter First and Last name: ";
cin >> first >> last;
n = a.findall(first,last,map,4);
// Display forwards
cout << endl;
cout << "Find List\n--------------\n";
for (i = 0; i < n; i++)
{
map[i]->put(cout);
}
}
List.h
#include "Node.h"
#include <iostream>
#include <string>
using namespace std;
class list
{ public:
list(); // Empty constructor
~list(); // Destructor
int findall(string, string, node_ptr*, int);
node *find(string, string); // Locate a note
private:
node *head;
};
Node.h
#include <iostream>
#include <string>
using namespace std;
class list;
class node
{ friend list;
public:
node(); // Null constructor
~node(); // Destructor
void put(ostream &out); // Put
private:
string first,last;
int age;
node *next;
};
typedef node * node_ptr;
List.cpp
#include "List.h"
#include <iostream>
#include <string>
using namespace std;
/**
* Empty Constructor
*
*/
list::list()
{
head = nullptr;
}
/**
* Destructor Constructor
*
*/
list::~list()
{ if (head == nullptr) return;
node *p = head, *t;
while (p)
{
t = p;
p = p->next;
delete t;
}
head = nullptr;
}
/**
* Locate node
*
*/
node *list::find(string last, string first)
{
node *temp = head;
while (temp)
{
if (temp->first == first && temp->last == last) return temp;
temp = temp->next;
}
return nullptr;
}
/**
* Find all.
*
*/
int list::findall(string first, string last, node_ptr* map, int n)
{
int ans;
ans = 0;
*map = find(first, last);
while (*map != NULL)
{
ans++;
*map = (*map)->next;
*map = find(first, last);
}
return ans;
}
Node.cpp
#include "Node.h"
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
/**
* Empty Constructor
*
*/
node::node()
{
last = "";
first = "";
age = 0;
next = nullptr;
}
/**
* Destructor
*
*/
node::~node()
{ if (next != nullptr) next = nullptr;
}
/**
* Put
*
*/
void node::put(ostream &out)
{ out << setw(14) << left << last << setw(14) << first << setw(10) << age << endl;
}
I really appreciate your help. Thank you.
findall() freezes because it gets stuck in an endless loop.
If no matching node is found, the first call to find() returns nullptr and findall() exits.
But if a matching node is found, a loop is entered, calling find() to search the entire list all over again from the beginning. That will find the same node as before. Then you call find() again, and again, and so on.
To solve this issue, if find() returns a matching node, you need to pass the next node in the following call to find() so it can start searching where the previous search left off. Repeat until you reach the end of the list.
class list
{ public:
...
int findall(string first, string last, node_ptr *map, int n);
node_ptr find(string first, string last, node_ptr start = nullptr); // Locate a note
...
};
node_ptr list::find(string last, string first, node_ptr start)
{
node_ptr temp = (start) ? start : head;
while (temp)
{
if ((temp->first == first) && (temp->last == last)) break;
temp = temp->next;
}
return temp;
}
int list::findall(string first, string last, node_ptr* map, int n)
{
int ans = 0;
node_ptr temp = nullptr;
while (ans < n)
{
temp = find(first, last, temp);
if (!temp) break;
*map++ = temp;
++ans;
temp = temp->next;
}
return ans;
}
Update: if you are not able to change the signature of find() then you will have to re-write findall() to duplicate what find() does:
class list
{ public:
...
int findall(string first, string last, node_ptr *map, int n);
node_ptr find(string first, string last); // Locate a node
...
};
node_ptr list::find(string last, string first)
{
node_ptr temp = head;
while (temp)
{
if ((temp->first == first) && (temp->last == last)) break;
temp = temp->next;
}
return temp;
}
int list::findall(string first, string last, node_ptr* map, int n)
{
int ans = 0;
node_ptr temp = head;
while (ans < n)
{
while (temp)
{
if ((temp->first == first) && (temp->last == last)) break;
temp = temp->next;
}
if (!temp) break;
*map++ = temp;
++ans;
temp = temp->next;
}
return ans;
}

C++ unhandled exception. 0xC0000005: Access violation reading location 0xccccccd0

I have been trying to work through this for the past couple of hours by going through my call stack, and have still yet to figure out what is going on!
My Sequence Database that basically gathers the info needed from a file, then calls on my Linked List class to create a new node with the gathered info, and put that node at the end of the Linked List:
Header:
#ifndef SEQUENCE_H
#define SEQUENCE_H
#include "DNA.h"
#include "DNAList.h"
class SequenceDatabase
{
public:
//Default Constructors
SequenceDatabase();
//Methods
void importEntries(string);
private:
DNAList list;
};
#endif
Source:
#include "SequenceDatabase.h"
#include "DNA.h"
#include "DNAList.h"
#include <fstream>
using namespace std;
SequenceDatabase::SequenceDatabase() //Default Constructor.
{
DNA object;
DNAList list;
}
void SequenceDatabase::importEntries(string name)
{
DNA* item;
ifstream file;
file.open(name);
if(!file.is_open())
{
cout << "Error opening file!" << endl;
exit(1);
}
char letter;
string label, sequence;
int ID, length, index;
file >> letter;
if(letter == 'D' || letter == 'd')
{
file >> label >> ID >> sequence >> length >> index;
DNA object(label,ID,sequence,length,index);
item = &object;
DNAList list(item);
}
}
My Linked List Header file:
class DNAList
{
public:
//Constructors
DNAList();
DNAList(DNA* newDNA);
//Linked List Functions
void push_back(DNA* newDNA);
DNA* findID(int ID);
void obliterate(int ID);
//DNANode struct for Linked List
struct DNANode
{
DNA* data;
DNANode* next;
DNANode* prev;
};
private:
DNANode* head;
typedef DNANode * ptr;
};
#endif
My Linked List class source file:
#include "DNAList.h"
#include "SequenceDatabase.h"
#include "DNA.h"
#include <iostream>
using namespace std;
DNAList::DNAList()
{
head = NULL;
}
DNAList::DNAList(DNA* newDNA)
{
cout <<"In DNA list second constructor" << endl;
ptr cur;
if(head == NULL)
{
ptr newNode = new DNANode;
cur = newNode;
cur -> data= newDNA;
head = cur;
cur -> prev = head;
cur -> next = NULL;
}
else
{
push_back(newDNA);
}
}
void DNAList::push_back(DNA* newDNA)
{
ptr cur;
ptr last;
cout << "Note: Adding " << newDNA -> getID() << " ..." << endl;
ptr newNode = new DNANode;
cur = head;
while(cur != NULL)
{
last = cur;
cur = cur -> next; //ERROR IS HAPPENING AT THIS LINE.
}
newNode -> data = newDNA;
newNode -> prev = last;
newNode -> next = NULL;
cur = newNode;
}
Now, I am new to using classes to contain my linked lists, so I am not sure if my node struct should be in public or private memory for my Linked List class, and also if my constructors are defined the way they should be. The Node struct is basically a pointer to the actual data that is in a header file called DNA with additional pointers to the struct for my next and previous Nodes so that the data is never messed with, but just pointed to.
The error is being stuck on the line right in the middle of my push_back function in my Linked List source file. I labeled it appropriately. Please can someone share some insight on what I am doing wrong here? Thanks!
My main file:
#include <iostream>
using namespace std;
#include "sequenceDatabase.h"
int main(){ //int argc, char* argv[]){
string commandsFileName;
commandsFileName = "lab1-commands-short.tab"; // for initial development
//commandsFileName = "lab1-commands.tab";
// commandsFileName = "lab1-commands-test.tab"; // for testing & grading
SequenceDatabase entries;
cout << "Importing " << commandsFileName << endl;
entries.importEntries(commandsFileName);
return 0;
}
if (...)
{
DNA object(label, ID, sequence, length, index);
item = &object;
DNAList list(item);
}
object is a locally-scoped object, meaning it is destroyed at the ending brace of the block. You're setting item to point to that local object and sending if off to the constructor of DNAList. The problem with that is if you try to access object after it has been destroyed, your program will no longer be in a valid state. This is because once your object is destroyed, the object that pointed to it will be left as a dangling pointer. Things like accessing a dangling pointer is known as Undefined Behavior.
But that's not where your UB comes from (yet). The real problem is in your DNAList constructor:
if (head == NULL)
{
// ...
}
else
{
push_back(newDNA);
}
head is an uninitialized pointer. Primitive objects (like int, char, char*) that are declared but not defined are uninitialized and thus have an indeterminate value. Testing objects in this state as if they had a value is also Undefined Behavior.
Note that UB can still appear to make your code work properly. But it can also do other nasty things that make no logical sense in your program.
head has the value of whatever was stored in the stack at that moment, which probably wasn't 0. So the condition fails and push_back() is invoked.
Then you do cur->next inside the while loop which dereferences an uninitialized pointer, finally causing an exception to be thrown.
That particular runtime error could be avoided by setting head to NULL inside the constructor body of DNAList and dynamically allocating object (so that it exists beyond the scope of the if statement, but there are still a few more things that are not right in your program as specified in the comments.

I am getting the error "invalid null pointer"

I want to read in student names from a file and insert them into my linked-list, but I am having this problem with an error box. The error reads "Expression: Invalid Null Pointer."
I've googled with no such luck. I think I have an idea where I've went wrong, but I don't know how to fix it.
If you could help, that would be great!
Here is my code:
P.S I'm not nearly done so my code might be incomplete, I'm just trying to weed out all my errors now so I don't have triple my errors at the end.
LList.h
#include <iostream>
#include <iomanip>
#include <string>
#ifndef LLIST_H
#define LLIST_H
typedef int ElementType;
class LList
{
public:
LList();
~LList();
void insert(std::string new_data);
void display();
void remove(std::string delete_data);
private:
class Node
{
public:
std::string data;
Node *next;
Node(std::string data_value = NULL);
};
Node *head;
int mySize;
};
#endif LLIST_H
LList.cpp
#include <iomanip>
#include <iostream>
#include <string>
#include "LList.h"
using namespace std;
LList::Node::Node (string data_value)
{
this -> data = data_value;
this -> next = NULL;
}
LList::LList()
{
this -> head = new Node(0);
mySize = 0;
string data = "";
}
LList::~LList()
{
delete this -> head;
}
void LList::insert(string new_data)
{
Node *tempHolder;
tempHolder = this->head;
while (tempHolder->next != NULL)
tempHolder = tempHolder -> next;
Node *newNode = new Node(new_data);
tempHolder ->next = newNode;
this->mySize++;
}
void LList::display()
{
Node *temp;
temp = head->next;
while(temp -> next != NULL)
{
cout << temp -> data << endl;
temp = temp -> next ;
}
}
void LList::remove(string delete_data)
{
Node *tempHolder;
tempHolder = head;
while (tempHolder->next != NULL )
{
if (tempHolder->next->data == delete_data)
{
Node *delete_ptr = tempHolder->next;
tempHolder->next = tempHolder->next->next;
delete delete_ptr;
mySize-- ;
break;
} else
tempHolder = tempHolder->next;
}
}
Main.cpp
#include <iostream>
#include <iomanip>
#include <string>
#include "LList.h"
#include <fstream>
using namespace std;
int main()
{
LList student;
ifstream infile;
char readLine[500];
infile.open ("names.txt");
if(infile.is_open())
{
while (!infile.eof())
{
infile.getline(readLine,sizeof(readLine)); // read a line from file
student.insert(readLine);
}
}
else
{
cout << "Can't open file!" << endl;
}
}
I found my problem.
In:
LList::LList()
{
this -> head = new Node(0);
mySize = 0;
string data = "";
}
Node(0);
is calling my
LList::Node::Node (string data_value)
{
this -> data = data_value;
this -> next = NULL;
}
which is initialized as a string.
I changed
Node(0);
to
Node("");
and it worked flawlessly.
I wonder could you give the reference where you read that you may to write?
Node(std::string data_value = NULL);
Class std::string has no constructor that converts NULL to an object of type std::string.
it would be much better to declare the constructor without a default argument
Node( std::string data_value );
There is no any sense to create a node without data.
In fact there is no any need to declare a constructor of Node. It could be used as an aggregate.
Also change the constructor of LList as
LList::LList() : head( 0 ), mySize( 0 ){}
Also the destructor is invalied
LList::~LList()
{
delete this -> head;
}
You have to delete not only head but all nodes in the LList.
Also nodes in a single linked list are inserted in the beginning of the list that is before the head.
I would write method insert the following way provided that the constructor of Node is removed bacause it is not needed.
void LList::insert( const std::string &new_data )
{
head = new Node { new_data, head };
}
If your compiler does not support the initializer list then you indeed need to define constructor in class Node.
Node( const std::string &data_value, next_node = NULL );
In this case method insert will look as
void LList::insert( const std::string &new_data )
{
head = new Node( new_data, head );
}