OVH Cloud OVH Cloud

find()

27 réponses
Avatar
Nicolas Aunai
salut,


je ne comprends pas trop sur quoi se base la comparaison dans la
méthode find() de la classe algorithm de la stl.

si j'ai défini l'opérateur '==' pour ma classe, la méthode va-t-elle
l'utiliser ? si non dois-je lui présicer ? comment ?


de plus, si aucun élément n'est trouvé la méthode retourne-t-elle UN
iterateur sur la borne supérieure de l'intervalle de recherche, ou
retourne-t-elle LE itérateur qu'on avait passé en argument ? dans ce
dernier cas, il suffit de comparer le adresses des deux itérateurs pour
voir si la fonction a échoué, mais dans le premier cas, comment etre
sûr que l'iterateur retourné pointe vers le dernier membre de
l'intervalle parce qu'elle a rien trouvé, ou plutot parce que l'élément
recherché EST le dernier de l'intervalle ?


merci
a+

--
Nico,
http://astrosurf.com/nicoastro
messenger : nicolas_aunai@hotmail.com

10 réponses

1 2 3
Avatar
Anthony Fleury
Nicolas Aunai wrote:

salut,
Salut,


je ne comprends pas trop sur quoi se base la comparaison dans la
méthode find() de la classe algorithm de la stl.
Elle se base sur un opérateur ==.



si j'ai défini l'opérateur '==' pour ma classe, la méthode va-t-elle
l'utiliser ? si non dois-je lui présicer ? comment ?


Oui, elle va l'utiliser si il y a un opérateur ==.
Pour utiliser une autre méthode de comparaison que cet opérateur, il y a
find_if qui elle se base sur un prédicat, c'est à dire une fonction qui
renvoie un booléen. Elle cherchera la première séquence de qui renvoie true
et te renverra un itérateur sur celle ci.
find_if(debut, fin, p) avec debut ton itérateur de début, fin l'itérateur de
fin et p le prédicat.

de plus, si aucun élément n'est trouvé la méthode retourne-t-elle UN
iterateur sur la borne supérieure de l'intervalle de recherche, ou
retourne-t-elle LE itérateur qu'on avait passé en argument ? dans ce
dernier cas, il suffit de comparer le adresses des deux itérateurs pour
voir si la fonction a échoué, mais dans le premier cas, comment etre
sûr que l'iterateur retourné pointe vers le dernier membre de
l'intervalle parce qu'elle a rien trouvé, ou plutot parce que l'élément
recherché EST le dernier de l'intervalle ?


find recoit trois paramètres :
un itérateur de début, un itérateur de fin, et une valeur à chercher.
Si jamais la valeur n'est pas trouvé, c'est à dire que l'opérateur == qui
est le prédicat de find renvoie false dans tous les cas, alors elle renvoie
l'itérateur de fin.

Pour un vecteur d'entiers par exemple :
int n, x = 42;
vector<int> a(n);
// remplissage de a...
if(find(a.begin(), a.end(), x) == a.end())
// Echec de la recherche...

Si 42 n'est pas dans a vecteur, alors find te renvoie a.end(). il n'y a qu'à
tester cette valeur pour savoir si find a échouée ou pas.

En esperant avoir été à peu près clair...

Anthony
--
"I should have seen it would be this way
I should have known from the start what she's up to
When you have loved and you've lost someone
You know what it feels like to lose" -- The Rasmus

Avatar
Nicolas Aunai
Anthony Fleury a dit :


Pour un vecteur d'entiers par exemple :
int n, x = 42;
vector<int> a(n);
// remplissage de a...
if(find(a.begin(), a.end(), x) == a.end())
// Echec de la recherche...

Si 42 n'est pas dans a vecteur, alors find te renvoie a.end(). il n'y a qu'à
tester cette valeur pour savoir si find a échouée ou pas.




ok, mais l'iterateur a.end(), désigne-t-il l'adresse du dernier élément
? ou la dernière adresse de mon tableau ?

exemple, chaque x est une case du tableau et '.' son adresse

.x.x.x.

le a.end() est-il le dernier ou l'avant dernier '.' ?

car j'ai :

i = a.end();
r = find(a.begin(),i,c);

if(r == i) //placé en dernière position
{
cout << "derniere position" << endl;
if(*r == c) //si c a été trouvé
{

[...]


et ça plante a l'execution... comme si '*r' n'était pas une case de mon
tableau.
idem avec *(r-1)

--
Nico,
http://astrosurf.com/nicoastro
messenger :

Avatar
Nicolas Aunai
Nicolas Aunai avait soumis l'idée :


et ça plante a l'execution... comme si '*r' n'était pas une case de mon
tableau.
idem avec *(r-1)



ok c'est '*r' qu'il faut, l'erreur venait du fait que mon tableau était
vide.

--
Nico,
http://astrosurf.com/nicoastro
messenger :

Avatar
Anthony Fleury
Nicolas Aunai wrote:

Anthony Fleury a dit :


Pour un vecteur d'entiers par exemple :
int n, x = 42;
vector<int> a(n);
// remplissage de a...
if(find(a.begin(), a.end(), x) == a.end())
// Echec de la recherche...

Si 42 n'est pas dans a vecteur, alors find te renvoie a.end(). il n'y a
qu'à tester cette valeur pour savoir si find a échouée ou pas.




ok, mais l'iterateur a.end(), désigne-t-il l'adresse du dernier élément
? ou la dernière adresse de mon tableau ?



Non, a.begin() pointe sur le premier élement de ton tableau alors que
a.end() pointe sur l'élement *suivant* le dernier élement.
C'est pour ca que quand tu parcours un vecteur avec un itérateur i, tu fais
toujours :
for ( i = a.begin() ; i != a.end() ; i++)

Au passage, il y a deux autres membres dans la STL : a.front() et a.back().
Ces deux élements sont des _références_ sur le premier et le dernier
élement de ton conteneur.

exemple, chaque x est une case du tableau et '.' son adresse

.x.x.x.

le a.end() est-il le dernier ou l'avant dernier '.' ?



C'est donc avec ton image le dernier '.'

car j'ai :

i = a.end();
r = find(a.begin(),i,c);

if(r == i) //placé en dernière position
{
cout << "derniere position" << endl;
if(*r == c) //si c a été trouvé
{

[...]


et ça plante a l'execution... comme si '*r' n'était pas une case de mon
tableau.
idem avec *(r-1)

mais tu travailles sur quoi comme type en fait ?

Petit exemple avec un vector<int>. Si jamais tu travailles sur une autre
classe, ca dépend de tes itérateurs. Attention cet exemple est tout bête,
mais bon, ca illustre ce que je viens de dire :

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
vector<int> v(10);
for(int i = 0; i != 10; i++)
cin >> v.at(i);
// affiche bien tous les élements de ton tableau.
for(vector<int>::iterator i = v.begin() ; i != v.end(); i++)
cout << *i << " ";
cout << endl;
vector<int>::iterator a = find(v.begin(), v.end(), 42);
if(a == v.end())
cout << "non trouvé. Dernier élement :" << *--a << endl;
}

comme tu le vois donc sur cet exemple, pour afficher le dernier élement,
j'ai fait *--a qui s'écrit aussi *(a-1).
Si tu fais *a ca n'appartient pas à ton tableau car c'est la case d'après,
mais *(a-1) est valable dans ce cas.
Et donc cet élement est aussi accessible avec cout << v.back(); directement.

Anthony
--
"I should have seen it would be this way
I should have known from the start what she's up to
When you have loved and you've lost someone
You know what it feels like to lose" -- The Rasmus


Avatar
James Kanze
Nicolas Aunai writes:

|> Anthony Fleury a dit :

|> > Pour un vecteur d'entiers par exemple : int n, x = 42;
|> > vector<int> a(n); // remplissage de a...
|> > if(find(a.begin(), a.end(), x) == a.end())
|> > // Echec de la recherche...

|> > Si 42 n'est pas dans a vecteur, alors find te renvoie a.end(). il
|> > n'y a qu'à tester cette valeur pour savoir si find a
|> > échouée ou pas.

|> ok, mais l'iterateur a.end(), désigne-t-il l'adresse du dernier
|> élément ? ou la dernière adresse de mon tableau ?

Il designe en fait un élément au delà de la fin du tableau.

|> exemple, chaque x est une case du tableau et '.' son adresse

|> .x.x.x.

|> le a.end() est-il le dernier ou l'avant dernier '.' ?

Le dernier.

|> car j'ai :

|> i = a.end();
|> r = find(a.begin(),i,c);

|> if(r == i) //placé en dernière position
|> {
|> cout << "derniere position" << endl;
|> if(*r == c) //si c a été trouvé
|> {

|> [...]

|> et ça plante a l'execution... comme si '*r' n'était pas une
|> case de mon tableau.

C'est normal. Tu n'as pas le droit de déréférencier cet
itérateur.

|> idem avec *(r-1)

Si le tableau n'est pas vide, en revanche, ça doit marcher. Pour
std::vector, en tout cas -- ce n'est même pas légal pour les
itérateurs de std::list.

--
James Kanze mailto:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France +33 1 41 89 80 93
Avatar
Gabriel Dos Reis
James Kanze writes:

| Nicolas Aunai writes:
|
| |> Anthony Fleury a dit :
|
| |> > Pour un vecteur d'entiers par exemple : int n, x = 42;
| |> > vector<int> a(n); // remplissage de a...
| |> > if(find(a.begin(), a.end(), x) == a.end())
| |> > // Echec de la recherche...
|
| |> > Si 42 n'est pas dans a vecteur, alors find te renvoie a.end(). il
| |> > n'y a qu'à tester cette valeur pour savoir si find a
| |> > échouée ou pas.
|
| |> ok, mais l'iterateur a.end(), désigne-t-il l'adresse du dernier
| |> élément ? ou la dernière adresse de mon tableau ?
|
| Il designe en fait un élément au delà de la fin du tableau.

Plus précisément, c'est l'iterator (fictif) qui suit immédiatement
l'itérateur qui pointe sur a.back() -- si a n'est pas vide.

-- Gaby
Avatar
kanze
Gabriel Dos Reis wrote in message
news:...
James Kanze writes:

| Nicolas Aunai writes:

| |> Anthony Fleury a dit :

| |> > Pour un vecteur d'entiers par exemple : int n, x = 42;
| |> > vector<int> a(n); // remplissage de a...
| |> > if(find(a.begin(), a.end(), x) == a.end())
| |> > // Echec de la recherche...

| |> > Si 42 n'est pas dans a vecteur, alors find te renvoie a.end().
| |> > il n'y a qu'à tester cette valeur pour savoir si find a
| |> > échouée ou pas.

| |> ok, mais l'iterateur a.end(), désigne-t-il l'adresse du dernier
| |> élément ? ou la dernière adresse de mon tableau ?

| Il designe en fait un élément au delà de la fin du tableau.

Plus précisément, c'est l'iterator (fictif) qui suit immédiatement
l'itérateur qui pointe sur a.back() -- si a n'est pas vide.


La norme parle des « past-the-end values ». Comment doit-on rendre cette
expression en français ? La norme C parle des pointeurs « one past the
last object » ; on pourrait poser la même question ici.

On remarque bien qu'il s'agit d'une expression technique très précise,
dont la signification ne se résume pas entièrement dans la signification
habituelle des mots qu'elle comporte. Donc, si « valeur au-delà de la
fin » pourrait être un candidat, il est loin d'être certain que c'est la
meilleur solution. D'autant plus qu'en C++, de tels itérateurs peuvent
exister pour un tableau vide, ou il n'y a pas de « last object ».

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16

Avatar
Franck Branjonneau
Gabriel Dos Reis écrivait:

James Kanze writes:

| Nicolas Aunai writes:
|
| |> Anthony Fleury a dit :
|
| |> > Pour un vecteur d'entiers par exemple : int n, x = 42;
| |> > vector<int> a(n); // remplissage de a...
| |> > if(find(a.begin(), a.end(), x) == a.end())
| |> > // Echec de la recherche...
|
| |> > Si 42 n'est pas dans a vecteur, alors find te renvoie a.end(). il
| |> > n'y a qu'à tester cette valeur pour savoir si find a
| |> > échouée ou pas.
|
| |> ok, mais l'iterateur a.end(), désigne-t-il l'adresse du dernier
| |> élément ? ou la dernière adresse de mon tableau ?
|
| Il designe en fait un élément au delà de la fin du tableau.

Plus précisément, c'est l'iterator (fictif) qui suit immédiatement
l'itérateur qui pointe sur a.back() -- si a n'est pas vide.


Et si a est vide ?
--
Franck Branjonneau

Avatar
Fabien LE LEZ
On Mon, 23 Feb 2004 12:40:06 +0100, Franck Branjonneau
wrote:

Et si a est vide ?


a.begin() == a.end()

--
;-)

Avatar
Franck Branjonneau
Fabien LE LEZ icrivait:

On Mon, 23 Feb 2004 12:40:06 +0100, Franck Branjonneau
wrote:

Et si a est vide ?


a.begin() == a.end()


Ce que j'aimais particulièrement c'était la formulation en français :

Si c est un container non vide, c.end() est l'iterateur fictif qui
succède à l'itérateur qui désigne c.back().

Mais incomplète :

Si c est un container vide, c.end() est l'iterateur fictif qui ...


Note que a.begin() == a.end() est une propriété de a.end() quand
a est vide. Ce ne sera une définition de a.end() que quand a.begin()
aura été défini ;-)
--
Franck Branjonneau


1 2 3