8
votes

Vérification Si Itérateur n'est pas affecté à l'élément lorsqu'il n'y a pas de conteneur spécifique

Je veux rechercher une valeur dans deux std :: vecteur 's. Si cela a été trouvé dans l'un d'entre eux, je veux retourner son itérateur. Sinon, je veux retourner une certaine valeur qui indique qu'il n'a pas été trouvé.

dans la situation normale où un seul std :: vecteur est impliqué, je retournerais std :: vecteur :: End . Que dois-je faire dans cette situation?

Situation normale: xxx

ma situation: xxx

Je veux retourner quelque chose que je peux vérifier plus tard pour savoir que le nombre 10 n'a été trouvé dans aucun d'entre eux.


9 commentaires

Un itérateur est jamais "null".


(Bien qu'un itérateur singulier puisse vous aider, vous êtes autorisé à faire étonnamment peu avec un.)


@LighessRacksinorbit corrigé


Je retournerais l'index dans la matrice à la place ou -1 si non trouvé. Cela pourrait être fait en différant les pointeurs commencements () et itérateur. Mais peut-être que c'est boiteux.


@ Jean-Françoisefabre Index de retour signifie que vous devez retourner un indice à quel vecteur appartient


Si l'appelant doit rester parfaitement ignorant les deux vecteurs, une sentinelle est probablement votre meilleur choix. Créez un vecteur factice qui fait partie de votre interface publique et renvoyez sa fin ().


Pour sauvegarder mon commentaire précédent, soyez averti! La solution "évidente" n'est pas tout ce qu'elle est fissurée.


Vous devriez utiliser boost :: rejoindre pour rejoindre les gammes de toute façon. Alors cela est trivial.


@LighessRacksinorbit Merci que vous avez fait clairement clairement


4 Réponses :


1
votes
auto find_ten=[](const std::vector<int>& v1,const std::vector<int>& v2, bool &found){
    found = true; // suppose we will find it

    auto it1=std::find(v1.cbegin(),v1.cend(),10);
    if(it1==v1.cend()){
        auto it2=std::find(v2.cbegin(),v2.cend(),10);  
        found = it2 != v2.end();     // false if not in v1 or in v2
        return it2; // whether it's end or not
    }

    return it1;
}

2 commentaires

Ah bon? Est-il bien défini pour comparer les itérateurs de différents conteneurs? Dans mon expérience, pour (auto it = conta.begin (), fin = CONTB.END (); ça! = Fin; ++ IT) ne va pas bien.


Je suis d'accord que ce n'est pas très académique, d'où ma solution alternative.



1
votes

Vous pouvez simplement renvoyer l'itérateur d'extrémité de la plupart des vecteurs de la bonne vecteur, cela fait un sens logique: xxx

ou vous pouvez prendre un argument itérateur: xxx

Ces deux, bien sûr, dépendent de votre cas d'utilisation: Si vous utilisez l'itérateur renvoyé pour plus que d'un accès direct à un élément, vous devez envisager une approche différente:

--- Edit ---

Si vous devez utiliser l'itérateur au-delà d'un accès direct à l'élément incriminé, vous pouvez utiliser std :: référence_wrapper pour vous permettre Renvoie une référence au vecteur incriminé (ou vous pouvez simplement retourner un pointeur). xxx

Démo en direct: http://ideone.com/cnljkg


1 commentaires

@Humamhelfewelawi Si vous avez besoin de plus que l'accès direct, voir Modifier.



1
votes

pas vraiment brillant, je suppose, mais ... je propose de retourner un std :: paire où le premier élément est un int (0 pour "non trouvé", 1 pour "trouvé en premier "et 2 pour" trouvé en seconde ") et le second est l'itérateur.

quelque chose comme xxx

ou meilleur: vous pouvez retourner une paire d'itérateurs où le second est le cend () du vecteur correspondant; quelque chose comme xxx

Je pense qu'il est important de renvoyer le cend () correspinig itérateur parce que je suppose que je veux utiliser l'itérateur pointant vers 10 et vous pourrait-il y aller.

Evemioulsy, si vous êtes seul intéressé à savoir si 10 est présent dans v1 ou dans v2 , Je suppose que vous devriez retourner un bool : true pour "trouvé", false sinon; quelque chose comme xxx

p.s.: Désolé pour mon mauvais anglais.


2 commentaires

@ Jarod42 - J'imagine que l'utilisation std :: option peut être une solution mais ... peut être ma limite ... Je ne comprends pas l'utilité du retour d'un const-itérateur sans information sur le conteneur qui est référencé.


@ Jarod42 - personne n'est parfait :-)



8
votes

Etant donné que C ++ 14, vous êtes autorisé à comparer les itérateurs initialisés à la valeur s'ils répondent à la catégorie de transfert de la valeur ou plus forts (voir [Aphante.Bévraducateurs] Paragraphe 2). Un itérateur initialisé de la valeur correspond à l'équivalent d'un pointeur NULL, de sorte que vous pouvez utiliser: xxx

, puis l'appelant peut faire: xxx


6 commentaires

Merci .. il semble exactement ce que je cherche. Mais je ne peux pas utiliser C ++ 14 encore.


En pratique, il fonctionnera probablement avec n'importe quelle version de C ++ (sauf dans les modes de débogage d'itérateurs), la norme C ++ 14 vient de le rendre officiellement légale


Ah c'est bien alors


Jusqu'à ce que c ++ 14, déclarez simplement un vecteur privé foo et avoir not_found () retour (FOO). Cela devient votre valeur sentinelle


Mais êtes-vous autorisé à comparer un itérateur initialisé à valeur avec un itérateur "normal" (dans le cas "trouvé")? N3644 dit en fait que c'est UB dans la discussion ("du résultat de la comparaison d'un itérateur initialisé de valeur à un itérateur avec une valeur non singulière est indéfinie. ").


@ T.c. Bon point. Cela semble limiter gravement l'utilité de la caractéristique, il n'est donc utile que dans des cas très similaires à l'exemple :: début () / a :: fin () en N3644. Même s'il reste indéfini pour le cas général, il serait utile que les conteneurs standard soutiennent de telles comparaisons.