Search and delete in struct vector

Hi everyone!
I have been cracking my head for some hours now trying to figure out how to do one part of my assignment.

Problem: I have a struct of persons who have names, signatures and height. I want to search for the database(struct) by signature. If i see the signature, i print the signature, name and height.

Here is my try

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
  // Struct
struct Database
{
	string firstName;
	string lastName;
	string signature;
	double height;
};

// my vector
vector<Database> people;

// my search function
void searchPerson(vector<Database> &vec)
{
  string signSearch;
  cout << endl << " Enter the signature of the person to search (xxxyyy00): ";
	getline(cin, signSearch);


	for (size_t i = 0; i < vec.size(); i++)  //loop through vec and search
	{
		if (vec[i].signature == signSearch)
		{
			cout << " Signature" << setw(20) << " Name " << setw(25) << right << " Height" << endl;
			cout << vec[i].signature << setw(20) << vec[i].firstName + " " + vec[i].lastName << setw(25)
				<< right << vec[i].height << endl << endl;
		}
		else
		{
			cout << "\n No person in the list has the signature " << signSearch << endl;
		}
	}
	cout << "\n Press \"ENTER\" to go to the menu ";
	cin.get();
}


I have seen a lot of complicated algorithms online on how to do this stuff. But i have hope that this can work. I have some results like this


// This is a sample list to begin with
**************************** NAME LIST ******************************
 Number of persons in the list: 7

 Nr      Signature                                   Name            Height[m]
 ------------------------------------------------------------------------------
 1.       liomes01                            Lionel Messi                 1.7
 2.       ardtur02                              Arda Turan                1.77
 3.       riymah03                            Riyad Mahrez                1.82
 4.       brifel04                             Brian Felix                0.89
 5.       ekxdon05                              Ek Donatus                1.23
 6.       boxekx06                                   Bo EK                1.77
 7.       evakas07                                Eva Kask                1.67


Enter the signature of the person to search (xxxyyy00): liomes01
 Signature               Name                    Height
liomes01        Lionel Messi                      1.7


 No person in the list has the signature liomes01

 No person in the list has the signature liomes01

 No person in the list has the signature liomes01

 No person in the list has the signature liomes01

 No person in the list has the signature liomes01

 No person in the list has the signature liomes01

 Press "ENTER" to go to the menu


I don't understand why the else option keep evaluating! Meanwhile, when i search the last person

Enter the signature of the person to search (xxxyyy00): evakas07

 No person in the list has the signature evakas07

 No person in the list has the signature evakas07

 No person in the list has the signature evakas07

 No person in the list has the signature evakas07

 No person in the list has the signature evakas07

 No person in the list has the signature evakas07
 Signature               Name                    Height
evakas07            Eva Kask                     1.67


 Press "ENTER" to go to the menu


I have tried many options. I even used
1
2
3
 
else
   continue;


Which stopped the repeated printing of

No person in the list has the signature


But that does not fullfill the program requirement. i.e. The user must be informed whether the search was ok or not.

Please, i need your advice
Thanks in advance
Last edited on
closed account (48T7M4Gy)
HINT: Maybe you could get the loop to break; once an entry is found. You then might look at your logic in more detail by following the 'recipe' on paper step by step. ;)
Last edited on
OP: also try printing out the vector just to make sure all the names have been read in correctly
@kemort
Yes, i tried to put the break like this
1
2
3
4
5
6
7
8
9
10
11
12
13
for (size_t i = 0; i < vec.size(); i++)
{
	if (vec[i].signature == signSearch)
	{
	   cout << " Signature" << setw(20) << " Name " 
                 << setw(25) << right << " Height" << endl;
	   cout << vec[i].signature << setw(20) << 
                      vec[i].firstName + " " + vec[i].lastName 
                     << setw(25)<< right << vec[i].height << endl;
		break;
	}
	else
	    cout << "\n No person in the list has the signature " << signSearch << endl;


And it works well if the entery is the first in the list like this

 Enter the signature of the person to search (xxxyyy00): liomes01
 Signature               Name                    Height
liomes01        Lionel Messi                      1.7



which is what i expect the program to do. But for another entry, it keeps on printing the else option like this


 Enter the signature of the person to search (xxxyyy00): brifel04
 No person in the list has the signature brifel04
 No person in the list has the signature brifel04
 No person in the list has the signature brifel04
 Signature               Name                    Height
brifel04         Brian Felix                     0.89


And for a non-existent person, it does prints the else option 7 times.
@gunnerfunner,
yes, it does print all the persons with
1
2
3
4
5
6
7
8
9
for (size_t i = 0; i < vec.size(); i++)
{
    cout << " Signature" << setw(20) << " Name " 
             << setw(25) << right << " Height" << endl;
    cout << vec[i].signature << setw(20) 
           << vec[i].firstName + " " + vec[i].lastName 
           << setw(25)<< right << vec[i].height << endl;
		break;
	}

Gives this as output
Signature               Name                    Height
liomes01        Lionel Messi                      1.7

 Signature               Name                    Height
ardtur02          Arda Turan                     1.77

 Signature               Name                    Height
riymah03        Riyad Mahrez                     1.82

 Signature               Name                    Height
brifel04         Brian Felix                     0.89

 Signature               Name                    Height
ekxdon05          Ek Donatus                     1.23

 Signature               Name                    Height
boxekx06               Bo EK                     1.77

 Signature               Name                    Height
evakas07            Eva Kask                     1.67


Which tells me that this for loop reads everything in the list.
Something wrong somewhere.
Last edited on
Use a boolean to record whether or not you find a match:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
bool match = false;
    for (size_t i = 0; i < vec.size(); i++)
	{
		if (vec[i].signature == signSearch)
		{
			cout << " Signature" << setw(20) << " Name " << setw(25) << right << " Height" << endl;
			cout << vec[i].signature << setw(20) << vec[i].firstName + " " + vec[i].lastName << setw(25)
				<< right << vec[i].height << endl << endl;
            match = true;
			break;
		}
	}
    if (match == false)
    {
			cout << "\n No person in the list has the signature " << signSearch << endl;
    }


Note I've left the break in the code so that it stops after the first match is found, without it multiple matches could be

found if they exist
Look at line 23 in your OP. You're comparing an entry in the vector to what the user entered. So far so good. However at line 29 you have an else condition. That means effectively:
 
if (vec[i].signature != signSearch)

So you're outputting "Not found" whenever any entry in the vector doesn't match what the user entered. You don't want to display "Not found" until you've searched the entire vector.




@gunnerfunner, thanks! That solves my problem. I had tried a similar boolean but i had it inside the for loop which was doing exactly the same thing as without it.

@AbstractionAnon, exactly that is what i was allowing my else to do. Foolish me. I have learned my lesson! But how could i make the else not to behave like if (vec[i].signature != signSearch)?

These few lines have saved me from the rather complicated algorithms that i see online for similar problems.

Thanks guys for your input.
But how could i make the else not to behave like if (vec[i].signature != signSearch)?

You're missing the point. You don't want to display "Not found" in the else. You want to put the display for "Not Found" AFTER the loop as gunnerfunner suggested.

IMO, you're trying to do too much in SearchPerson(). 1) Prompt for the search criteria, 2) Search, 3) Display the output (if found) 4) Display "Not found" if not found and 5) prompt for ENTER to continue. The simpler you make your functions, the easier they are to debug.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
#include <vector>
#include <iomanip>
#include <string>
using namespace std;

// Struct
struct Database
{   string firstName;
	string lastName;
	string signature;
	double height;
	
	void Display (ostream & os) const;  // Function to display an entry
};

// my vector
vector<Database> people;

void Database::Display (ostream & os) const
{   os << " Signature" << setw(20) << " Name " << setw(25) << right << " Height" << endl;
	os << signature << setw(20) << firstName << " " << lastName << setw(25)
	   << right << height << endl << endl;
}

//  Return a pointer to the database entry (if found)
Database * Find (vector<Database> & vec, const string & sig)
{   for (size_t i = 0; i < vec.size(); i++)  //loop through vec and search
	{   if (vec[i].signature == sig)
		    return &vec[i];		
	}
    return NULL;    //  No found
}
    
// my search function
void searchPerson (vector<Database> &vec)
{   string signSearch;
    Database *  dbentry;
    
    cout << endl << " Enter the signature of the person to search (xxxyyy00): ";
	getline(cin, signSearch);
    dbentry = Find (vec, signSearch);
    if (dbentry)
        dbentry->Display (cout);
    else        
        cout << "\n No person in the list has the signature " << signSearch << endl;	
}
@AbstractionAnon, thanks for the tips.

This function i just asked for help is actually just 1 of 22 functions that i have already made for a project in an intro to c++ course. If i have to separate everything, then i end up with... maybe an app (laughs).

Yes you are right, debugging can be very difficult with my way of work. I have to consider splitting it as rightly suggested.

Your solution seem to contain some advanced concepts but clear enough to understand. Thanks for a second look!
closed account (48T7M4Gy)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <iostream>
#include <string>
#include <vector>
#include <iomanip>

using namespace std;

// Struct
struct Database
{
    string firstName;
    string signature;
};

void searchPerson(vector<Database> );

int main()
{
    // my vector
    vector<Database> people;
    Database temp;
    
    // JUST SOME SIMPLE TEST DATA
    temp.firstName = "one";temp.signature = "on"; people.push_back(temp);
    temp.firstName = "two";temp.signature = "tw"; people.push_back(temp);
    temp.firstName = "thr";temp.signature = "th"; people.push_back(temp);
    temp.firstName = "fou";temp.signature = "fo"; people.push_back(temp);
    
    searchPerson(people);
    
    return 0;
}

// my search function
void searchPerson(vector<Database> vec)
{
    bool found = false;
    
    string signSearch;
    cout << endl << " Enter the signature of the person to search (xxxyyy00): ";
    getline(cin, signSearch);
    
    
    for (size_t i = 0; i < vec.size(); i++)  //loop through vec and search
    {
        if (vec[i].signature == signSearch)
        {
            cout << " Signature" << setw(20) << " Name " << endl;
            cout << vec[i].signature << setw(20) << vec[i].firstName << endl;
            found = true;
            break;
        }
    }
    
    if( !found )
        cout << "\n No person in the list has the signature " << signSearch << endl;
    
    cout << "\n Press \"ENTER\" to go to the menu ";
    cin.get();
}
EDIT: Question title edited

Sorry for not including the full corrected answer.
@Kemort, thanks for doing that for me :).

I wished i had followed the tips from AbstractionAnon. It could have been a lot easier to do the other part of the work, i.e. deleting a particular person based on signature.

I provide here, the other part of the work, i.e deleting an entry (just the function). I do this because, this is quite simple and straight forward for a beginner like me and many others.
NB: To test this, just place it under kemort's solution and everything will be fine
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function prototyp 
void deletePerson(vector<Database> &vec); // put before main()
// function definition
void deletePerson(vector<Database> &vec)
{
// Get signature to search
string signSearch;
cout << " Enter the signature of the person you want to delete: ";
getline(cin, signSearch);

bool signIndex = false;
for (size_t i = 0; i < vec.size(); i++)  // Go through vec and search for signSearch
{
	if (vec[i].signature == signSearch) // if index found
	{
		cout << "\n "  << vec[i].firstName + 
			" " +vec[i].lastName << " deleted!" << endl;  // Inform user of action
		vec.erase(vec.begin() + i);  // deleting the entery
		signIndex = true;
		break;
	}
}
// signSearch not in the list
if (!signIndex)
	cout << " No person with signature "
	<< signSearch << " in the list!" << endl;
}

 Enter the signature of the person you are want to delete: on

 one  deleted!

This does the work and it is 50x easier to visualize (at least as a begninner) than this
http://stackoverflow.com/questions/32062126/how-to-remove-a-struct-element-from-a-vector
Last edited on
Topic archived. No new replies allowed.