Comment puis-je parcourir une chaîne et connaître l’indice (position actuelle)?

Souvent, lors d’une itération à travers une chaîne (ou tout object énumérable), nous ne nous intéressons pas seulement à la valeur actuelle, mais également à la position (index). Pour accomplir cela en utilisant ssortingng::iterator nous devons maintenir un index séparé:

 ssortingng str ("Test ssortingng"); ssortingng::iterator it; int index = 0; for ( it = str.begin() ; it < str.end(); it++ ,index++) { cout << index << *it; } 

Le style ci-dessus ne semble pas supérieur au style c:

 ssortingng str ("Test ssortingng"); for ( int i = 0 ; i < str.length(); i++) { cout << i << str[i] ; } 

Dans Ruby, nous pouvons obtenir le contenu et l’index de manière élégante:

 "hello".split("").each_with_index {|c, i| puts "#{i} , #{c}" } 

Alors, quelle est la meilleure pratique en C ++ pour parcourir un object énumérable et garder une trace de l’index actuel?

Je n’ai jamais entendu parler d’une meilleure pratique pour cette question spécifique. Cependant, une des meilleures pratiques en général consiste à utiliser la solution la plus simple pour résoudre le problème. Dans ce cas, l’access de type tableau (ou c-style si vous voulez l’appeler ainsi) est le moyen le plus simple d’itérer tout en ayant la valeur d’index disponible. Donc, je recommanderais certainement cette façon.

Comme ça:

 std::ssortingng s("Test ssortingng"); std::ssortingng::iterator it = s.begin(); //Use the iterator... ++it; //... std::cout << "index is: " << std::distance(s.begin(), it) << std::endl; 

Vous pouvez utiliser la distance standard de la fonction STL comme indiqué précédemment.

 index = std::distance(s.begin(), it); 

En outre, vous pouvez accéder à la chaîne et à d’autres conteneurs avec l’interface c-like:

 for (i=0;i 

Une bonne pratique serait basée sur la lisibilité, par exemple:

 ssortingng str ("Test ssortingng"); for (int index = 0, auto it = str.begin(); it < str.end(); ++it) cout << index++ << *it; 

Ou:

 ssortingng str ("Test ssortingng"); for (int index = 0, auto it = str.begin(); it < str.end(); ++it, ++index) cout << index << *it; 

Ou votre original:

 ssortingng str ("Test ssortingng"); int index = 0; for (auto it = str.begin() ; it < str.end(); ++it, ++index) cout << index << *it; 

Etc. Tout ce qui est le plus facile et le plus propre pour vous.

Il n'est pas clair qu'il y ait une bonne pratique, car vous aurez besoin d'une variable de compteur quelque part. La question semble être de savoir si vous définissez l'endroit et comment il s'incrémente.

J’utiliserais it-str.begin () Dans ce cas particulier, std :: distance et operator- sont les mêmes. Mais si le conteneur se transforme en quelque chose sans access aléatoire, std :: distance incrémentera le premier argument jusqu’à ce qu’il atteigne la seconde, donnant ainsi un temps linéaire et operator- ne sera pas compilé. Personnellement, je préfère le second comportement – il vaut mieux être averti lorsque votre algorithme de O (n) est devenu O (n ^ 2) …

Pour les chaînes, vous pouvez utiliser ssortingng.c_str() qui vous renverra un const char *, qui peut être traité comme un tableau, par exemple:

 const char* strdata = str.c_str(); for (int i = 0; i < str.length(); ++i) cout << i << strdata[i]; 

Puisque std::distance n’est que le temps constant pour les iterators à access aléatoire, je préférerais probablement l’arithmétique de l’iterator explicite. De plus, comme nous écrivons du code C ++ ici, je pense qu’une solution plus idiomatique C ++ est préférable à une approche de style C.

 ssortingng str{"Test ssortingng"}; auto begin = str.begin(); for (auto it = str.begin(), end = str.end(); it != end; ++it) { cout << it - begin << *it; }