This question already has answers here:
Why does std::getline() skip input after a formatted extraction?
(5 answers)
Closed 6 years ago.
I have to design a program to allow the user to input information for 5 nodes in a doubly linked list and then sort the doubly linked list alphabetically. It skips over allowing the user to input the address, doesn't print any information besides the name ,and doesn't sort the list alphabetically. What am I doing wrong?
#include <iostream>
#include <string>
struct node
{
std::string firstName;
std::string lastName;
std::string address;
long phoneNum;
node *next;
node *prev;
};
bool isEmpty(node *head);
void insertAsFirstElement(node *&head, node *&last, std::string firstName, std::string lastName, std::string address, long phoneNum);
void insert(node *&head, node *&last, std::string firstName, std::string lastName, std::string address, long phoneNum);
void searchFor(node *&last, std::string lastName);
void showList(node *current);
bool isEmpty(node *head)
{
if(head == NULL)
return true;
else
return false;
}
void insertAsFirstElement(node *&head, node *&last, std::string firstName, std::string lastName, std::string address, long phoneNum)
{
node *temp = new node;
temp->firstName = firstName;
temp->lastName = lastName;
temp->address = address;
temp->phoneNum;
temp->next = NULL;
temp->prev = NULL;
head = temp;
last = temp;
}
void insert(node *&head, node *&last, std::string firstName, std::string lastName, std::string address, long phoneNum)
{
if(isEmpty(head))
insertAsFirstElement(head, last, firstName, lastName, address, phoneNum);
else
{
node *temp = new node;
temp->firstName = firstName;
temp->lastName = lastName;
temp->address = address;
temp->phoneNum;
int result = lastName.compare(last->lastName);
if (result < 0)
{
temp->next = head;
head->prev = temp;
temp->prev = NULL;
head = temp;
}
else if ( result > 0)
{
temp->next = NULL;
temp->prev = last;
last->next = temp;
last = temp;
}
}
}
void searchFor(node *&last, std::string findName)
{
node *temp = last;
while (temp != NULL)
{
if (temp->lastName == findName)
{
std::cout << temp->firstName << " " << temp->lastName << " " << temp->address << " " << temp->phoneNum << std::endl;;
}
temp = temp->prev;
}
}
void showList(node *current)
{
if(isEmpty(current))
std::cout << "The list is empty\n";
else
{
std::cout << "The list contains: \n";
while(current != NULL)
{
std::cout << current->firstName << " " << current->lastName << " " << current->address << " " << current->phoneNum << std::endl;
current = current->next;
}
}
}
int main()
{
node *head = NULL;
node *last = NULL;
std::string firstName;
std::string lastName;
std::string address;
long phoneNum;
int count;
count = 5;
while (count > 0)
{
std::cout << "Enter the first name of person #" << count << ":\n";
std::cin >> firstName;
std::cout << "Enter the last name of person #" << count << ":\n";
std::cin >> lastName;
std::cout << "Enter the address of person #" << count << ":\n";
std::getline(std::cin,address);
std::cout << "Enter the phone number of person #" << count << ":\n";
std::cin >> phoneNum;
insert(head, last, firstName, lastName, address, phoneNum);
count = count - 1;
}
showList(head);
std::string findName;
std::cout << "What is the last name of the person you would like to find?\n";
std::cin >> findName;
searchFor(last, findName);
return 0;
}
Your issue is that you are mixing cin >> and getline which is problematic in C++ due to trailing newlines and what not.
Good practice is to always use getline and then use a stringstream to split the line up into tokens. For example, I modified your solution to only use getline and string streams (NOTE: You need to #include <sstream> at the top of your file.
You can read more about the issues with mixing cin >> and getline and also other ways to solve them here.
int main()
{
node *head = NULL;
node *last = NULL;
std::string firstName;
std::string lastName;
std::string address;
std::string phoneNumStr;
long phoneNum;
int count;
count = 5;
while (count > 0)
{
std::cout << "Enter the first name of person #" << count << ":\n";
std::getline(std::cin,firstName); // no use of cin >>
std::cout << "Enter the last name of person #" << count << ":\n";
std::getline(std::cin,lastName); // no use of cin >>
std::cout << "Enter the address of person #" << count << ":\n";
std::getline(std::cin,address);
std::cout << "Enter the phone number of person #" << count << ":\n";
std::getline(std::cin,phoneNumStr);
std::stringstream s(phoneNumStr); // no use of cin. Using stringstream to break up line and extract it into phoneNum
s >> phoneNum;
insert(head, last, firstName, lastName, address, phoneNum);
count = count - 1;
}
showList(head);
std::string findName;
std::cout << "What is the last name of the person you would like to find?\n";
std::cin >> findName;
searchFor(last, findName);
return 0;
}
Related
So I made a doubly linked list which stores a person's first name, last name, address and age and I am currently stuck on making a sorting algorithm for the list. So far I've managed to create 3 functions, one that adds a node to the list, one that deletes a node from the list and one which prints the list.
Here's what I have so far, the struct:
struct Node {
string First_Name;
string Last_Name;
string Address;
int age;
Node* next;
Node* prev;
} *first = 0, * last = 0;
The addToList function:
void addToList()
{
string temp = "Yes";
string First_Name;
string Last_Name;
string Address;
int age;
Node* current = first;
while (temp == "Yes") {
cout << "Enter the persons first name: ";
cin >> First_Name;
cout << "Enter the persons last name: ";
cin >> Last_Name;
cout << "Enter the persons age: ";
cin >> age;
cout << "Enter the persons address: ";
cin >> Address;
cout << "Would you like to add another person? Yes or No";
cin >> temp;
current = new Node;
current->First_Name = First_Name;
current->Last_Name = Last_Name;
current->age = age;
current->Address = Address;
if (last) last->next = current;
else first = current;
current->prev = last;
current->next = 0;
last = current;
}
return;
}
And the print list:
void printList()
{
if (!first)
{
cout << "Nothing is present in the list." << endl;
return;
}
Node* current = first;
while (current)
{
cout << current->First_Name << " " << current->Last_Name << " " << current->age << " " << current->Address << endl;
current = current->next;
}
}
My question is, how would I be able to sort the list alphabetically, I've never done sorting before...
Thank you!!
To use custom sorting for a doubly-linked list, overload operator<:
struct Person
{
std::string first;
std::string last;
std::string address;
unsigned int age;
bool operator<(const Person& p) const
{
bool is_less_than = false;
if (last == p.last)
{
is_less_than = first < p.first;
}
else
{
is_less_than = last < p.last;
}
return is_less_than;
}
};
Now you can use std::list and it will automatically sort by last name, then first. And std::list is a doubly-linked list.
To compare Persons:
Person a;
Person b;
//...
if (a < b)
{
std::cout << "Person A < Person B\n";
}
I am having trouble figuring out how to get my input data into my queue... I am so close to getting this to work right.
I know I am just confused about how things are working. I have used example code and my instructions to come up with a working program that appears to be working correctly (other than not actually putting my input file data into the queue). I bypassed the function I was trying to make for this. In addition to this, I was trying to write a function to remove an employee from the queue (which I think does work), but I am not sure I was able to get it right...
I have not taken a programming class for over 10 years and really would love to get any help in understanding what I am doing and getting that darn data into the queue.
Below is my main driver file. I will provide my header file code if needed. Thanks in advance for any help you can provide on this.
//Program Assignment #3
//Creates Queue as a Linked Structure
#include<iostream>
#include<string>
#include<fstream>
#include"Employee.h"
#include"LinkedQ.h"
using namespace std;
struct Node
{
LinkedQ nodeQ;
Employee EmpNumber;
Employee LastName;
Employee FirstName;
Employee ServiceYears;
};
void loadFile(LinkedQ &);
void addEmp(LinkedQ &);
void delEmp(LinkedQ &);
int main()
{
LinkedQ empList;
int choice;
int numIn, yearsIn;
string LastName;
string FirstName;
LinkedQ empIn;
ifstream input;
input.open("Employee.txt");
while (input)
{
input >> numIn >> LastName >> FirstName >> yearsIn;
if (input)
{
cout << "this is where we load data from the file into the queue\n";
system("pause");
//empIn.Enqueue(numIn, LastName, FirstName, yearsIn);
//empList.addEmp(empIn);
}
}
input.close();
do
{
//display menu
system("cls");
cout << "\t\tMenu: \n"
<< "\t1. Add Employee\n"
<< "\t2. Remove Employee\n"
<< "\t3. Count of Employees\n"
<< "\t4. Quit\n\n";
cout << "Enter your choice and press return: ";
cin >> choice;
switch (choice)
{
case 1:
addEmp(empList); // call to function to add an employee to the queue
break;
case 2:
delEmp(empList); // call to fucntion to remove an employee from the queue
break;
case 3:
cout << endl << "Count of Employees: "
<< empList.GetLength() << endl; // See how many employees are in the queue
system("pause");
break;
case 4:
cout << "End of Program"; // End Program
break;
default:
cout << "Not a valid choice!" << endl;
cout << "Choose Again."; // Handling incorrect inputs
system("pause");
break;
}
} while (choice != 4); // If choice is not 4, continue running program
return 0;
}
//***********************************
//Loads the file (having trouble figuring out how to implement this part)
//***********************************
void loadFile(Employee &empList)
{
int numIn, yearsIn;
string LastName;
string FirstName;
LinkedQ empIn;
ifstream input;
input.open("Employee.txt");
while (input)
{
input >> numIn >> LastName >> FirstName >> yearsIn;
if (input)
{
cout << "this is where we load data from the file into the queue";
//empIn.setFields(numIn, LastName, FirstName, yearsIn);
//empList.addEmp(empIn);
}
}
input.close();
}
//***************************************
//add an employee
//***************************************
void addEmp(LinkedQ &empList)
{
Employee newEmp;
newEmp.user();
empList.Enqueue(newEmp);
}
//****************************************
//remove a employee
//****************************************
void delEmp(LinkedQ &empList)
{
Employee EmpToRemove;
int empNum;
// bool successful;
cout << "Please enter EMPLOYEE NUMBER of employee to remove:";
cin >> empNum;
EmpToRemove.setEmpNumber(empNum);
empList.Dequeue(EmpToRemove);
//successful = empList.Dequeue(EmpToRemove);
//if (successful == true)
//{
cout << "Removed" << endl << endl;
system("pause");
//}
//else
//{
// cout << "Emp Not found" << endl << endl;
//}
}
Here is the LinkedQ implementation file:
//LinkedQ class
#include "LinkedQ.h"
#include <cstddef>
#include <new>
struct NodeType
{
Employee info;
NodeType* next;
};
LinkedQ::LinkedQ(void)
{
newNode = nullptr;
front = NULL;
rear = NULL;
length = 0;
}
void LinkedQ::MakeEmpty()
{
NodeType* tempPtr;
while (front != NULL)
{
tempPtr = front;
front = front->next;
delete tempPtr;
}
rear = NULL;
}
LinkedQ::~LinkedQ(void)
{
MakeEmpty();
}
bool LinkedQ::IsFull() const
{
NodeType* location;
try
{
location = new NodeType;
delete location;
return false;
}
catch (std::bad_alloc exception)
{
return true;
}
}
bool LinkedQ::IsEmpty() const
{
return (front == NULL);
}
void LinkedQ::Enqueue(Employee newItem)
{
if (IsFull())
cout << "Queue is Full";
// throw FullQueue();
else
{
NodeType* newNode;
newNode = new NodeType;
newNode->info = newItem;
newNode->next = NULL;
if (rear == NULL)
{
front = newNode;
}
else
{
rear->next = newNode;
}
rear = newNode;
length++;
}
}
void LinkedQ::Dequeue(Employee& item)
{
if (IsEmpty())
{
//throw EmptyQueue();
cout << "Queue is empty";
}
else
{
NodeType* tempPtr;
tempPtr = front;
item = front->info;
front = front->next;
if (front == NULL)
{
rear = NULL;
}
delete tempPtr;
length--;
}
}
int LinkedQ::GetLength() const
{
return length;
}
And here is the Employee implementation file:
//employee Class
#include"Employee.h"
//Constructor
Employee::Employee()
{
EmpNum = 0;
}
//setters
void Employee::setEmpNumber(int eNum)
{
EmpNum = eNum;
}
void Employee::setEmpName(string LName)
{
LastName = LName;
}
void Employee::setEmpFirstName(string FName)
{
FirstName = FName;
}
void Employee::setYearsService(int years)
{
YearsService = years;
}
void Employee::setFields(int num, string LN, string FN, int years)
{
EmpNum = num;
LastName = LN;
FirstName = FN;
YearsService = years;
}
void Employee::user()
{
string inputString;
int intNumber;
cout << "Employee Number ";
cin >> intNumber;
while (intNumber <= 0)
{
cout << "Employee Number ";
cin >> intNumber;
}
EmpNum = intNumber;
cout << "Last Name: ";
cin >> inputString;
LastName = inputString;
cout << "First Name: ";
cin >> inputString;
FirstName = inputString;
cout << "Years of Service: ";
cin >> intNumber;
while (intNumber < 0)
{
cout << "Years of Service ";
cin >> intNumber;
}
cout << endl;
YearsService = intNumber;
}
//getters
const int Employee::getEmpNumber()
{
return EmpNum;
}
const string Employee::getLastName()
{
return LastName;
}
const string Employee::getFirstName()
{
return FirstName;
}
const int Employee::getYearsService()
{
return YearsService;
}
//overloads
bool Employee::operator == (const Employee &right)
{
bool status;
if ( EmpNum == right.EmpNum)
status = true;
else
status = false;
return status;
}
bool Employee::operator != (const Employee &right)
{
bool status;
if (EmpNum != right.EmpNum)
status = true;
else
status = false;
return status;
}
I think the parameter of loadFile should be of type LinkedQ, which, if I understand it correctly, is the queue class/struct, and the empIn variable should be of type Employee.
Edit:
The method you call on the empList object should be Enqueue, instead of addEmp.
So this is a doubly linked list that is supposed to hold names, address, and phone numbe and print them out. It works for the first 3 nodes then suddenly crashes after the the phone number entry on the third node. something is wrong with the pointers I believe but I have tried everything I can think of.
#include <iostream>
using namespace std;
class node
{
private:
string elem;
node* next;
node* prev;
string firstName;
string lastName;
string address;
string phoneNumber;
friend class linkedList;
};
//Linked list
class linkedList
{
public:
linkedList();
void addFrontNode(const string& e);
void addNode(const string& e);
void addNode2(node* nextloc, const string& e);
void addNode3(node* nextloc, const string& e);
void addNode4(node* nextloc, const string& e);
void print();
void search();
node* nextloc;
private:
node* head;
node* tail;
};
void linkedList::addFrontNode(const string &e)
{
node* v = new node;
string firstNameEntry;
string lastNameEntry;
string addressEntry;
string phoneNumberEntry;
cout << "Enter first name: ";
cin >> firstNameEntry;
cout << "Enter last name: ";
cin >> lastNameEntry;
cout << "Enter the address ";
cin.ignore();
getline(cin, addressEntry);
cout << "Enter a phone number ";
cin >> phoneNumberEntry;
v->elem = firstNameEntry;
v->lastName = lastNameEntry;
v->address = addressEntry;
v->phoneNumber = phoneNumberEntry;
v->next = head;
head = v;
}
void linkedList::addNode(const string &e)
{
node* v = new node;
string firstNameEntry;
string lastNameEntry;
string addressEntry;
string phoneNumberEntry;
cout << "Enter first name: ";
cin >> firstNameEntry;
cout << "Enter last name: ";
cin >> lastNameEntry;
cout << "Enter the address ";
cin.ignore();
getline(cin, addressEntry);
cout << "Enter a phone number ";
cin >> phoneNumberEntry;
v->elem = firstNameEntry;
v->lastName = lastNameEntry;
v->address = addressEntry;
v->phoneNumber = phoneNumberEntry;
v->next = tail;
tail = v;
tail->next = NULL;
}
void linkedList::addNode2(node* nextloc, const string &e)
{
node* v = new node;
string firstNameEntry;
string lastNameEntry;
string addressEntry;
string phoneNumberEntry;
cout << "Enter first name: ";
cin >> firstNameEntry;
cout << "Enter last name: ";
cin >> lastNameEntry;
cout << "Enter the address ";
cin.ignore();
getline(cin, addressEntry);
cout << "Enter a phone number ";
cin >> phoneNumberEntry;
v->elem = firstNameEntry;
v->lastName = lastNameEntry;
v->address = addressEntry;
v->phoneNumber = phoneNumberEntry;
nextloc = head -> next;
v->next = nextloc;
v->next = nextloc;
v->prev = nextloc->prev;
nextloc->prev = v;
}
void linkedList::addNode3(node* nextloc, const string &e)
{
node* v = new node;
string firstNameEntry;
string lastNameEntry;
string addressEntry;
string phoneNumberEntry;
cout << "Enter first name: ";
cin >> firstNameEntry;
cout << " Enter last name: ";
cin >> lastNameEntry;
cout << " Enter the address ";
cin.ignore();
getline(cin, addressEntry);
cout << " Enter a phone number ";
cin >> phoneNumberEntry;
v->elem = firstNameEntry;
v->lastName = lastNameEntry;
v->address = addressEntry;
v->phoneNumber = phoneNumberEntry;
v->next = nextloc;
v->prev = nextloc->prev;
nextloc->prev = v;
}
void linkedList::addNode4(node* nextloc, const string &e)
{
node* v = new node;
string firstNameEntry;
string lastNameEntry;
string addressEntry;
string phoneNumberEntry;
cout << "Enter first name: ";
cin >> firstNameEntry;
cout << " Enter last name: ";
cin >> lastNameEntry;
cout << " Enter the address ";
cin.ignore();
getline(cin, addressEntry);
cout << " Enter a phone number ";
cin >> phoneNumberEntry;
v->elem = firstNameEntry;
v->lastName = lastNameEntry;
v->address = addressEntry;
v->phoneNumber = phoneNumberEntry;
v->next = nextloc;
v->prev = nextloc->prev;
nextloc->prev->next = v;
nextloc->prev = v;
}
linkedList::linkedList() :head(NULL) {}
void linkedList::print()
{
node* v = new node;
v = head;
while (v != NULL)
{
cout << v->elem << " ";
cout << v->lastName << " ";
cout << v->address << " ";
cout << v->phoneNumber;
v = v->next;
}
}
void linkedList::search()
{
node* v = new node;
v = tail;
string lastNameSearch;
cout << "Enter a last name to search ";
cin >> lastNameSearch;
while (v != NULL)
{
if (v->lastName == lastNameSearch)
{
cout << v->elem;
cout << v->address;
cout << v->phoneNumber;
}
v = v->prev;
}
}
int main()
{
string node1;
string node2;
string node3;
string node31;
string node4;
string node5;
linkedList list;
list.addFrontNode(node1);
list.addNode(node2);
list.addNode2(list.nextloc, node3);
list.addNode3(list.nextloc, node4);
list.addNode4(list.nextloc, node5);
list.print();
return 0;
}
There are several issues.
If you use addFrontNode() to add first node, you must set your tail.
Change this:
v->next = head;
head = v;
To this:
v->next = NULL;
head = v;
tail = v;
Your function addNode() doesn't add to list correctly, try calling print and you will see, no node is added by this function.
Change this:
v->next = tail;
tail = v;
tail->next = NULL;
To this:
tail->next = v;
v->next = NULL;
tail = v;
In main() just use addFrontNode() to add first and then use addNode() to add all others. After this your code worked as expected.
Didn't understand meaning of variable nextloc, might be the source of problems.
Overall recommendation: create one function to add node
The code is indeed in need of re-write, but I don't want to repeat recommendations from the first answer. I however, believe that the question was about the reasons of the crash. It's because while copy-pasting the code, you added 2 extra lines to your addNode2:
void linkedList::addNode2(node* nextloc, const string &e)
{
...
nextloc = head -> next;
v->next = nextloc;
...
}
Comment out at least first of them and it won't crash any more (but this wouldn't make it better, really).
Here is my code
struct Node{
char* isbn;
char* author;
char* title;
char* copyright;
char* genre;
bool status;
Node* next;
};
struct LinkedList {
Node* head; // This is the starting pointer of Linked List
LinkedList(){
head = NULL;
}
void insertAtHead(char* a, char* b, char* c, char* d, char* e, bool f){
Node* temp = new Node;
temp->isbn = a;
// etc. assigning information
temp->next = head;
head = temp;
}
void display(){
int i = 1;
Node* it = head;
while (it != NULL){
// display book info
it = it->next;
i++;
}
cout << "\n";
}
};
int main(){
LinkedList LL;
int x;
char a1[10] = "";
char a2[25] = "";
char a3[25] = "";
char a4[15] = "";
char a5[15] = "";
bool a6 = 0;
do{
cout << "\n======================================\n";
cout << "1) Insert Book At Head.\n";
cout << "2) Display All Books.\n";
cout << "3) Exit.\n";
cout << "======================================\n";
cin >> x;
switch(x){
case 1:{
cout << "Enter ISBN: "; cin >> a1;
cout << "Enter The Author's Name: "; cin >> a2;
cout << "Enter The Book Title: "; cin >> a3;
cout << "Enter The CopyRights: "; cin >> a4;
cout << "Enter The Book Genre: "; cin >> a5;
cout << "Enter The Status Of Book: "; cin >> a6;
LL.insertAtHead(a1,a2,a3,a4,a5,a6);
break;
}
case 2:
LL.display();
break;
case 3:
break;
}
}while(x!=3);
return 0;
}
The Problem is That When i insert a book using case 1 of switch it inserts a book in
the linked list with the given data but when i enter a new book the previously saved book
is overwritten by new book
It's not the linked list which is not working. It's the way you assign the values. You givie it adress of your input buffers (which are overwritten at each reading) and you store this adress in your node.
You have to make a copy of your buffers (using the old C-way strdup()).
I'd suggest a better approach: consider the use of C++ strings.
It's suffichent to #include <string> and update your struct into:
struct Node{
string isbn;
string author;
string title;
string copyright;
string genre;
bool status;
Node* next;
};
As strings understand correctly the assignment from char*, it wll generate its own copy, not realying anymore on your buffers. It'll be better though to consider replacing char* with strings in all your code.
I'm new to C++ and currently experimenting about linked lists and I'm having trouble with displaying the multiple values in my program. I know the problem is somewhere in the pointers(DisplayAll function) but I'm not sure how to solve it.
node* InfoBook::AddNode(nodePtr temp)
{
string firstname;
string lastname;
string phonenumber;
string dayofbirth;
string monthofbirth;
string yearofbirth;
string age;
string streetname;
string city;
string state;
string zipcode;
InfoBook ad;
if(head != NULL)
{
current = head;
while(current -> next != NULL)
{
current = current -> next;
}
current -> next = new node;
current -> firstname = temp -> firstname;
current -> lastname = temp -> lastname;
////code here to add the other values////
current -> zipcode = temp -> zipcode;
current -> next -> next = nullptr;
return current;
ad.userPromptStatement();
}
else
{
head = new node;
head -> firstname = temp -> firstname;
head -> lastname = temp -> lastname;
////code here to add the other values////
head -> zipcode = temp -> zipcode;
head -> next = nullptr;
return current;
}
}
////////////////////////////////DisplayAll/////////////////////////////////
void InfoBook::DisplayAll()
{
current = head;
int count = 1;
string firstname;
string lastname;
string phonenumber;
string dayofbirth;
string monthofbirth;
string yearofbirth;
string age;
string streetname;
string city;
string state;
string zipcode;
if(current == nullptr)
{
cout << "\n\n\No Record exists.";
}
while(current != NULL)
{ ////////I know the problem is somewhere between here////////
cout << "Record # " << count << " : ";
cout << current -> firstname << endl;
cout << current -> lastname << endl;
cout << current -> phonenumber << endl;
cout << current -> dayofbirth << endl;
cout << current -> monthofbirth << endl;
cout << current -> yearofbirth << endl;
cout << current -> age << endl;
cout << current -> streetname << endl;
cout << current -> city << endl;
cout << current -> state << endl;
cout << current -> zipcode << endl;
cout <<"\n\n\n";
current = current -> next;
count++;
}
}
///////////////////////////////////////////////
////pointers
InfoBook::InfoBook()
{
head = NULL;
current = NULL;
temp = NULL;
}
////////
class InfoBook
{
private:
nodePtr head;
nodePtr current;
nodePtr temp;
public:
InfoBook();
void userPromptStatement();
node* AddNode(nodePtr);
void DisplayAll();
/////////////
typedef struct node
{
string firstname;
string lastname;
string phonenumber;
string dayofbirth;
string monthofbirth;
string yearofbirth;
string age;
string streetname;
string city;
string state;
string zipcode;
static int count;
node* next;
} *nodePtr;
the program displays only 'Record # :'s but not the values. Any ideas?
i think after
current -> next = new node;
you should add this:
current = current->next;
because you have to assign to the node you've alloc, not the current one.