Impossible to catch value of i when he finds an existing name

HI all of you.This file works well. Many trials to catch the value of i. Is there somebody to help me find. Many Thanks. Here is the code :
/*ref.cpp*/
#include<list>
#include<iostream>
#include<string>
using namespace std;
void pause()
{
cout << "Hit ENTER to continue\n";
cin.get();
}
struct Entry {
string name;
int number;
Entry(const string& n, int i) :name(n), number(i) { }
};
list<Entry> phone_book;
void print_entries()
{
typedef list<Entry>::const_iterator LI;

for (LI i = phone_book.begin(); i != phone_book.end(); ++i) {
const Entry& e = *i; // reference used as shorthand
cout << '{' << e.name << ' ' << e.number << "}\n";
}
cout <<endl;
}

void print_entry(const string& s)
{
typedef list<Entry>::const_iterator LI;

for (LI i = phone_book.begin(); i != phone_book.end(); ++i) {
const Entry& e = *i; // reference used as shorthand
if (s == e.name) {
cout << e.name << ' ' << e.number << '\n';
//cout << *i;// error: no match for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream<char>}’ and ‘const Entry’)
//cout <<LI;// error:expected primary-expression before ‘;’ token
//cout << i;//no match for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream<char>}’ and ‘LI {aka std::_List_const_iterator<Entry>}’)
//cout << const_iterator;// does not work
//cout << const_iterator LI;//does not work
//cout << iterator;//does not work
return;
}
}

cout <<endl;
}
void f(const Entry& e, list<Entry>::iterator i, list<Entry>::iterator p)
{
phone_book.push_front(e); // add at beginning
phone_book.push_back(e); // add at end
phone_book.insert(i,e); // add before the element referred to by `i'

phone_book.erase(p); // remove the element referred to by `p'
}

int main()
{

phone_book.push_back(Entry("one",111));
phone_book.push_back(Entry("two",222));
phone_book.push_back(Entry("three",333));
phone_book.push_back(Entry("four",444));
phone_book.push_back(Entry("five",555));
//advance(j,7);//qu'il soit ou pas, ça marche pareil
Entry six("six",666);
print_entries();
pause();
cout <<"FUNCTION f(six,phone_book.begin(),phone_book.begin());\n";
f(six,phone_book.begin(),phone_book.begin());
print_entries();
pause();
print_entry("four");
print_entry("seven");
print_entry("three");
print_entries();// I added
print_entry("aubertin");
print_entry("seven");
pause();
cout << "Now one insertion(one)(third)\n";
list<Entry>::iterator it= phone_book.begin();//go to the begining of the list
advance(it, 2);
phone_book.insert(it, Entry("one",111));
print_entries();
cout << "Now one erase\n";
list<Entry>::iterator ip= phone_book.begin();//define itrator and go to the begining of the list
advance(ip,1);
phone_book.erase(ip);//erase second
print_entries();
pause();
cout << "Now one erase\n";
list<Entry>::iterator p= phone_book.begin();//define and go to the begining of the list
phone_book.erase(p); //erase first
print_entries();
pause();
cout <<"FUNCTION f(seven,phone_book.begin(),phone_book.erase(j));\n";
Entry seven("seven",777);
list<Entry>::iterator j= phone_book.begin();//define iterator and go to the begining of the list
f(seven,phone_book.begin(),phone_book.erase(j));//works well
//f(seven,phone_book.erase(j),phone_book.begin);//does not work
print_entries();
return 0;
}
Hello

First some general comments before providing an actual solution to 'catch value of i':

1. please indent your code and use code tags when posting, it makes reading so much easier;
2. think about the design of your program carefully - here implementation and interface are mixed up since phone_book (an instance of list<Entry>) is forward declared within the implementation section of your code and you had to do it to be able to define your print_entries(), print_entry() and f() functions. However this is going to be problematic going forward if you ship your program to a client, how is s/he going to know what phone_book is given just the interface;
3. you should also keep the data members (here, name and number) private as much as possible in line with the general principles of OOP;
4. also it would be good practice to separate your program into a header file, an implementation file and then the main function itself that calls the class/structure methods - a simple search will list out the benefits of doing this;
5. also think of overloading operators like <<, == etc to accomplish tasks like printing your data, comparisons etc. That way you can write member methods (for ==) or friend functions (for <<) instead of non-member, non-friend functions like you've done;
6. code below tries to incorporate these points and uses post C++11 tools like range loops. Please make sure your compiler supports that or you can use iterators like you'd done before;
7. finally, I am not sure what your function f() is trying to achieve, if you explain it more clearly I can try and re-work it or you might be able to do it yourself from here on

Header File:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
#ifndef PHONEBOOK_HEADER_
#define PHONEBOOK_HEADER_

class Entry {
    private:
    std::string m_name;
    int m_number;

    public:
    Entry(const std::string& name, int number) :m_name(name), m_number(number) { }
    bool operator == (std::string rhs)const;
    int GetNumber()const;
    friend std::ostream& operator<<(std::ostream& os, const Entry& e);
};
#endif 

Implementation File:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<iostream>
#include "Phonebook_header.h"
#include<string>
using namespace std;

bool Entry::operator==(std::string rhs)const{
        return m_name == rhs;
    }

int Entry::GetNumber()const{
    return m_number;
    }

std::ostream& operator<<(std::ostream& os, const Entry& e){
    os<<e.m_name<< "\t"<<e.m_number<<endl;
    return os;
}

int main()
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
#include<list>
#include<iostream>
#include "Phonebook_header.h"
#include<string>
using namespace std;

int main(){
list<Entry> phone_book;

phone_book.push_back(Entry("one",111));
phone_book.push_back(Entry("two",222));
phone_book.push_back(Entry("three",333));
phone_book.push_back(Entry("four",444));
phone_book.push_back(Entry("five",555));

for (auto& itr: phone_book){
    cout<<itr;
    }
    cout<<endl;

int match = 0; 
for (auto& itr: phone_book){
   if(itr == "three"){
    cout<<"There is a match and it's corresponding number is "<<itr.GetNumber()<<endl;
    match ++;
   }
}
if(match==0){
        cout<<"There is no match"<<endl;
    }

}

Last edited on
I thank you very much for your cooperation. I tried already to use code tags but I am lost with the lot of information I got. Maybe you can give me some simple information about this code tags. Thanks again
For help on how to use code tags, see:

http://www.cplusplus.com/articles/z13hAqkS/
To gunnerfunner. Excuse me to be so late. 1. I made refer.cpp with vim and g++ compiler. Is it possible , with vim , using ctrl K and set:nu , to get a tagged code ?? 2. I did not see your answer about catching value of i . 3. For your 3 files I had to use Code::blocks. But he gives an error in main, line 16:for (auto& itr: phone_book){ Can you debug that for me. Many thanks
1. I have not used vim, so I'm not able to help you on this;

2. By catching value of i my assumption is that you want to get the number for a corresponding name, this is given by line 24 (if there's a match) or line 29 (if there's no match) in my int main()

3. What is the error message that you're getting? I just re-ran my project using CodeBlocks and it worked fine. Under Settings->Compiler...->Compiler settings -> Compiler Flags ... please ensure that g++ follows the C++11 standard (see pt. 6 in my previous post)
To gunnerfunner. Excuse me to be so late. 1. I made refer.cpp with vim and g++ compiler. Is it possible , with vim , using ctrl K and set:nu , to get a tagged code ??

Code tags aren't something you put in your code. They're something you put in your post on this forum to make your code readable.

Did you read the link I posted?
To gunnerfunner. I got new OS Linux 16.04. Code::Blocks is very new. My problem is that I cannot Build. In the "Project build options" the only one enabled is: "enabdle all commun compiler warnings". You should be very kind to give me all the options I must enable. I know it is a big work, so I thank you very much in advance.
You do not need Code::Blocks. Plain g++ is sufficient. What are the filenames that you do have created?

Lets assume that they were:
1
2
3
foo.h   // the header
foo.cpp  // the implementation
bar.cpp  // the main() 


g++ -Wall -Wextra -std=c++11 -o myprog bar.cpp foo.cpp


Do also do
man g++

and browse/search until you find the description of option -std and the values that it does support. The c++11 is the minimum, but if c++14 is there, then use that, etc.
To keskiverto. I executed your instructions. Now I see no bug anywhere, with Code::Blocks. But when I run the program, I don't see any console. As I am a beginner with Code::Blocks, there is an error probably when establishing the project (name, path, etc). Thanks for your cooperation.
To gunnerfunner. No bug in your project but build fails: in main.cpp "indefinite reference to Entry::operator ==std::_cxx11 basic_string etc . Your implementation file is source or empty?? Many thanks for your reply.
In the "main file" there is:
1
2
3
4
#include<list>
#include<iostream>
#include "Phonebook_header.h"
#include<string> 

During compilation the preprocessor replaces each include pragma with the contents of included file. Lets do it for the line 3:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include<list>
#include<iostream>

class Entry {
    private:
    std::string m_name; // What is this std::string ? Error
    int m_number;

    public:
    Entry(const std::string& name, int number) :m_name(name), m_number(number) { }
    bool operator == (std::string rhs)const;
    int GetNumber()const;
    friend std::ostream& operator<<(std::ostream& os, const Entry& e);
};

#include<string> // too late for Entry 


We could reorder the "main file" into:
1
2
3
4
#include<list>
#include<iostream>
#include<string>
#include "Phonebook_header.h" 

That would remove the issue from the "main file", but why should every user (file) of the "Phonebook_header.h" have to look what headers to include before it?

No, the header should have minimum necessary definitions within it.

The std::string is a must. We cannot compute the size of an Entry object if we do not know the size of std::string object.

We do not need to know the size or members of std::ostream because we have only a reference to such objects, but we need to tell the compiler that std::ostream is a typename. We must forward declare it (unless we define it).

Hence, the "Phonebook_header.h" needs two lines before class Entry:
1
2
#include<iosfwd> // forward declares ostream
#include<string> // defines string 

sylvian: as mentioned I had no problems running this program on CodeBlocks, if your compiling/linking environment is different please make the necessary changes
To keskiverto. 1. I applied your modifications. Always Build fails. Maybe I put an error. So if you have time go to Code::Blocks and apply your idea. 2. Till now, I had no answer to my first problem in my file."impossible to catch value etc ". If you have an answer please let me know. Many thanks
Perhaps you could explain your problem a little more clearly?

Also, if you used code tags to make your code readable, more people would be likely to read it and help you.
Topic archived. No new replies allowed.