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

335 views Asked by At

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];  
1

There are 1 answers

6
Cheers and hth. - Alf On BEST ANSWER

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.