How do I search for a string in a data structure by use of loops?

Hello,

I am writing code for a series of phone records. I am trying to use a search for a string using pointers to a data structure. I thought that by looping through a structure and looking for a string that matches a string addressed by a pointer would be the way forward. But all I do is continually loop through and skip all the strings.

Any ideas? I thought I might try using standard library functions with <string> would help/

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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <string>

using namespace std;

struct TeleType
{
	string name;
	string phoneNo;
	TeleType *nextaddr;
};

void display(TeleType *); // function prototype
void find_record(TeleType *);//function prototype for search function

int main()
{
	TeleType t1 = { "Acme, Sam","(555) 898-2392" };
	TeleType t2 = { "Dolan, Edith","(555) 682-3104" };
	TeleType t3 = { "Lanfrank, John","(555) 718-4581" };
	TeleType *first; // create a pointer to a structure

	first = &t1; // store t1's address in first

	t1.nextaddr = &t2; // store t2's address in t1.nextaddr
	t2.nextaddr = &t3; // store t3's address in t2.nextaddr
	t3.nextaddr = NULL; // store the NULL address in t3.nextaddr

	display(first); // send the address of the first structure
	find_record(first);

	system("pause");

	return 0;
}

void display(TeleType *contents) // contents is a pointer to a
{ // structure of type TeleType

	while (contents != NULL) // display until end of linked list
	{
		cout << endl << setiosflags(ios::left)
			<< setw(30) << contents->name
			<< setw(20) << contents->phoneNo;

		contents = contents->nextaddr; // get next address
	}

	cout << endl;

	return;
}

void find_record(TeleType *contents) // contents is a pointer to a
{ // structure of type TeleType

	string text_to_search_for;

	cout << "What name are you looking for?" << endl;
	getline(cin, text_to_search_for);

	string *ptr_to_string = &text_to_search_for;

	while (contents != NULL) // display until end of linked list
	{

		if (*ptr_to_string == contents->name)
		{
			cout << endl << setiosflags(ios::left)
				<< setw(30) << contents->name
				<< setw(20) << contents->phoneNo;
		}
		else
		{
			contents = contents->nextaddr; // get next address
		}
	}

	cout << endl;
}
Hello,

I managed to solve it by use of the .compare() operator. But it only works if the characters are the same case. How could I improve this to get around? Perhaps by converting all text into lower case first, and then searching that way?
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
61
62
63
64
#include <iostream>
#include <iomanip>
#include <string>
#include <cctype>

struct TeleType
{
    std::string name;
    std::string phoneNo;

    TeleType* next = nullptr ;
};

void print( const TeleType& tt )
{
    std::cout << "name: " << std::left << std::setw(20) << tt.name
              << "phone: " << tt.phoneNo << '\n' ;
}

void print_all( const TeleType* first )
{ for( const TeleType* p = first ; p != nullptr ; p = p->next ) print(*p) ; }

// compare two strings for equality ignoring case; return true if equal
static bool cmp_equal_ignore_case( const std::string& a, const std::string& b )
{
    if( a.size() != b.size() ) return false ; // strings of differing lengths are not equal

    for( std::size_t i = 0 ; i < a.size() ; ++i ) // compare each character, ignoring case
        if( std::tolower( a[i] ) != std::tolower( b[i] ) ) return false ; // mismatch, not equal

    return true ; // all characters were matched
}

// return nullptr if TeleType with searched for name is not found
const TeleType* find_by_name( const TeleType* first, std::string name )
{
    for( const TeleType* p = first ; p != nullptr ; p = p->next )
        if( cmp_equal_ignore_case( p->name, name ) ) return p ; // found it

    return nullptr ;
}

int main()
{
    TeleType c = { "Lanfrank, John", "(555) 718-4581", nullptr };
    TeleType b = { "Dolan, Edith", "(555) 682-3104", std::addressof(c) };
    TeleType a = { "Acme, Sam", "(555) 898-2392", std::addressof(b) };
    TeleType* first = std::addressof(a) ;

    print_all(first) ;


    std::string name_to_find ;
    std::cout << "\nWhat name are you looking for? " ;
    std::getline( std::cin, name_to_find ) ;

    const auto p = find_by_name( first, name_to_find ) ;
    if( p != nullptr )
    {
        std::cout << "found name '" << name_to_find << "' : " ;
        print(*p) ;
    }
    else std::cout << "did not find name '" << name_to_find << "'\n" ;
}
Last edited on
Hello,

JLBorges, That's what I was thinking of, searching char by char in the string. I just thought that there would be an in built function for it already in the standard library. But the simple idea of comparing lengths first to filter out was a great preceding idea.

Thanks a lot!
For bool cmp_equal_ignore_case( const std::string& a, const std::string& b )

Boost:
1
2
// http://www.boost.org/doc/libs/1_65_1/doc/html/boost/algorithm/iequals.html
return boost::iequals(a,b) ; // #include <boost/algorithm/string.hpp> 

Posix:

Microsoft:
1
2
// https://msdn.microsoft.com/en-us/library/k59z8dwe.aspx
return ::_stricmp( a.c_str(), b.c_str() ) == 0 ; // #include <string.h> 

Standard library:
1
2
3
// http://en.cppreference.com/w/cpp/algorithm/equall
return std::equal( a.begin(), a.end(), b.begin(), b.end(), 
                   []( char x, char y ) { return std::tolower(x) == std::tolower(y) ; } ) ;
Registered users can post here. Sign in or register to post.