Comparing values input to values in a vector - c++

I'm trying to input a form of data validation in which when a user enter's a book's ISBN number, if it has already been stored then it will output an error message. However, I'm having trouble doing this. I'm not sure if I'm overloading the == operator correctly, and I'm not sure how to compare the vector values in the store_ISBN() function.
Here is the code:
#include "std_lib_facilities.h"
// Classes ---------------------------------------------------------------------
class Book{
public:
vector<Book> books; // stores book information
Book() {}; // constructor
friend ostream& operator<<(ostream& out, const Book& b);
bool operator==(const Book& d);
string what_title();
string what_author();
int what_copyright();
void store_ISBN();
void is_checkout();
private:
char check;
int ISBNfirst, ISBNsecond, ISBNthird;
char ISBNlast;
string title;
string author;
int copyright;
};
// Class Functions -------------------------------------------------------------
string Book::what_title()
{
cout << "Title: ";
getline(cin,title);
cout << endl;
return title;
}
string Book::what_author()
{
cout << "Author: ";
getline(cin,author);
cout << endl;
return author;
}
int Book::what_copyright()
{
cout << "Copyright Year: ";
cin >> copyright;
cout << endl;
return copyright;
}
void Book::store_ISBN()
{
bool test = false;
cout << "Enter ISBN number separated by spaces: ";
while(!test){
cin >> ISBNfirst >> ISBNsecond >> ISBNthird >> ISBNlast;
for(int i = 0; i < books.size(); ++i)
if(ISBNfirst == books[i]) cout << "test"; // no idea how to implement this line
if((ISBNfirst<0 || ISBNfirst>9) || (ISBNsecond<0 || ISBNsecond>9) || (ISBNthird<0 || ISBNthird>9))
error("Invalid entry.");
else if(!isdigit(ISBNlast) && !isalpha(ISBNlast))
error("Invalid entry.");
else test = true;}
cout << endl;
}
void Book::is_checkout()
{
bool test = false;
cout << "Checked out?(Y or N): ";
while(!test){
cin >> check;
if(check == 'Y') test = true;
else if(check == 'N') test = true;
else error("Invalid value.");}
cout << endl;
}
// Operator Overloading --------------------------------------------------------
bool Book::operator==(const Book& d){ // is this right???
if((ISBNfirst == d.ISBNfirst) && (ISBNsecond == d.ISBNsecond)
&& (ISBNthird == d.ISBNthird) && (ISBNlast == d.ISBNlast)) return true;
else return false;
}
ostream& operator<<(ostream& out, const Book& b){
out << "Title: " << b.title << endl;
out << "Author: " << b.author << endl;
out << "ISBN: " << b.ISBNfirst << "-" << b.ISBNsecond << "-" << b.ISBNthird << "-" << b.ISBNlast << endl;
out << endl;
return out;
}
// Main ------------------------------------------------------------------------
int main()
{
Book store;
string question;
while(true){
store.what_title();
store.what_author();
store.what_copyright();
store.store_ISBN();
store.is_checkout();
store.books.push_back(store);
cout << "Are you finished?(Y or N): ";
cin >> question;
if(question == "Y") break;
else if(question == "N"){
cout << endl;
cin.ignore();}
else error("Invalid value.");
}
cout << endl;
cout << "Books stored -\n" << endl;
for(int i = 0; i < store.books.size(); ++i)
cout << store.books[i];
keep_window_open();
}
Note that in the store_ISBN function I've only included testing for one variable since I don't want to type out the whole thing before I figure out how to do it.
As you can see each time a book passes through the loop in main, the data for that book is stored. I'm then able to output all the data input after the loop by overloading the << operator to print Title, Author, and ISBN. So I think I should be able to access that individual data in the vector to compare to the user input ISBN, but I don't know how. The parts that I am confused about have been commented as such.

I'm not sure quite what the user is expected to type for an ISBN.
Reading from a stream into an int will read digits up to a space, and convert the result to int (if all goes well, anyway). Reading into a char will store the char value. So at the moment you're validating than an ISBN looks like three single digits (0-9), and then the next char. That's not what I think an ISBN looks like.
Your operator== looks OK, although note that for a bool return value,
if (X) return true;
else return false;
can be replaced with
return X;
because conditionals are already of type bool.
After setting your ISBN values (and any other fields you plan to use in operator==, if it's not finished yet), the way to look for a matching book in the store is:
for(int i = 0; i < books.size(); ++i)
if(*this == books[i]) cout << "test";
In other words, look for a book equal to this book. Or you could use std::find from <algorithms>, although in this case it wouldn't really be any more concise.
By the way, it is unusual to use the same class (Book) to represent both a single book, and the whole store. Unpicking that is a fairly complex set of changes and decisions, though, so I'll just say that a class should represent a single kind of thing, and an object of the class represent an example of that kind. So normally Book and Bookstore are different kinds of thing. The vector in Book is an instance variable, meaning that every Book has its own vector of Books. That doesn't really make sense.

books refers to a vector of Book class. You are comparing Book to an integer, which is undefined behavior. You need to dereference the Book object before you can access its data members.
First, don't access vectors using subscript [] notation. It is inefficient and makes life difficult. Use an iterator (something like, not sure on how you would want to implement):
for (std::vector::iterator it = books.begin(); it != books.end(); ++it)
{
}
That isn't your problem, however. You use the -> operator to dereference objects to get to their members. You made your members private, however, so you either need a get function like
ISBNf() { return ISBNfirst; }
Or make your members public, but that is a bad idea (people can fool with your data). However, for simplicity, assume they are public, this is what you want:
for (std::vector::iterator it = books.begin(); it != books.end(); ++it)
{
if (*this == *it) cout << "test";
}
There is no good solution, here, because I have no idea what you are trying to achieve. I think you are trying to compare the number of digits on the integer, but this is not how to achieve that. If you are just trying to make sure you are assigning ISBNfirst properly, let me put your mind to rest: you are. However, you aren't accessing them correctly, which is where the -> operator comes in.
Next, this code is overkill:
else if(!isdigit(ISBNlast) && !isalpha(ISBNlast)
instead, use the isalphnum() function:
else if (!isalphnum(ISBNlast));
Posted; I will edit my post to point out all the flaws in your code.

Related

C++ program stuck in an infinite loop

Please note that I am a complete beginner at C++. I'm trying to write a simple program for an ATM and I have to account for all errors. User may use only integers for input so I need to check if input value is indeed an integer, and my program (this one is shortened) works for the most part.
The problem arises when I try to input a string value instead of an integer while choosing an operation. It works with invalid value integers, but with strings it creates an infinite loop until it eventually stops (unless I add system("cls"), then it doesn't even stop), when it should output the same result as it does for invalid integers:
Invalid choice of operation.
Please select an operation:
1 - Balance inquiry
7 - Return card
Enter your choice and press return:
Here is my code:
#include <iostream>
#include <string>
using namespace std;
bool isNumber(string s) //function to determine if input value is int
{
for (int i = 0; i < s.length(); i++)
if (isdigit(s[i]) == false)
return false;
return true;
}
int ReturnCard() //function to determine whether to continue running or end program
{
string rtrn;
cout << "\nDo you wish to continue? \n1 - Yes \n2 - No, return card" << endl;
cin >> rtrn;
if (rtrn == "1" and isNumber(rtrn)) { return false; }
else if (rtrn == "2" and isNumber(rtrn)) { return true; }
else {cout << "Invalid choice." << endl; ReturnCard(); };
return 0;
}
int menu() //function for operation choice and execution
{
int choice;
do
{
cout << "\nPlease select an operation:\n" << endl
<< " 1 - Balance inquiry\n"
<< " 7 - Return card\n"
<< "\nEnter your choice and press return: ";
int balance = 512;
cin >> choice;
if (choice == 1 and isNumber(to_string(choice))) { cout << "Your balance is $" << balance; "\n\n"; }
else if (choice == 7 and isNumber(to_string(choice))) { cout << "Please wait...\nHave a good day." << endl; return 0; }
else { cout << "Invalid choice of operation."; menu(); }
} while (ReturnCard()==false);
cout << "Please wait...\nHave a good day." << endl;
return 0;
}
int main()
{
string choice;
cout << "Insert debit card to get started." << endl;
menu();
return 0;
}
I've tried every possible solution I know, but nothing seems to work.
***There is a different bug, which is that when I get to the "Do you wish to continue?" part and input any invalid value and follow it up with 2 (which is supposed to end the program) after it asks again, it outputs the result for 1 (continue running - menu etc.). I have already emailed my teacher about this and this is not my main question, but I would appreciate any help.
Thank you!
There are a few things mixed up in your code. Always try to compile your code with maximum warnings turned on, e.g., for GCC add at least the -Wall flag.
Then your compiler would warn you of some of the mistakes you made.
First, it seems like you are confusing string choice and int choice. Two different variables in different scopes. The string one is unused and completely redundant. You can delete it and nothing will change.
In menu, you say cin >> choice;, where choice is of type int. The stream operator >> works like this: It will try to read as many characters as it can, such that the characters match the requested type. So this will only read ints.
Then you convert your valid int into a string and call isNumber() - which will alway return true.
So if you wish to read any line of text and handle it, you can use getline():
string inp;
std::getline(std::cin, inp);
if (!isNumber(inp)) {
std::cout << "ERROR\n";
return 1;
}
int choice = std::stoi(inp); // May throw an exception if invalid range
See stoi
Your isNumber() implementation could look like this:
#include <algorithm>
bool is_number(const string &inp) {
return std::all_of(inp.cbegin(), inp.cend(),
[](unsigned char c){ return std::isdigit(c); });
}
If you are into that functional style, like I am ;)
EDIT:
Btw., another bug which the compiler warns about: cout << "Your balance is $" << balance; "\n\n"; - the newlines are separated by ;, so it's a new statement and this does nothing. You probably wanted the << operator instead.
Recursive call bug:
In { cout << "Invalid choice of operation."; menu(); } and same for ReturnCard(), the function calls itself (recursion).
This is not at all what you want! This will start the function over, but once that call has ended, you continue where that call happened.
What you want in menu() is to start the loop over. You can do that with the continue keyword.
You want the same for ReturnCard(). But you need a loop there.
And now, that I read that code, you don't even need to convert the input to an integer. All you do is compare it. So you can simply do:
string inp;
std::getline(std::cin, inp);
if (inp == "1" || inp == "2") {
// good
} else {
// Invalid
}
Unless that is part of your task.
It is always good to save console input in a string variable instead of another
type, e.g. int or double. This avoids trouble with input errors, e.g. if
characters instead of numbers are given by the program user. Afterwards the
string variable could by analyzed for further actions.
Therefore I changed the type of choice from int to string and adopted the
downstream code to it.
Please try the following program and consider my adaptations which are
written as comments starting with tag //CKE:. Thanks.
#include <iostream>
#include <string>
using namespace std;
bool isNumber(const string& s) //function to determine if input value is int
{
for (size_t i = 0; i < s.length(); i++) //CKE: keep same variable type, e.g. unsigned
if (isdigit(s[i]) == false)
return false;
return true;
}
bool ReturnCard() //function to determine whether to continue running or end program
{
string rtrn;
cout << "\nDo you wish to continue? \n1 - Yes \n2 - No, return card" << endl;
cin >> rtrn;
if (rtrn == "1" and isNumber(rtrn)) { return false; }
if (rtrn == "2" and isNumber(rtrn)) { return true; } //CKE: remove redundant else
cout << "Invalid choice." << endl; ReturnCard(); //CKE: remove redundant else + semicolon
return false;
}
int menu() //function for operation choice and execution
{
string choice; //CKE: change variable type here from int to string
do
{
cout << "\nPlease select an operation:\n" << endl
<< " 1 - Balance inquiry\n"
<< " 7 - Return card\n"
<< "\nEnter your choice and press return: ";
int balance = 512;
cin >> choice;
if (choice == "1" and isNumber(choice)) { cout << "Your balance is $" << balance << "\n\n"; } //CKE: semicolon replaced by output stream operator
else if (choice == "7" and isNumber(choice)) { cout << "Please wait...\nHave a good day." << endl; return 0; }
else { cout << "Invalid choice of operation."; } //CKE: remove recursion here as it isn't required
} while (!ReturnCard()); //CKE: negate result of ReturnCard function
cout << "Please wait...\nHave a good day." << endl;
return 0;
}
int main()
{
string choice;
cout << "Insert debit card to get started." << endl;
menu();
return 0;
}

No Operator error code

I am completing a hotel reservation form using C++ language. I keep getting no operator error for fin !=0. How can I address this error? Here is the actual coding...
void Hotel::show_room_record()
{
cout << "R.Num" << setw(10) << "R.Stat" << setw(10) << "Category" << setw(10) << "Rent\n";
ifstream fin("room.dat", ios::in);
for (int p = 0; fin != 0; p = p + 15)
{
fin.seekg(p);
fin >> room_no;
fin >> room_status;
fin >> category;
fin >> rent;
cout << room_no << setw(10) << room_status << setw(10) << category << setw(10) << rent << "\n";
}
fin.close();
}
You can't compare fin with 0, fin wont return the next input.
First store the input in a variable, then compare it.
For your case, you probably want to check if the next character is a '0', or even a '\0'.
Try using this:
http://www.cplusplus.com/reference/istream/istream/peek/
Your condition becomes (assuming you want '\0'):
fin.peek() != 0
You cannot test fin != 0. fin isn't a number, to testing for equality with 0 makes about as much sense as testing what kind of orange an apple is. You can test that fin is still readable though with a simple fin by taking advantage of operator bool, but that's tricky because the test for is readable will be made before reading. You can't test for failure before you have a chance to fail and that leaves open the possibility that the last reads failed and were not checked for validity.
Instead of trying to fix this, I'm going to go all X-Y on you here and suggest something completely different.
Define a structure
struct room
{
int room_no;
string room_status;
string category;
int rent; // could be a float. Don't care much for this example
// that said, watch out for rounding errors when dealing with floats
};
Create a function that makes it really easy to read into this structure
std::istream & operator>>(std::istream & in,
room & inroom)
{
in >> inroom.room_no >> inroom.room_status >> inroom.category >> inroom.rent;
return in;
}
Create a function that makes it really easy to write this structure
std::ostream & operator<<(std::ostream & out,
const room & outroom)
{
out << outroom.room_no << setw(10) << outroom.room_status <<
setw(10) << outroom.category << setw(10) << outroom.rent;
return out;
}
Make a std::vector of the above structure a member of the Hotel class
std::vector<room> rooms;
Read the file into it
room temp;
while (in >> temp)
{
rooms.push_back(temp);
}
Now the hotel knows the status of all the rooms without having to keep looking at the file. This makes printing easy.
for(room & r: rooms)
{
cout << r << '\n';
}
It makes finding any room a simple traversal of rooms
for(room & r: rooms)
{
if (r.whatever == desiredwhatever)
{
return r;
}
}
and every now and then you rewrite the file if a room was changed.
std::ostream outfile("path to file goes here");
for(room & r: rooms)
{
if (!(outfile << r << '\n'))
{
//handle error
}
}
All of these things you probably have to do anyway. The only downside is if you are not allowed to use std::vector. In that case you either write a simple vector substitute or use an array and pray it never overflows.

Sorting Linked Lists - move nodes or swap data members?

I have a simple question. I'm working on a C++ app that is a contact list app. It stores names, addresses, numbers, ages, etc for multiple people. I'm using stucts and linked lists (nodes). I'm building the sort list function, to alphabetize the list. I'm currently wondering if it's better to actually reorder the list by moving the structs as a whole or by swapping the data members inside each node. At first, I considered moving the nodes, but now swapping the data members seems more safe, as I don't have to reorder the list. At any rate, I don't know if either possesses any benefits over the other.
EDIT: Here's the source code I'm working on. Notice the sort function is incomplete. Also, I'm still a novice programmer, so the coding will probably have a ton of issues, from a professional standpoint. That, alongside the fact I'm not close to being done with it. I'm only writing it to practice coding over my summer break between programming classes.
#include <iostream>
#include <fstream>
#include <string.h>//for functions in date function
#include <time.h> //for functions in date function
#include <sys/stat.h>//for mkdir functions
#include <unistd.h>//for usleep function
#include <ctype.h>//for toupper function in swap function
using namespace std;
struct PersonInfo
{
char FirstName[20];
char LastName[20];
char Address[40];
char PhoneNumber[20];
int Age;
PersonInfo *Link;
};
bool EmptyFileChecker(ifstream &FI, const char *P);
void AddPeopleToList(PersonInfo *&HeadPointer);
void RebuildOldList(ifstream &FI, PersonInfo *&HeadPointer, const char *P);
void DisplayList(PersonInfo *HeadPointer);
void SaveSettings(ofstream &FO, const PersonInfo *HeadPointer, const char *P);
void DisplayMenu(PersonInfo *&HeadPointer, const char *P, ifstream &FileIn, ofstream &FileOut);
void SortContacts(PersonInfo *&HeadPointer);
bool NamesInOrder(const char LastName1[], const char LastName2[]);
string Date();
//Delete Contact
//ENCRYPT LIST?
//Check for memory leaks in code and destructor?
//Return something - noun-like
//void adjective - like
int main()
{
PersonInfo *HeadPointer;
const char *Path = "/Users/josephlyons/Library/Application Support/The Lyons' Den Labs/TheLyons'DenContactInformation.txt";//code variable for username
ifstream FileIn;
ofstream FileOut;
mkdir("/Users/josephlyons/Library/Application Support/The Lyons' Den Labs", ACCESSPERMS);//MODE??
if (!EmptyFileChecker(FileIn, Path))
AddPeopleToList(HeadPointer);
else
RebuildOldList(FileIn, HeadPointer, Path);
DisplayMenu(HeadPointer, Path, FileIn, FileOut);
//SortContacts(HeadPointer);
SaveSettings(FileOut, HeadPointer, Path);
}
void DisplayMenu(PersonInfo *&HeadPointer, const char *P, ifstream &FileIn, ofstream &FileOut)
{
short int MenuChoice;
do
{
cout << "(1) Display Contact List\n";
cout << "(2) Organize Contact List\n";//delete when done with program and automatically sort list before saving.
cout << "(3) Add Contact/s\n";
cout << "(4) Delete Contact/s\n";
cout << "(5) Quit\n\n";
cout << "Choice: ";
cin >> MenuChoice;
if (MenuChoice == 1)
DisplayList(HeadPointer);
else if (MenuChoice == 2)
SortContacts(HeadPointer);
else if (MenuChoice == 3)
AddPeopleToList(HeadPointer);
else if (MenuChoice == 4)
cout << "choice 4";
}
while(MenuChoice != 5);
}
bool EmptyFileChecker(ifstream &FI, const char *P)//DONE
{
FI.open(P);
if (FI.fail())
return false;
else if (FI.eof())//return 0 if file doesnt exist or if file is empty
return false;
else
return true;
}
void AddPeopleToList(PersonInfo *&HeadPointer)
{
PersonInfo *CurrentPosition;
char UserChoice;
do
{
CurrentPosition = new PersonInfo;
if (CurrentPosition == NULL)
{
cout << "Not enough memmory to make new contact.";
return;
}
cout << "\nEnter First Name: ";
cin >> CurrentPosition->FirstName;
CurrentPosition->FirstName[0] = toupper(CurrentPosition->FirstName[0]);//automatically capitalize first name
cout << "Enter Last Name: ";
cin >> CurrentPosition->LastName;
CurrentPosition->LastName[0] = toupper(CurrentPosition->LastName[0]);//automatically capitalize last name
cin.ignore();//flushes a single newline left in input buffer from previous cin >>
cout << "Enter Adress: ";
cin.getline(CurrentPosition->Address, 40);//using cin.get() to allow for spaces in address
cout << "Enter Phone Number: ";
cin.getline (CurrentPosition->PhoneNumber, 20);//using cin.get() to allow for spaces in number
cout << "Enter Age: ";
cin >> CurrentPosition->Age;
cout << "\nAdd another contact? Y/N: ";
cin >> UserChoice;
cout << "\n";
CurrentPosition->Link = HeadPointer;
HeadPointer = CurrentPosition;
}
while (UserChoice == 'y' || UserChoice == 'Y');
SortContacts(HeadPointer);
}
void RebuildOldList(ifstream &FI, PersonInfo *&HeadPointer, const char *P)
{
PersonInfo *TemporaryPersonPointer;
char EndOfListChecker = 1;//initialized at a not 0 to allow entrance into loop
while (EndOfListChecker != 0)
{
TemporaryPersonPointer = new PersonInfo;
if (TemporaryPersonPointer == NULL)
cout << "Not enough memory to generate the full list";
FI >> TemporaryPersonPointer->FirstName;
FI >> TemporaryPersonPointer->LastName;
FI.ignore();//flushes a single newline from input
FI.getline(TemporaryPersonPointer->Address, 40);
FI.ignore();
FI.getline(TemporaryPersonPointer->PhoneNumber, 20);
FI >> TemporaryPersonPointer->Age;
TemporaryPersonPointer->Link = HeadPointer;
HeadPointer = TemporaryPersonPointer;
FI.get(EndOfListChecker);
while (EndOfListChecker == '\n')
{
FI.get(EndOfListChecker);
}
if (EndOfListChecker != 0)
FI.putback(EndOfListChecker);
}
}
void DisplayList(PersonInfo *HeadPointer)
{
do
{
cout << "\nFirst Name: ";
cout << HeadPointer->FirstName << endl;
cout << "Last Name: ";
cout << HeadPointer->LastName << endl;
cout << "Adress: ";
cout << HeadPointer->Address << endl;
cout << "Phone Number: ";
cout << HeadPointer->PhoneNumber << endl;
cout << "Age: ";
cout << HeadPointer->Age;
cout << "\n\n";
HeadPointer = HeadPointer->Link;
usleep(75000);
}
while (HeadPointer != NULL);
cout << "Press enter to go to main menu: ";
cin.ignore(2);
cout << "\n";
}
void SaveSettings(ofstream &FO, const PersonInfo *HeadPointer, const char *P)
{
FO.open(P);
if (FO.fail())
cout << "Couldn't Open File\n";
while (HeadPointer != NULL)
{
FO << HeadPointer->FirstName << endl;
FO << HeadPointer->LastName << endl;
FO << HeadPointer->Address << endl;
FO << HeadPointer->PhoneNumber << endl;
FO << HeadPointer->Age << endl << endl;
HeadPointer = HeadPointer->Link;
}
FO << (char) 0 << endl;
FO << "Date of Settings: " << Date() << endl;
FO.close();
}
void SortContacts(PersonInfo *&HeadPointer)
{
PersonInfo *MovingPointer1;//used to "crawl" down list
PersonInfo *MovingPointer2;//used to "crawl" down list
PersonInfo *StaticPointer;//always points at first node to give HeadPointer a way to link back to the list at end
PersonInfo *TemporaryPointer;//holds a node during a swap
bool ZeroSwapsOccured = false;//initialized at false to allow entrance into loop once
MovingPointer1 = StaticPointer = HeadPointer;//set all to point at first node
MovingPointer2 = HeadPointer->Link;
while (ZeroSwapsOccured == false)
{
ZeroSwapsOccured = true;
while (MovingPointer2->Link != NULL)
{
if (!NamesInOrder(MovingPointer1->LastName, MovingPointer2->LastName))
{
ZeroSwapsOccured = false;
//Temp = MP1
//MP1 = MP2
//MP2 = TEMP
MovingPointer1->Link = MovingPointer2->Link;
MovingPointer2->Link = MovingPointer1;
HeadPointer->Link = MovingPointer2;
}
}
}
HeadPointer = StaticPointer;//link HeadPointer back to list after sort
}
bool NamesInOrder(const char LastName1[], const char LastName2[])
{
for (int i = 0; LastName1[i] || LastName2[i]; ++i)//go until you get to the end of the larger name
{
if(toupper(LastName1[i]) < toupper(LastName2[i]))
return true;
if(toupper(LastName1[i]) > toupper(LastName2[i]))
return false;
}
return true;//this will only be used if same last name
//build in fucntionality to then go to first name after last name, if both last names are the same
}
string Date()//not my code here - just modified it to read easier
{
char Time[50];
time_t now = time(NULL);
strftime(Time, 50, "%b, %d, %Y", localtime(&now)); //short month name
return string(Time);
}
First - You're reordering the list in both cases.
Second -
Swapping two nodes usually takes five operations:
Change the node one back from the first node to point to the second node.
Change the node one back from the second node to point to the first node.
Store the first node's next pointer in a temporary pointer.
Change the first node's next pointer to the second node's next pointer.
Change the second node's next pointer to the temporary pointer.
Swapping two variables takes at least three operations:
Store the first variable in a temporary variable.
Change the first variable to the second variable.
Change the second variable to the first variable.
But now multiply that by the number of struct members.
The struct should have at least 2 data members - a pointer and a payload - so off the bat you're looking at, at least, 6 operations. Which will increase by 3 for each member in the struct. So you're better off just swapping the nodes.
No memory should be moving. The nodes in a linked list are not ordered in memory but only in relation to each-other via pointer(s) to the next/previous nodes in the list. your operation can be done with only a few pointer assignments.
Swapping the data is more costly and complex. For example, to swap the data, you will need to swap the name, address, numbers, ages etc.
On the other hand, swapping the node means just swapping two memory location address inside your list. So, swapping the nodes is highly preferable.
Secondly, if you add more metaData fields to your node, you won't have to change the sort code to swap the newly added data field.
So you have a linked list that you want to sort. To do it correctly and efficiently you have to use the correct sorting algorithm which in this case is the Merge Sort. For sure you should not swap the nodes' data.
Check this link: http://www.geeksforgeeks.org/merge-sort-for-linked-list/
If node data size is larger, that time it's better to swap node's position rather than swap node's data (swapping data will be bad choice).
Reasons of choosing moving the pointer implementation over swapping the data:
Let's suppose you want to add a new field to your contact list after some time. If you swap data, you will have to change your code every time you make changes to your contact list field.
As fields in contact list increase, overhead for swapping the data will grow.

Problems with changing a const char pointer

I'm having some issues with changing a char pointer and can't figure out where I'm going wrong
Here's my function for changing the description...
void appointment::changeDescription(const char * s) // change an existing description
{
if (desc != NULL)
strcpy(desc, s);
if (s == NULL)
return;
}
And here's the function that calls the change description function.
bool keyBoardEnterAppointment( schedule & sched) // return true if successful
// return false if full
{
if (sched.isFull() == true)
{
cout << "Schedule is FULL." << endl;
return false;
}
else
{
appointment s;
int day, month, year;
char *desc = new char;
long source;
cout << "*/Enter Appointment\\* ";
cout << "Description: "; cin >> desc;
cout << "Source: "; cin >> source;
cout << "Month: "; cin >> month;
cout << "Day: "; cin >> day;
cout << "Year: "; cin >> year;
s.changeDescription(desc);
s.setSource(source);
s.setDay(day);
s.setMonth(month);
s.setYear(year);
sched.addtoSchedule(s);
sched.print(cout);
return true;
}
}
It compiles and runs but the description remains the same as the default constructor description...
If you use std::string to store the description in the appointment class then you can make things much easier for yourself and for the people who end up working on your code. The changeDescription method would then become this:
#include <string>
void appointment::changeDescription(std::string const& s){
this->desc = s;
}
And change the calling code to this:
std::string desc;
Then all of the annoying memory management that causes the problems you are facing are fixed pretty much for free (in terms of programming effort that is). Generally speaking this is considered to be better idiomatic c++ code than using null terminated C-style char arrays.
Another thing about your code is that you really should check that s is not null before you try to copy it, not afterwards.

How to compare 2 integers to see if they are equal?

How do I compare two integers in C++?
I have a user input ID (which is int) and then I have a Contact ID that is part of my Struct. The Contact ID is int also.
I need to compare to see if they are the same, to know that it exists.
I did something like this*:
if(user_input_id.compare(p->id)==0)
{
}
but I get an error message saying that expression must have class type.
*based on reading this page http://www.cplusplus.com/reference/string/string/compare/
The function you found is for comparing two std::strings. You don't have std::strings, you have ints. To test if two ints are equal, you just use == like so:
if (user_input_id == p->id) {
// ...
}
In fact, even if you had two std::strings, you'd most likely want to use == there too.
I am unsure what you mean, but IMHO
int k;
std::cin>>k;
if (k==p->id)
do_sth();
else
do_sth_else();
The point is you do not store input as string, but a int.
//simple program to compare
#include<iostream>
using namespace std;
typedef struct node {
int a;
}node;
int main() {
node p;
p.a = 5;
int a;
cin >> a;
if( p.a == a )
cout << "Equal" << endl;
else
cout << "Not Equal"<< endl;
return 0;
}
IF your struct's name is p and you have an integer in it called hello, you can do the following
int input;
cin << input;
if(input == p.hello){
cout << "the input is equal to p.hello" << endl;
}
else{
cout << "the input is not equal to p.hello" << endl;
}