Cannot shift right using arrays and structures in address book program c++ - c++

I am working on a project using arrays and structures to further my poor programming skillz. I cannot figure out how to shift the array to the right. In the function editContact, I am trying to sort the contacts by last name after the name is changed. The plan is to shift the array right and put the edited contact in the appropriate alphabetized spot.
Do I need to put
"int numContacts=0;
Contact entries[500];"
into a structure?
This is the code I am struggling with specifically:
void shiftUp(int startIndex) {
entries = new int[entries.Length];
for (int i = startIndex; i < entries.Length - 1; i++)
{
entries[i] = entries[i + 1];
}
entries[entries.Length - 1] = entries[0];
}
This is the error message I receive from the compiler:
addressbook.cpp:311: error: request for member 'Length' in 'entries', which is of non-class type 'Contact [500]'
addressbook.cpp:311: error: incompatible types in assignment of 'int*' to 'Contact [500]'
addressbook.cpp:313: error: request for member 'Length' in 'entries', which is of non-class type 'Contact [500]'
addressbook.cpp:318: error: request for member 'Length' in 'entries', which is of non-class type 'Contact [500]'
This is the bulk of the program:
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
/*structures*/
struct Contact {
string firstName;
string lastName;
string middleInitial;
string phoneNumber;
string streetAddress;
string city;
string state;
string zipCode;
};
int numContacts=0;
Contact entries[500];
/*prototypes*/
int mainMenu();
int searchResults(string searchTerm);
void searchContacts();
void contactDetail(int contactIndex);
void editContact(int contactIndex);
bool deleteContact(int contactIndex);
void listContacts();
void addContact();
void shiftUp(int startIndex);
void shiftDown(int startIndex);
void saveData();
void loadData();
int findLocation(string lastName);
void saveContact(ofstream dataFile, Contact& newContact);
void loadContact(ifstream dataFile, Contact& newContact);
/*consts*/
const int SEARCH_CMD = 1;
const int LIST_CMD = 2;
const int ADD_CMD = 3;
const int EXIT_CMD = 4;
int main(){
loadData();
int selection;
do {
selection = mainMenu();
switch(selection) {
case SEARCH_CMD:
searchContacts();
break;
case LIST_CMD:
listContacts();
break;
case ADD_CMD:
addContact();
break;
}
} while (selection !=EXIT_CMD);
saveData();
}
int mainMenu(){
/*show the menu*/
cout << "**** Welcome to AddressBook ****" << endl << "1. Search for Contacts" << endl << "2. List Contacts" << endl << "3. Add New Contact" << endl << "4. Exit" << endl << "Enter Selection:";
/*input the selection*/
int selection;
while(1) {
cin >> selection;
/*validate the selection and reprompt if neccessary*/
if ((selection >4) || (selection < 1)) {
cout << "This is not a valid menu option. Please try again.";
break;
}
if ((selection <=4) && (selection >=1)) {
break;
}
}
/* return a valid selection */
return(selection);
}
void searchContacts() {
/*output "Enter search term: " */
cout << "Enter search term: ";
/*input the string searchTerm */
string searchTerm;
cin >> searchTerm;
/* call searchResults(searchTerm) */
searchResults(searchTerm);
}
int searchResults(string searchTerm){
/* output "Search Results:"*/
int noMatch =0;
cout << "Search Results: " << endl;
/*loop through every contact*/
int contactsIndex[500];
for (int i=0; i<=numContacts; i++) {
if (entries[i].lastName == searchTerm) {
noMatch++;
cout << noMatch << ". " << entries[i].firstName << " " << entries[i].lastName << " " << entries[i].phoneNumber << endl;
contactsIndex[noMatch] = i;
}
}
if (noMatch == 0) {
cout << "No match found\n";
return(1);
}
int selectContact;
cout << "Select a contact (or M for Main Menu): ";
cin >> selectContact;
if ((selectContact > 0) && (selectContact <= noMatch)) {
contactDetail(contactsIndex[selectContact]);
}
if ((selectContact=='m') || (selectContact=='M')) {
}
/* compare each field (using substr) to searchTerm*/
/* if the searchTerm is in any field, output the contact*/
/* save the index of the contact to contactsIndex array*/
/* output "Select a Contact (or M for Main Menu): "*/
/*input selection*/
/*if selection is a contact number, call contactDetail(contactsIndex[selection-1]);*/
}
void contactDetail(int contactsIndex){
/*show the indicated contact - addressBook.entries[contactIndex]*/
cout << entries[contactsIndex].firstName << " " << entries[contactsIndex].middleInitial << ". " << entries[contactsIndex].lastName << endl;
cout << entries[contactsIndex].streetAddress << endl << entries[contactsIndex].city << ", " << entries[contactsIndex].state << ", " << entries[contactsIndex].zipCode << endl;
cout << "Phone: " << entries[contactsIndex].phoneNumber << endl;
/* output "Select E for Edit, D to delete or M for Main Menu: "*/
cout << "Select E for Edit, D to delete, or M for Main Menu:" ;
/* read selection*/
char menuSelection;
cin >> menuSelection;
/*if selection is E*/
if (menuSelection == 'E') {
editContact(contactsIndex);
}
/* editContact(contactIndex)*/
/*if selection is D*/
if (menuSelection == 'D') {
bool retValue;
retValue = deleteContact(contactsIndex);
}
/* retValue = deleteContact(contactIndex)*/
/*else m, break*/
if (menuSelection == 'M') {
}
/* loop while retValue is false*/
}
void editContact(int contactsIndex){
/*output "**Press Enter to leave field unchanged. Enter a new value to change it.**"*/
cout << "Press Enter to leave field unchanged. Enter a new value to change it." << endl;
/*use addressBook.entries[contactIndex]*/
string editEntry;
cout << "First Name: ";
cin >> editEntry;
entries[contactsIndex].firstName = editEntry;
cout << "Last Name: ";
cin >> editEntry;
entries[contactsIndex].lastName = editEntry;
cout << "Middle Initial: ";
cin >> editEntry;
entries[contactsIndex].middleInitial = editEntry;
cout << "Phone Number: ";
cin >> editEntry;
entries[contactsIndex].phoneNumber = editEntry;
cout << "Street Address: ";
cin >> editEntry;
entries[contactsIndex].streetAddress = editEntry;
cout << "City: ";
cin >> editEntry;
entries[contactsIndex].city = editEntry;
cout << "State: ";
cin >> editEntry;
entries[contactsIndex].state = editEntry;
cout << "Zip Code: ";
cin >> editEntry;
entries[contactsIndex].zipCode = editEntry;
/* prompt for each field */
/* input fields*/
/* if input is not empty*/
/* set corresponding field with input*/
/* shiftUp(contactIndex)*/
shiftUp(contactsIndex);
int newIndex;
newIndex = findLocation (entries[contactsIndex].lastName);
/* newIndex = findLocation(lastName)
if (newIndex != numContacts) {
shiftDown(newIndex);
}*/
/* if newIndex != numContacts*/
/* shiftDown(newIndex)*/
/* add the new contact at [newindex]*/
/* output "Select E to Edit or M for Main Menu: "*/
/* if selection is Edit*/
/*loop*/
}
bool deleteContact(int contactIndex){
/*output "Are you sure you want to delete this contact? (Y/N): "*/
/*read selection*/
/*validate selection*/
/* if yes*/
/*shiftUp(contactIndex)*/
/* output "Contact deleted! Press any key to return to main menu."*/
/*return true - means contact was deleted*/
/*else if No*/
/*return false*/
return(false);
}
void listContacts(){
/*output "Contact List: "*/
cout << "Contact List: " << endl;
/* for all contacts:*/
for (int i=0; i < numContacts; i++) {
cout << entries[i].firstName << " " << entries[i].middleInitial << ". " << entries[i].lastName << endl;
cout << entries[i].streetAddress << endl << entries[i].city << ", " << entries[i].state << ", " << entries[i].zipCode << endl;
cout << "Phone: " << entries[i].phoneNumber << endl << endl;
/* output firstName, lastName, and phone (formatted)*/
/* output "Select a Contact (or M for Main Menu): "*/
/*input selection*/
/*validate selection*/
/*if selection is a contact number, call contactDetail(contactsIndex[selection-1]);*/
}
}
void addContact(){
cout << "Add A Contact! Please enter each value as prompted." << endl;
/*
string newEntry;
cout << "First Name: ";
cin >> newEntry;
entries[contactsIndex].firstName = newEntry;
cout << "Last Name: ";
cin >> newEntry;
entries[contactsIndex].lastName = newEntry;
cout << "Middle Initial: ";
cin >> newEntry;
entries[contactsIndex].middleInitial = newEntry;
cout << "Phone Number: ";
cin >> newEntry;
entries[contactsIndex].phoneNumber = newEntry;
cout << "Street Address: ";
cin >> newEntry;
entries[contactsIndex].streetAddress = newEntry;
cout << "City: ";
cin >> newEntry;
entries[contactsIndex].city = newEntry;
cout << "State: ";
cin >> newEntry;
entries[contactsIndex].state = newEntry;
cout << "Zip Code: ";
cin >> newEntry;
entries[contactsIndex].zipCode = newEntry;
*/
/*First Name:*/
/*Last Name:*/
/*Middle Initial:*/
/*Phone Number:*/
/*Street Address:*/
/*City: */
/*State:*/
/*Zip Code:*/
/* add the new contact to the addressBook*/
/* newIndex = findLocation(lastName)*/
/* if newIndex != numContacts*/
/* shiftDown(newIndex)*/
/* add the new contact at [newindex]*/
/* addressBook.numContacts++*/
/*set contactIndex to index of added contact*/
/*Enter 'E' for Edit Again, 'D' to Delete, or 'M' for Main Menu: M*/
/*if selection is E*/
/* editContact(contactIndex)*/
}
void shiftDown(int startIndex) {
/*shift the addressBook.entries up */
/*starting at startIndex+1 through the end of the array (loop should loop from bottom)*/
/*addressBook.numContacts++;*/
}
void shiftUp(int startIndex) {
entries = new int[entries.Length];
for (int i = startIndex; i < entries.Length - 1; i++)
{
entries[i] = entries[i + 1];
}
entries[entries.Length - 1] = entries[0];
/*shift the addressBook.entries down */
/*starting at startIndex through the end of the array (loop should loop from top)*/
/*addressBook.numContacts--;*/
}
int findLocation(string lastName) {
/*go through the addressBook and find the first lastName that is greater than the lastName passed to the function*/
int nameOrder;
for (int i=0; lastName < entries[i].lastName; i++) {
nameOrder++;
}
/* if you reach the end of the array, return the number of the next available slot*/
return(nameOrder);
}
void loadData(){
string newContact;
ifstream dataFile;
dataFile.open("addressBook.dat");
/*open addressBook.dat for input. call stream dataFile*/
/*for loop until end of file using i as loop counter*/
if (dataFile.is_open()) {
for (int i=0;!dataFile.eof();i++) {
getline (dataFile,newContact);
entries[i].firstName = newContact;
cout << entries[i].firstName << endl;
getline (dataFile,newContact);
entries[i].lastName = newContact;
cout << entries[i].lastName << endl;
getline (dataFile,newContact);
entries[i].middleInitial = newContact;
getline (dataFile,newContact);
entries[i].phoneNumber = newContact;
getline (dataFile,newContact);
entries[i].streetAddress = newContact;
getline (dataFile,newContact);
entries[i].city = newContact;
getline (dataFile,newContact);
entries[i].state = newContact;
getline (dataFile,newContact);
entries[i].zipCode = newContact;
numContacts++;
}
}
else cout << "Unable to open file";
/*loadContact(dataFile, addressBook.entries[i]);*/
/*close addressBook.dat*/
dataFile.close();
}
Thanks for your help, this is the solution I ended up using
void shiftUp(int startIndex) {
/*shift the addressBook.entries up to delete entries*/
/*starting at startIndex+1 through the end of the array (loop should loop from bottom)*/
for (int i = startIndex; i <= numContacts; ++i ){
entries[i] = entries[i+1];

Technically, instead of this:
void shiftUp(int startIndex) {
entries = new int[entries.Length];
for (int i = startIndex; i < entries.Length - 1; i++)
{
entries[i] = entries[i + 1];
}
entries[entries.Length - 1] = entries[0];
}
do:
void shiftUp( int startIndex )
{
int const n = sizeof( entries )/sizeof( *entries );
for( int i = n - 1; i > startIndex; --i )
{
entries[i] = entries[i - 1];
}
}
Examine the differences to learn some new C++ things.
Instead of raw arrays, consider using C++ standard library containers like vector and map.
Raw arrays has some problems, including how to safely find the size.
With C++11 and later, instead of the above C expression consider using std::end(a) - std::begin(a), expressed as a function template (e.g. called size).
Also, you may or will discover that resorting by shifting for each new item, gives O(n2) time. Things just get slower and slower the more items you have. Unproportionally so.
This is also a good reason to use standard library containers.
They employ far more efficient strategies for keeping things sorted.

Related

copy precedent value 2d dynamic array

Hi I want to create a 2d growing dynamic array with use of char. The problem is that my function put all word in the same row. The dynamic allocation is not good but I don't know how to correct this.
void display(char** data, int length)
{
for (int i = 0; i < length; i++)
for (int j = 0; j < data[i][j] != '\0'; j++)
cout << data[i][j];
cout << endl;
}
void add(char** &data, int length, char* word)
{
if (length == 1)
{
data = new char* [length];
}
data[length-1] = new char[strlen(word)+1];
strcpy_s(*(data + length -1), strlen(word) + 1, word);
data[length - 1][strlen(word) + 1] = '\0';
}
int main()
{
char** data = NULL;
int choice = 0, length = 0; char name[80];
cout << "Enter your choice" << endl;
while (cin >> choice && choice != 3)
{
switch (choice)
{
case 0:
cout << "Enter name to add: " << endl;
cin.ignore(); cin.getline(name, 80);
length++;
add(data, length, name);
break;
}
cout << endl << "Enter your next choice: " << endl;
}
This is what is get
Enter your choice
0
Enter name to add:
jhon
jhon
Enter your next choice:
0
Enter name to add:
marc
jhonmarc
I'm pretty sure that instead of
if (length = 1)
you meant to write
if (length == 1)
In C++ = means assignment and == means equality.
Seems your code has other bugs though. You never grow the size of data. Do it the easy way and use std::vector<std::string>
#include <vector>
#include <string>
int main()
{
std::vector<std::string> data;
int choice = 0, length = 0; std::string name;
cout << "Enter your choice" << endl;
while (cin >> choice && choice != 3)
{
switch (choice)
{
case 0:
cout << "Enter name to add: " << endl;
cin.ignore(); getline(cin, name); // read name
data.push_back(name); // add name to data
break;
}
cout << endl << "Enter your next choice: " << endl;
}
Problem solved.

vector pointers and retrieving data

I'm a beginner at coding in C++ and every other language. The problem I'm having here is in main() with the first (else if) where (UserInput == sell). I would like the function to print the data stored in the object #listPos to retrieve the cost and input it into my incomplete Profit() function, but every time I dereference the pointer (Search) I get an error code. There's something I'm missing big time please help!!
Ive already tried (*search) but there's a huge error code.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class UnSold{
public:
UnSold(string NameOfShoe, int PurchasePrice ){
name = NameOfShoe;
cost = PurchasePrice;
return;
}
void SetName(string NameOfShoe){
name = NameOfShoe;
return;
}
void SetCost(int PurchasePrice){
cost = PurchasePrice;
return;
}
string GetName() const {
return name;
}
int GetCost() const{
return cost;
}
void Profit();
void PrintItem();
private:
string name;
int cost;
};
void UnSold::Profit(){
static int profit = 0;
//profit += (sold-cost);
}
void UnSold::PrintItem(){
cout << "Name: " << this->name << " Cost: " << this->cost << endl;
}
void PrintEverything(vector<UnSold*> AllItems) {
unsigned int i;
for (i=0; i<AllItems.size(); ++i) {
cout<< i+1 << " ";
(*AllItems.at(i)).PrintItem();
}
}
int main(){
vector<UnSold*> Inventory;
string Name;
int Cost;
string UserInput;
unsigned int listPos;
UnSold* newItem = nullptr;
UnSold* search = nullptr;
while ( UserInput != "quit") {
cout << "Do you want to add, sell, print or quit?" <<endl;
cin >> UserInput;
if ( UserInput == "add") {
cout << "Enter item name: "<<endl;
cin >> Name;
cout << "Enter item cost: " << endl;
cin >> Cost;
newItem = new UnSold(Name, Cost);
Inventory.push_back(newItem);
}
else if ( UserInput == "sell") {
cout << "List Positon: ";
cin >> listPos;
if ( listPos < Inventory.size()){
cout << " Item Sold and Removed from list position " << listPos <<endl;
search = Inventory.at(listPos-1);
//cout<< "contents of Search: "<< search << endl;
delete search;
Inventory.erase(Inventory.begin() + (listPos -1));
}
else{
cout << "Error"<<endl;
}
}
else if ( UserInput == "print") {
PrintEverything(Inventory);
}
else if ( UserInput != "quit"){
}
}
return 0;
}
This is a compile error.
Remove line 85: newItem.at(listPos - 1); and it runs just fine in visual studio.
The issue is that newItem is a pointer to an element. I assume you meant to use Inventory here instead. However, that logic was already done on the previous line.
On a side note, I stongly advise against storing owning pointers like this. There's no good reason in this case not to just use vector<UnSold> instead.
else if ( UserInput == "sell") {
cout << "List Positon: ";
cin >> listPos;
if ( listPos < Inventory.size()){
cout << " Item Sold and Removed from list position " << listPos <<endl;
search = Inventory.at(listPos-1);
//cout<< "contents of Search: "<< search << endl;
delete search;
Inventory.erase(Inventory.begin() + (listPos -1));
Here you mix the use of listPos and listPos - 1.
If you're allowing the user to input position 0 indexed, then
Inventory.at(listPos-1) should be Inventory.at(listPos) and
Inventory.erase(Inventory.begin() + (listPos -1)) should be Inventory.erase(Inventory.begin() + (listPos)).
If you're letting them input the position with the indexing starting at 1, then
if (listPos < Inventory.size()) should be
if(listPos <= Inventory.size() && listPos > 0)

Bookshelf Data Structures Issues

I am making a bookshelf of width size s(1<s<100). Add book id and the book width at the leftmost of the vector. If you add a book which causes the width to be exceeded, then delete the rightmost book until the book to be added can be put on the shelf. In the end, the remaining books on the bookshelf can be added.
The issue I am facing that when var = 'E' the program should display the remaining books on the shelf and then exit that problem and go to a different problem, but when 'E' is entered the remaining books on the shelf will not display, and the program will not exit. I have tried messing with the while loops condition that is nested in the overall while loop.
#include <iostream>
#include <vector>
using namespace std;
struct book{
int id;
int w;
};
int main(){
//std::vector::~vector
//create instance of book
book my_book;
//initialize the placeholders
int s, removed_book, back_width;
char var;
//create the vector
vector<book>shelf;
while(true){
//enter the s value
s = 0;
cout << "enter the s value: " << endl;
cin >> s;
int w_total = 0;
//be able to exit the program
if(s == -1){
return 0;
}
int x = 1;
//while remaining space
while(x!=0){ //need to fix this up
cout << "enter the action(A,R,E): " << endl;
cin >> var >> my_book.id >> my_book.w;
//if A
if(var == 'A'){
//get info about the book
/*
cout << "enter id: " << endl;
cin >> my_book.id;
cout << "width(w): " << endl;
cin >> my_book.w;
*/
w_total += my_book.w;
shelf.insert(shelf.begin(),my_book);
cout << "total width(1): " << w_total << endl;
if(w_total > s){
while(w_total >= s){
//remove the rightmost(back) book
w_total = w_total - shelf.back().w;
cout << "total width(2): " << w_total << endl;
shelf.erase(shelf.end()-1);
}
}
}
//if R
else if(var == 'R'){
//cout << "which book to be removed? : " << endl;
//cin >> removed_book;
removed_book = my_book.id;
for(int i = 0; i < s; i++){
if(shelf[i].id == removed_book){
shelf.erase(shelf.begin()+i);
}
}
}
//if E
else if(var == 'E'){
cout << "remaining books on shelf: " << endl;
for(int i = 0; i < shelf.size(); i++){
if(shelf[i].id!=0){
cout << "id: "<<shelf[i].id << endl;
}
}
//maybe put the display in here?
x = 1;
}
}
//print out the remaining shelf
shelf.clear();
//erase the shelfs(vectors) contents
//increase problem number
}
return 0;
}
Expected output:
10(shelf width)
A 1 3(Add id width)
A 2 5
E
-->PROBLEM 1: 2 1
cin >> var >> my_book.id >> my_book.w is asking the user to enter three things: a character and two integers. You have to enter all three before the action in var will be checked and acted upon.

What is a deleted function, and why only my functions that I pass files into are considered deleted? [duplicate]

This question already has answers here:
Using fstream Object as a Function Parameter
(3 answers)
Closed 6 years ago.
#include <bits/stdc++.h>
using namespace std;
class contact {
private:
vector< pair<string, int> > contact_info;
public:
void add_contact(string contact_name, int contact_number) {
contact_info.push_back(make_pair(contact_name, contact_number));
sort(contact_info.begin(),contact_info.end());
}
void edit_contact(string contact_name) {
int found_at;
for (unsigned int i =0; i < contact_info.size(); i++) {
if (contact_info[i].first == contact_name) {
found_at = i;
}
}
if (contact_info[found_at +1].first == contact_name) {
int choice;
int counter = found_at;
int index = 1;
while (contact_info[counter].first == contact_name) {
cout << index << ". " << contact_info[counter].first << " " << contact_info[counter].second;
counter++;
index++;
}
cout << "Choose any please: ";
cin >> choice;
found_at = found_at - (choice - 1);
}
cout << "Enter the new number: ";
cin >> contact_info[found_at].second;
}
void show_all() {
for (unsigned int i =0; i < contact_info.size(); i++) {
cout << contact_info[i].first << " " << contact_info[i].second << endl;
}
}
void delete_contact(string contact_name) {
int found_at;
for (unsigned int i =0; i < contact_info.size(); i++) {
if (contact_info[i].first == contact_name) {
found_at = i;
}
}
if (contact_info[found_at +1].first == contact_name) {
int choice;
int counter = found_at;
int index = 1;
while (contact_info[counter].first == contact_name) {
cout << index << ". " << contact_info[counter].first << " " << contact_info[counter].second;
counter++;
index++;
}
cout << "Choose any please: ";
cin >> choice;
found_at = found_at - (choice - 1);
}
contact_info.erase(contact_info.begin()+found_at);
}
void writeFile(ofstream contact_file) {
for (unsigned int i =0; i < contact_info.size(); i++) {
contact_file << contact_info[i].first << " " << contact_info[i].second << endl;
}
}
void readFile(ifstream contact_file) {
string input;
while (!contact_file.eof()) {
contact_file >> input;
size_t pos = input.find(" ");
string name = input.substr(0,pos);
string number_str = input.substr(pos);
int number = stoi(number_str) ;
contact_info.push_back(make_pair(name,number));
}
}
};
int main()
{
int choice;
ifstream contacts_file_read;
contacts_file_read.open("contacts.txt");
ofstream contacts_file_write;
contacts_file_write.open("contacts.txt");
bool in_prog = true;
contact contacts;
string name;
int number;
while (in_prog) {
cout << "1. Add contacts" << endl
<< "2. Edit contact" << endl
<< "3. Delete contact" << endl
<< "4. Show all" << endl
<< "5. exit" << endl;
cout << "Your choice: ";
cin >> choice;
contacts.readFile(contacts_file_read);
if (choice == 1) {
cout << "Enter name & number separated by a space: ";
cin >> name >> number;
contacts.add_contact(name, number);
} else if (choice == 2) {
cout << "Enter name of contacts to be edited: ";
cin >> name;
contacts.edit_contact(name);
} else if (choice == 3) {
cout << "Enter name of contact to be deleted: ";
cin >> name;
contacts.delete_contact(name);
} else if (choice == 4) {
contacts.show_all();
} else if(choice == 5) {
contacts.writeFile(contacts_file_write);
} else {
cout << "Wrong choice" << endl;
}
}
return 0;
}
So, I was asked in my programming class to make a phone book application in C++ using only objects, so this is my attempt at it.
All functions are good, I did recompile the program after finishing each function at it gave me 0 errors, however whenever I try to call writeFile or readFile function that were previously working fine, now the compiler gave me an error of "error: use of deleted functions... "
I don't know what are deleted functions and why only functions that take file objects as an argument are treated as such.
Can anyone please help?
Thanks.
Objects of type std::ifstream are not copyable -- indeed, the object represents the unique handle of an open file, and it would be difficult to conceptualize what it would mean to copy such unique responsibility.
Indeed, this inability to copy an object is encoded by making the copy constructor deleted, which causes the error that you see when you do attempt to copy it.
Your code should pass the original ifstream, not a copy (by taking a reference parameter):
void readFile(ifstream & contact_file)
// ^^^^^^^^^^

How to alphabetize a list on C++

I have been having some trouble on my code for my final project. I have looked everwhere and I am having a hard time so I thought I would ask on here. I need to make sure that when all the names are listed in this phonebook that they will come out in alphabetical order but as of yet I am unsure how to do that. Here is the program that i currently have! Thank you!
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
using namespace std;
struct Contact {
string name, number, notes;
};
Contact contactList[100];
int rec_num = 0;
int num_entries;
string toUpper (string S) {
for (int i= 0; i < S.length(); i++)
S[i] = toupper(S[i]);
return S;
}
void ReadFile () {
string S;
fstream input("PhoneData.txt");
while (!input.eof() && !input.fail()){
input >> contactList[rec_num].name >> contactList[rec_num].number;
getline(input, S);
contactList[rec_num].notes = S;
rec_num++;
}
cout << "Book read." << endl;
num_entries = rec_num;
input.close();
return;
}
// stores phonebook for future runs of the program
void StoreFile () {
fstream F ("PhoneData.txt");
rec_num = 0;
while (rec_num < num_entries){
F << contactList[rec_num].name << " " << contactList[rec_num].number << " " << contactList[rec_num].notes << " " << endl;
rec_num++;
}
cout << "Phonebook stored." << endl;
return;
}
// adds contact
void add_name(string name, string number, string notes){
contactList[num_entries].name = name;
contactList[num_entries].number = number;
contactList[num_entries].notes = notes;
num_entries++;
return;
}
// finds contact
void retrieve_name(string name){
for (int i = 0; i < num_entries; i++){
if (toUpper(contactList[i].name) == toUpper(name)) {
cout << "Phone Number: " << contactList[i].number << endl << "Notes: " << contactList[i].notes << endl;
return;
}
}
cout << "Name not found" << endl;
return;
}
// updates contact info
void update_name(string name){
string new_number;
string new_notes;
cout<<"New Phone Number"<<endl;
cin>> new_number;
cout<<"New Notes"<<endl;
cin>> new_notes;
for (int i = 0; i < num_entries; i++){
if (toUpper(contactList[i].name) == toUpper(name)) {
contactList[i].number = new_number;
contactList[i].notes = new_notes;
return;
}
}
}
// deletes contact
void delete_name(string name){
int INDEX=0;
for (int i = 0; i < num_entries; i++){
if (toUpper(contactList[i].name) == toUpper(name)) {
INDEX=i;
for ( int j=INDEX; j < num_entries; j++ ){
contactList[j].name = contactList[j+1].name;
contactList[j].number = contactList[j+1].number;
contactList[j].notes = contactList[j+1].notes;
}
}
}
return;
}
void listAllContacts() {
int i = 0;
while (i < num_entries) {
cout << "-- " << contactList[i].name << " " << contactList[i].number << endl << "-- " << contactList[i].notes << endl << endl;
i++;
}
}
int main(){
string name, number, notes;
string FileName;
char command;
FileName = "PhoneData.txt";
ReadFile ();
cout << "Use \"e\" for enter, \"f\" for find, \"l\" for list, \"d\" for delete, \"u\" for update, \"s\" for send message, \"q\" to quit." << endl << "Command: ";
cin >> command;
while (command != 'q'){
switch (command){
case 'e': cin >> name; cout << "Enter Number: ";
cin >> number; cout << "Enter Notes: ";
cin.ignore(); getline(cin, notes);
add_name(name, number, notes); break;
case 'f': cin >> name; retrieve_name(name); break;
case 'l':
listAllContacts(); break;
case 'u': cin>> name; update_name (name);break;
case 'd' : cin>> name; delete_name (name); break;
}
cout << "\nCommand: "; cin >> command;
}
StoreFile();
cout << "All set !";
return 0;
}
Given
Contact contactList[100];
int num_entries;
you can use std::sort to sort the list of contacts. std::sort has two forms. In the first form, you can use:
std::sort(contanctList, contactList+num_entries);
if you define operator< for Contact objects.
In the second form, you can use:
std::sort(contanctList, contactList+num_entries, myCompare);
if you define myCompare to be callable object that can compare two Contact objects.
To use the first form, change Contact to:
struct Contact {
string name, number, notes;
bool operator<(Contact const& rhs) const
{
return (this->name < rhs.name);
}
};
If you want to the comparison of names to be case insensitive, convert both names to either uppercase or lowercase and them compare them.