How do you search for a specific string in a linked list and return that value? - c++

I have a program that takes in input with 5 parameters. The inputs are video title, url, comment, length, and rating. Then sorts them based on title. The user will need to specify insert (to enter the video information), lookup (look up a video by title and print ONLY that video and its information associated with it), or print (just simply print everything).
for example
input:
insert
Arthur Benjamin: Lightning calculation and other "Mathemagic"
http://www.youtube.com/watch?v=M4vqr3_ROIk
Hard to believe.
15.25
4
lookup
Arthur Benjamin: Lightning calculation and other "Mathemagic"
output:
Arthur Benjamin: Lightning calculation and other "Mathemagic" , http://www.youtube.com/watch?v=M4vqr3_ROIk, Hard to believe., 15.25, 4
my problem is dealing with lookup in main
if(user == "lookup")
{
getline(cin, title);
if(vlistObj -> lookup(videoObj))
{
vlistObj->print();
}
}
and also lookup in my linked list
bool Vlist::lookup(Video *other)
{
Node *node = m_head;
return node->m_next -> m_video->GetTitle() == other-> GetTitle();
}
I am honestly very lost on how to make lookup search for a specific title (assuming lots of video title/info has been given) and only print what I ask (assuming it's in the list).
Here is the complete code:
#include <iostream>
#include <stdlib.h>
#include <cstring>
using namespace std;
class Video {
public:
Video(string video_title, string video_link, string video_comment, double video_length, int video_number);
void print();
const string& GetTitle() const { return title; }
private:
std::string title;
string link;
string comment;
double length;
int rating;
};
Video::Video(string video_title, string video_link, string video_comment, double video_length, int video_number)
: title(video_title), link(video_link), comment(video_comment), length(video_length), rating(video_number)
{
}
void Video::print(){
cout << title << ", " << link << ", " << comment << ", " << length << ", " << rating << endl;
}
class Vlist {
public:
Vlist() {m_head = nullptr; }
bool lookup(Video *other);
void Insert(Video *video);
void print();
private:
class Node {
public:
Node(Video *video, Node *next) {m_video = video; m_next = next; }
Video *m_video;
Node *m_next;
};
Node *m_head;
};
void Vlist::Insert(Video* video)
{
if (m_head == NULL || m_head->m_video -> GetTitle() > video->GetTitle())
{
m_head = new Node(video, m_head);
}
else
{
Node *node = m_head;
while (node->m_next != NULL && node->m_next -> m_video->GetTitle() < video->GetTitle())
{
node = node->m_next;
}
node->m_next = new Node(video, node->m_next);
}
}
bool Vlist::lookup(Video *other)
{
Node *node = m_head;
return node->m_next -> m_video->GetTitle() == other-> GetTitle();
}
void Vlist::print()
{
Video *video;
Node *node = m_head;
while(node != NULL)
{
node -> m_video-> Video::print();
node = node->m_next;
}
}
int main()
{
string sort_type, url, comment, title, user;
int rating;
double length;
int initial = 0, last = 0, number;
Vlist *vlistObj= new Vlist();
Video *videoObj;
while (getline(cin,user)) {
if(user == "insert")
{
getline(cin,title);
getline(cin, url);
getline(cin, comment);
cin >> length;
cin >> rating;
cin.ignore();
videoObj = new Video(title,url, comment, length, rating);
vlistObj->Insert(videoObj);
}
if(user == "lookup")
{
getline(cin, title);
if(vlistObj -> lookup(videoObj))
{
vlistObj->print();
}
}
if(user == "print")
{
vlistObj->print();
}
}
}
Also I do want to note that I am receiving a segmentation fault. But I do know that it is because of my code in lookup. The program runs and output correctly if I do not type lookup

Error is in the Vlist::lookup function, where the current node pointer points to m_next which then points to m_video: m_next is not required, m_head should point directly to m_video.
Here below the complete working code, I also changed something here and there to eliminate all warnings from my compiler
#include <iostream>
#include <stdlib.h>
#include <cstring>
using namespace std;
class Video {
public:
Video(string video_title, string video_link, string video_comment, double video_length, int video_number);
void print();
const string& GetTitle() const { return title; }
private:
string title;
string link;
string comment;
double length;
int rating;
};
Video::Video(string video_title, string video_link, string video_comment, double video_length, int video_number)
: title(video_title), link(video_link), comment(video_comment), length(video_length), rating(video_number)
{
}
void Video::print(){
cout << title << ", " << link << ", " << comment << ", " << length << ", " << rating << endl;
}
class Vlist {
public:
Vlist():m_head(nullptr) {} // init_list
bool lookup(const string& title); // gets user input directly
void Insert(Video *video);
void print();
Video* get(const string& title); // new:returns pointer in list with given title
private:
class Node {
public:
Node(Video *video, Node *next):m_video(video), m_next(next) {} // init_list
Video *m_video;
Node *m_next;
} *m_head; // declared directly together with class definition
};
void Vlist::Insert(Video* video)
{
if (m_head == NULL || m_head->m_video -> GetTitle() > video->GetTitle())
{
m_head = new Node(video, m_head);
}
else
{
Node *node = m_head;
while (node->m_next != NULL && node->m_next -> m_video->GetTitle() < video->GetTitle())
{
node = node->m_next;
}
node->m_next = new Node(video, node->m_next);
}
}
bool Vlist::lookup(const string& title)
{
Node *node = m_head;
while (node->m_next != NULL && node-> m_video->GetTitle() != title)
{
node = node->m_next;
}
return node-> m_video->GetTitle() == title; // there was one pointer too many here
}
void Vlist::print()
{
Node *node = m_head;
while(node != NULL)
{
node -> m_video-> Video::print();
node = node->m_next;
}
}
Video* Vlist::get(const string& title) // returns required item from list
{
Node *node = m_head;
while (node != NULL) {
if (node->m_video->GetTitle() == title)
return node->m_video;
node = node->m_next;
}
return nullptr;
}
int main()
{
string sort_type, url, comment, title, user;
int rating;
double length;
Vlist *vlistObj= new Vlist;
Video *videoObj;
while (getline(cin,user)) {
if(user == "insert")
{
getline(cin,title);
getline(cin, url);
getline(cin, comment);
cin >> length;
cin >> rating;
cin.ignore();
videoObj = new Video(title, url, comment, length, rating);
vlistObj->Insert(videoObj);
}
if(user == "lookup") // more than a few changes here
{
getline(cin, title);
if (vlistObj -> lookup(title))
{
videoObj = vlistObj->get(title);
videoObj->print();
} else {
cout << "not found!\n";
}
}
if(user == "print")
{
vlistObj->print();
}
}
}
BIG EDIT
Previous version did not traverse the Vlist correctly.
Now Vlist is properly searched by the lookup command, that thus finally prints the correct Video.

Overview
Before looking at the specific issues, your code shows you are struggling with putting all the pieces together and are, in a sense, guessing and not paying particular attention to every line in your code. You can't code by just "trying things and see if it works", that will just make you old, gray and frustrated. Take the time to know just exactly what your next lines of code needs to do, craft the line, and then craft a test to ensure it succeeds (or make friends with gdb and check there -- you indicated you are using g++)
Examples:
#include <iostream>
#include <limits>
// #include <stdlib.h>
// #include <cstring>
What were stdlib.h and cstring included for? And:
void Vlist::print()
{
// Video *video; /* unused */
and
// int initial = 0, last = 0, number = 0; /* unused */
How is other initialized? If you are passing a pointer to a Video object, that object must at minimum have the title initialized, so GetTitle() returns a meaningful value...
bool Vlist::lookup(Video *other)
{
Node *node = m_head;
return node->m_next -> m_video->GetTitle() == other-> GetTitle();
}
That doesn't really make much sense?
Take your time and slow-down, understand what you need to do, and then pick up the keyboard (not the other way around)
Be consistent with your use of syntax. You include std::string in places and then simply string in others relying on using namespace std;. See Why is “using namespace std;” considered bad practice?
Further, under no conditions in C++ is there ever a space surrounding ->. That is an operator that joins an object and its member, with nothing in between.
Specific Issues
It is clear that what you have will not output the Video object that matches a lookup when you are attempting to print a Vlist. (doesn't make much sense to print the entire list in response to finding one title of interest). Your lookup() function cannot return bool, instead it must return a pointer to the node containing the title (if found) or nullptr if not found. That means you must save and validate the return in order to know which Node contains the record you want to print. Within main() that looks like:
else if (user == "lookup") {
if (getline(std::cin, title)) {
videoObj = new Video (title); /* you must construct a new videoObj */
Video *video = nullptr; /* you want a Video* pointer returned */
if ((video = vlistObj->lookup(videoObj))) { /* lookup & assign return */
video->print(); /* output the video, not list */
}
else {
std::cout << "title not found: '" << title << "'.\n";
}
}
}
Now that videoObj points to a Video object that has title initialized, the lookup() function can do it's job -- returning a pointer to the node within the list that contains that title (and all the rest of the information) or returning nullptr if the title isn't found. (note the else indicating to the user that condition)
A rewrite of lookup() that does just that would be:
Video *Vlist::lookup (Video *other)
{
Node *node = m_head;
while (node) { /* iterate over nodes in list looking for title */
if (node->m_video->GetTitle() == other->GetTitle())
return node->m_video; /* return pointer to node if found */
node = node->m_next;
}
return nullptr; /* nullptr if not */
}
(Note: simply passing other as std::string makes more sense, but in case you need a Video object -- this is a minimal way to do it)
There were a litany of other cleanups needed, tweaks to initializations, syntax fixes -- removing spaces around ->, etc... that are too numerous to mention. Not to mention to need to ensure you are not leaking memory -- that is left to you (and your properly written destructors) Use valgrind to verify you are freeing all memory before your program exits.
Putting the syntax clean ups and initializations together, you could do something like:
#include <iostream>
#include <limits>
class Video {
public:
Video ( std::string video_title, std::string video_link, std::string video_comment,
double video_length, int video_number );
void print();
const std::string& GetTitle() const { return title; }
private:
std::string title {}, link {}, comment {};
double length;
int rating;
};
Video::Video ( std::string video_title = "",
std::string video_link = "",
std::string video_comment = "",
double video_length = 0, int video_number = 0)
: title(video_title), link(video_link), comment(video_comment),
length(video_length), rating(video_number)
{
}
void Video::print()
{
std::cout << title << ", " << link << ", " << comment << ", " <<
length << ", " << rating << '\n';
}
class Vlist {
public:
Vlist() { m_head = nullptr; }
Video *lookup (Video *other);
void Insert (Video *video);
void print();
private:
class Node {
public:
Node (Video *video = nullptr, Node *next = nullptr) {
m_video = video; m_next = next;
}
Video *m_video;
Node *m_next;
};
Node *m_head;
};
void Vlist::Insert (Video* video)
{
if (m_head == nullptr || m_head->m_video->GetTitle() > video->GetTitle()) {
m_head = new Node (video, m_head);
}
else {
Node *node = m_head;
while (node->m_next != nullptr &&
node->m_next->m_video->GetTitle() < video->GetTitle()) {
node = node->m_next;
}
node->m_next = new Node(video, node->m_next);
}
}
Video *Vlist::lookup (Video *other)
{
Node *node = m_head;
while (node) { /* iterate over nodes in list looking for title */
if (node->m_video->GetTitle() == other->GetTitle())
return node->m_video; /* return pointer to node if found */
node = node->m_next;
}
return nullptr; /* nullptr if not */
}
void Vlist::print()
{
Node *node = m_head;
while (node != nullptr) {
node->m_video->Video::print();
node = node->m_next;
}
}
int main (void) {
std::string sort_type {}, url {}, comment {}, title {}, user {};
int rating = 0;
double length = 0;
Vlist *vlistObj = new Vlist();
Video *videoObj = nullptr;
while (getline(std::cin, user)) {
if (user == "insert") {
if (getline (std::cin, title) &&
getline (std::cin, url) &&
getline (std::cin, comment) &&
std::cin >> length &&
std::cin >> rating) {
std::cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
videoObj = new Video (title, url, comment, length, rating);
vlistObj->Insert(videoObj);
}
}
else if (user == "lookup") {
if (getline(std::cin, title)) {
videoObj = new Video (title); /* you must construct a new videoObj */
Video *video = nullptr; /* you want a Video* pointer returned */
if ((video = vlistObj->lookup(videoObj))) { /* lookup & assign return */
video->print(); /* output the video, not list */
}
else {
std::cout << "title not found: '" << title << "'.\n";
}
}
}
else if (user == "print") {
std::cout << "\nlist content:\n";
vlistObj->print();
}
}
}
Example Input File
To minimally exercise your code you need more than one node in your linked list. What about attempting to lookup a node that does not exist -- validate that code-path?
$ cat dat/ll_video2.txt
insert
Arthur Benjamin: Lightning calculation and other "Mathemagic"
http://www.youtube.com/watch?v=M4vqr3_ROIk
Hard to believe.
15.25
4
insert
Arthur Benjamin: Some Other "Mathemagic"
http://www.youtube.com/watch?v=SomeOther
Hard to swallow.
25.25
7
lookup
Arthur Benjamin: Lightning calculation and other "Mathemagic"
lookup
Arthur Benjamin: Some Other "Mathemagic"
lookup
Mickey & Minnie do Disney
print
Example Use/Output
The results of the three lookups are handled correctly and the list contents print as they should in result to the print command input as the last line of input above:
$ ./bin/ll_video <dat/ll_video2.txt
Arthur Benjamin: Lightning calculation and other "Mathemagic", http://www.youtube.com/watch?v=M4vqr3_ROIk, Hard to believe., 15.25, 4
Arthur Benjamin: Some Other "Mathemagic", http://www.youtube.com/watch?v=SomeOther, Hard to swallow., 25.25, 7
title not found: 'Mickey & Minnie do Disney'.
list content:
Arthur Benjamin: Lightning calculation and other "Mathemagic", http://www.youtube.com/watch?v=M4vqr3_ROIk, Hard to believe., 15.25, 4
Arthur Benjamin: Some Other "Mathemagic", http://www.youtube.com/watch?v=SomeOther, Hard to swallow., 25.25, 7
Look things over and let me know if you have further questions.

Related

LinkedList sorting a-z

Requirements for this function: If the full name (both the first and last name) is not equal to any full name currently in the list then add it and return true. Elements should be added according to their last name. Elements with the same last name should be added according to
their first names. Otherwise, make no change to the list and return false (indicating that the name is already in the list).
//this function add nodes to the list
//return true if fullname isn't in the list. Else return false if fullname is in the list.
//should be added according to last name.
bool OnlineDating::makeMatch(const std::string& firstName, const std::string& lastName, const OnlineType& value)
{
Node* p = head;
//are these nodes already set to firstName and lastName in this function
Node first;
Node last;
Node* temp = nullptr;
//if the list is empty just insert the fullname and value to the list
if (p == nullptr) {
//add values to the empty list
insertToRear(firstName, lastName, value);
return true;
}
else {
// so this loop is to check if fullname is in the list but first sort in alphebetial order
//sure its added in alphebetical order
//traverse the list after knowing where head is
while (p != nullptr) {
//checking to make sure theres at least another node in the list
if (p->next != nullptr) {
//its not going through ig loop?
//these are used to check and alphebetically selected names
if (p->last > p->next->last) {
insertToRear(p->first, p->last, p->value);
p->next = temp;
return true;
}
else if (p->next->last > p->last) {
insertToRear(p->first, p->last, p->value);
p->next = temp;
return true;
}
//check if full name is already in the list
if (p->last == p->next->last) {
insertToRear(p->first, p->last, p->value);
p->next = temp;
return true;
}
else if (p->first > p->next->first) {
insertToRear(p->first, p->last, p->value);
p->next = temp;
return true;
}
else {
//returns false if it passes through these checks
return false;
}
}
p = p->next;
}
}
}
Here is my main.cpp
int main()
{
OnlineDating clippersGonnaClip;
clippersGonnaClip.makeMatch("Kawhi", "Leonard", 2);
clippersGonnaClip.makeMatch("Paul", "George", 13);
clippersGonnaClip.makeMatch("Ivica", "Zubac", 40);
clippersGonnaClip.makeMatch("Reggie", "Jackson", 1);
clippersGonnaClip.makeMatch("Patrick", "Beverley", 21);
for (int n = 0; n < clippersGonnaClip.howManyMatches(); n++) {
string first;
string last;
int val;
clippersGonnaClip.confirmMatch(n, first, last, val);
cout << first << " " << last << " " << val << endl;
}
return 0;
}
honestly, I just want to create a ptr that will point to each node. Check as long as that node isn't pointing to nullptr, and sort the LinkedList in alphabetical order. finally link the nodes together using my *temp. Why won't it let me go through the if statements every time I compile I get a negative number? Every other function works for this program except this makeMatch(...).
Nothing in the requirements says anything about the data types you need to use. In this case using std::set makes most sense.
By providing a comparison operation on persons and a set you can guarantee uniqueness. Like this :
#include <set>
#include <string>
struct person_t
{
std::string name;
std::string last_name;
unsigned int age;
};
bool operator<(const person_t& lhs, const person_t& rhs)
{
if (lhs.last_name == rhs.last_name)
return lhs.name < rhs.name;
return lhs.last_name < rhs.last_name;
}
int main()
{
// set will ensure all persons are unique
std::set<person_t> persons;
persons.insert({ "Kawhi", "Leonard", 2 });
persons.insert({ "Paul", "George", 13 });
persons.insert({ "Ivica", "Zubac", 40 });
persons.insert({ "Reggie", "Jackson", 1 });
persons.insert({ "Patrick", "Beverley", 21 });
}

Store the address of an object inside a node

I'm trying to create an object of a class called Cell and store it in a linked list. I'm sure I could do this with an array, but part of my assignment is that I use a linked list and I didn't think I'd get this many problems. This is currently my node. Right now, I have all these variables stored in the node, but I'd rather create an object(Called "Cell") to store them. Info should be a pointer to an object of type T. Right now, that T should be of type Cell.
template<class T>
struct Node {
T *info;
Node<T> *nodeP;
Node<T> *linkP;
int nodeNumber = 0;
bool purchased = false;
std::string color = " ";
int index = 0;
int max_num = 0;
std::string name = " ";
int price;
};
In here I am creating the node and adding it to a linked list. At the moment I'm just filling in values of the node, but I'm trying to create an object of type Cell and assign it's address to the pointer info. I've tried a couple different ways but keep coming back with errors. I commented them out so you can see what I've tried.
template<class T>
void Board<T>::setCellValue() {
//open file
ifstream inFile;
string line;
inFile.open("CellValues.txt");
//Check for Error
if (inFile.fail()) {
cerr << "File does not exist!";
exit(1);
}
int index = 0, max_num = 0, count = 0, price = 0;
string color, name;
istringstream inStream;
while (getline(inFile, line)) {
inStream.clear();
inStream.str(line);
inStream >> color >> index >> max_num >> name >> price;
//creates node
Node<T> *newNodeP = new Node<T>;
//create pointer, assign pointer to pointer in Node
//Cell<T> *cellPtr = new Cell<T>(count, name, color, index, max_num, price);
//newNode->info= cellPtr;
//creating anonymous object and assigning to the node? I think
newNodeP->info = new Cell<T>(color, index, max_num, name, price);
//weird way I was just experimenting with
newNodeP->info->Cell<T>(count, name, color, index, max_num, price);
//fills node values(this is what I want to handle in the object
newNodeP->color = color;
newNodeP->index = index;
newNodeP->max_num = max_num;
newNodeP->name = name;
newNodeP->nodeNumber += count;
newNodeP->price = price;
newNodeP->linkP = NULL;
if (firstP != NULL)
lastP->linkP = newNodeP;
else
firstP = newNodeP;
lastP = newNodeP;
count++;
}
}
Currently, I have two ways of returning the node landed on. One returns a Node* and sort of works. It returns the pointer to the node, and I can access the values inside that node, but I can't figure out how to store the pointer to that node.
//Find Cell
template<class T>
Node<T>* Board<T>::findCell(int id) {
for (Node<T> *traverseP = firstP; traverseP != NULL; traverseP = traverseP->linkP) {
if (traverseP->nodeNumber == id) {
return traverseP;
}
}
return nullptr;
}
//how I call it in main. it returns an address to that node, but I'm getting errors trying to store that address in a pointer.
cout << "You landed on cell " << gameBoard.findCell(player.getCellNum()) << endl << endl;
Node<T> *ptr = gameboard.findCell(player.getCellNum())->info;
This second way, I think returns the reference to the object in the node, but my earlier problem is stopping me from figuring that out.
//Return Cell
template <class T>
T Board<T>::returnCell(int id) {
for (Node<T> *traverseP = firstP; traverseP != NULL; traverseP = traverseP->linkP) {
if (traverseP->nodeNumber == id) {
return traverseP->info;
}
}
return nullptr;
}
//How i'm calling it in main. I don't really know what it's returning though because it only prints "You landed on " and then nothing else.
cout << "You landed on " << gameBoard.returnCell(player.getCellNum()) << endl;

Reading data from a file into a linked list, and searching for elements in the linked list

I am trying to write code and am taking in data from a file and storing it into a struct and creating a linked list. I don't see any immediate problems with my code but I made a function to check if a zipcode exists within any of the structs in the linked list and it doesn't seem to be working. Here's what the data from the file looks like:
id,price,bedrooms,bathrooms,sqft,yr_built,zipcode
1370804430,543115,2,1,1380,1947,98199
3744000040,518380,4,2.5,2810,2014,98038
3313600266,190000,3,1,1180,1966,98002
EDIT I implemented new code for reading the file into a linked list but my function for finding the zipcode isn't working. When I enter a zipcode I know exists in the file, nothing gets printed.
typedef struct housetype house;
struct housetype{
int id;
int price;
int bedrooms;
double bathrooms;
int sqft;
int year;
int zipcode;
house *next; };
int findzipcode(house* head, int zip){
house* current = head;
while(current != NULL){
if(current->zipcode == zip){
cout << "Zipcode exists" << endl;
return 1;
break;}
current = current->next;
}
return 0;}
int main(){
house *head = NULL;
FILE *houseinfo = NULL;
houseinfo = fopen("house-info-v4.txt", "r");
if (houseinfo == NULL) {
cout << "Error reading file" << endl;
}
else {
int res;
house *last = head;
house h;
do {
res = fscanf(houseinfo, "%d,%d,%d,%lf,%d,%d,%d",
&h.id, &h.price, &h.bedrooms, &h.bathrooms,
&h.sqft, &h.year, &h.zipcode);
if (res > 0) { // <== fscanf successful (if file fits!)
house *n = (house*)malloc(sizeof(house));
memcpy(n, &h, sizeof(house));
n -> next = NULL;
if (last) last->next = n;
if ( ! head) head = n;
last = n;
}
} while (res > 0);
}
int zip;
cout << "Enter a zipcode" << endl;
cin >> zip;
findzipcode(head, zip);}
The code you present will only load the first item, so if you are searching for later items it won't work.
Notice how the code with the fscanf doesn't have a loop.
I think you read only one row from data and made one node for linked list. If you want to make linked list then you have to read all rows from file and create node of each row and link it with loop.
For example
while (1)
read_file
if feof:
break
make_node
add row_info -> node
link_node
Trying to write this code with c++
At least two problems
head remains NULL
only one house is read from the file
Try something like
if (houseinfo == NULL) {
cout << "Error reading file" << endl;
}
else {
int res; // <== fscanf result
house *last = head; // <== last house set (head is still null)
house h; // <== holds values until fscanf check
do {
res = fscanf(houseinfo, "%d,%d,%d,%lf,%d,%d,%d",
&h.id, &h.price, &h.bedrooms, &h.bathrooms,
&h.sqft, &h.year, &h.zipcode);
if (res > 0) { // <== fscanf successful (if file fits!)
house *n = (house*)malloc(sizeof(house)); // c++ cast malloc
memcpy(n, &h, sizeof(house)); // <== copy to allocated house
n -> next = NULL;
if (last) last->next = n; // last next is our n
if ( ! head) head = n; // set head if necessary
last = n; // last house set is n, now
}
} while (res > 0);
}
Explanations are in comments. Basically
loop on fscanf until no more lines in file
read values in local variable h
if fscanf successful, allocate and set n
if we have a last, set its next to our new n
if head not set yet, set it
finally, last points to n to be used at next iteration
First of all select a language. Either C or C++.
There is a problem in your code. The thing is, you have memory leak here and that in one way is the reason for the problem.
Well to say it in detail, you allocate memory and get input and store it in that memory and then you forget about it. You don't forget but yes there is no way you can access it. This is the memory leak. And then you pass a NULL valued pointer to the search function and it returns nothing.
This change will solve the problem,
house *n = malloc(sizeof(house));
head = n; //<----- We are not losing the allocated memory
fscanf(houseinfo, "%d.....
..
Also there is one redundant thing in your code (this is not causing the problem but yes you should know this).
cout << "Zipcode exists" << endl;
return 1;
break; //<--- this is redundant
}
Once a return statement is executed that break will never be executed. Just put the return statement. No use putting the break here.
Another point you didn't free the allocated memory.(Ah! to free you need to keep track of it - which you didn't do here). After you are done working with it you should free it.
findzipcode(head, zip);
free(head);
Also check the return value of malloc. In case it returns NULL take necessary action.
in the following proposed code:
error conditions are checked and acted upon
most of the comments to the question are incorporated
And now, the proposed code:
#include <cstdio>
#include <cstdlib>
#include <errno.h>
struct housetype
{
int id;
int price;
int bedrooms;
double bathrooms;
int sqft;
int year;
int zipcode;
struct housetype *next;
};
typedef struct housetype house;
void findzipcode(house* head, int zip)
{
house* current = head;
while( current )
{
if(current->zipcode == zip)
{
cout << "Zipcode exists" << endl;
return;
}
current = current->next;
}
}
int main( void )
{
house *head = NULL;
FILE *houseinfo = fopen("house-info-v4.txt", "r");
if ( !houseinfo )
{
cerr << "fopen failed due to" << strerror( errno ) << endl;
exit( EXIT_FAILURE );
}
// implied else, fopen successful
int res;
house *last = NULL;
house h;
while( 7 == (res = fscanf(houseinfo, "%d,%d,%d,%lf,%d,%d,%d",
&h.id, &h.price, &h.bedrooms, &h.bathrooms,
&h.sqft, &h.year, &h.zipcode) ) )
house *n = new house;
if( !n )
{
cerr << "malloc failed due to: " << strerror( errno ) << endl;
exit( EXIT_FAILURE );
}
// implied else, malloc successful
memcpy(n, &h, sizeof(house));
n -> next = NULL;
if (last)
last->next = n;
else if ( ! head)
head = n;
last = n;
}
int zip;
cout << "Enter a zipcode" << endl;
cin >> zip;
findzipcode(head, zip);
while( head )
{
house *nextHouse = head->next;
delete head;
head = nextHouse;
}
}
Of course, if you really want to use C++, then suggest using a vector rather than a linked list

Sorting using Linear Linked List in C++

So I'm trying to build a linear linked list that takes info from users and saves the info in two sorted lists by name (alphabetically) and by birthdate. So far I have
struct node{
char* name;
int birthDate;
node *nameNext;
node * dateNext;
};
where each node will have two pointers pointing to the appropriate list. The problem I'm having is how to direct the head pointer node *head. How do I set head when there are two different lists? I'm thinking something like head->nameNext and head->dateNext but that would point to the second node of the lists if it work. Please help! Thanks in advance.
if i got your question right, you're simply looking to sort your list
in two ways (alphabetically and birthdate)
note: i will use bubble sort to simplify the algorithm but you can use better one as you know
#include <iostream>
struct node{
const char* name;
int birthdate;
node*next;
};
struct sort_data{
private:
node *name_root = nullptr; // alphabetically head/root pointer
node *date_root = nullptr; // birthdate head/root pointer
public:
void push(const char*name,int birthdate); // push data;
void sort_by_birth(); // sort the birth linked list
void sort_by_alphabet(); // sort the alphabet linked list
void print_birth(); // print the data of the birth linked list
void print_alph(); // print of the data of the alphabet linked list
};
void sort_data::push(const char*name,int birthdata) {
node*Name = new node; // allocate a node for the alphabet list
node*Date = new node; // allocate a node for the date list
Name->name = Date->name = name;
Name->birthdate = Date->birthdate = birthdata;
Name->next = name_root;
Date->next = date_root;
name_root = Name;
date_root = Date;
}
void sort_data::sort_by_birth() {
node*i = date_root;
node*j;
if(!i) // if i == nullptr
return;
while(i){ // while(i!=nullptr)
j = i->next;
while(j){
if(i->birthdate > j->birthdate){
std::swap(i->birthdate,j->birthdate);
std::swap(i->name,j->name);
}
j = j->next;
}
i = i->next;
}
}
void sort_data::sort_by_alphabet() {
node*i = name_root;
node*j;
if(!i)
return;
while(i){
j = i->next;
while(j){
if(i->name[0] > j->name[0]){
std::swap(i->birthdate,j->birthdate);
std::swap(i->name,j->name);
}
j = j->next;
}
i = i->next;
}
}
void sort_data:: print_birth(){
node*temp = date_root;
while(temp){
std::cout << temp->name << " " << temp->birthdate << std::endl;
temp = temp->next;
}
}
void sort_data::print_alph() {
node*temp = name_root;
while(temp){
std::cout << temp->name << " " << temp->birthdate << std::endl;
temp = temp->next;
}
}
int main(){
sort_data obj;
obj.push("jack",1997);
obj.push("daniel",1981);
obj.push("maria",1995);
obj.push("john",2008);
obj.sort_by_alphabet();
obj.sort_by_birth();
std::cout << "alphabetically : \n" ;
obj.print_alph();
std::cout << "by birthdate : \n";
obj.print_birth();
}
note: because you're using C++ don't use char* to store string literals
use std::string or const char *. as the chars in string literals are const char so you don't want to point on const char with char
if you're using a C++ compiler that support C++11 your compiler should generate a warning about such thing

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