2009-10-14 5 views
1

Le programme ci-dessous semble se bloquer à la fin à chaque fois, et je suppose que c'est parce qu'une fois arrivé à i = (taille-1), puis wordList [ i + 1] ne retournera rien, renvoie null, ou quelque chose d'équivalent. De toute façon autour de cela? Ai-je raison de dire que c'est la source de mon problème?Programme d'écrasement de boucle 'for' simple sur l'itération finale

#include <iostream> 
#include <string> 
#include <vector> 
#include <algorithm> 
#include <iomanip> 

using std::cin; 
using std::cout;   using std::endl; 
using std::sort; 
using std::string;   using std::vector; 

// Obtain a list of words and return the de-duped list 
// with an accompanying word count 
int main() 
{ 
    cout << "Enter a series of words separated by spaces, " 
      "followed by end-of-file: "; 

    vector<string> wordList; 
    string x; 
    while (cin >> x) 
      wordList.push_back(x); 

    typedef vector<string>::size_type vec_sz; 
    vec_sz size = wordList.size(); 
    if (size == 0) { 
     cout << endl << "This list appears empty. " 
         "Please try again." << endl; 
     return 1; 
    } 

    sort(wordList.begin(), wordList.end()); 

    cout << "Your word count is as follows:" << endl; 
    int wordCount = 1; 
    for (int i = 0; i != size; i++) { 
     if (wordList[i] == wordList[i+1]) { 
      wordCount++; 
      } 
     else { 
      cout << wordList[i] << " " << wordCount << endl; 
      wordCount = 1; 
      } 
     } 
    return 0; 
} 

Répondre

3

Vous avez besoin de deux changements. Comme indiqué dans les commentaires précédents, votre condition de fin devrait être < size-1 pour empêcher la lecture hors des limites. Vous devez également imprimer le nombre du dernier élément, qui sera wordCount, car s'il est unique, wordCount vaut 1 et si ce n'est pas le cas, il a déjà été ajouté. Code corrigé:

for (int i = 0; i < size-1; i++) { 
    if (wordList[i] == wordList[i+1]) { 
     wordCount++; 
     } 
    else { 
     cout << wordList[i] << " " << wordCount << endl; 
     wordCount = 1; 
     } 
    } 
cout << wordList[size-1] << " " << wordCount << endl; 
+0

Super machielo. On dirait que vous avez pris mes deux soucis - le problème des hors limites ainsi que la façon d'attraper le dernier mot de la liste. Le simple passage à 'i IanWhalen

+0

Je suis content que vous l'ayez trouvé utile :) – AntonioMO

-1

Vous pouvez essayer

for (int i = 0; i < size; i++) 

Cela arrêtera la boucle d'essayer de répondre à un indice qui est hors des limites.

+0

Alors que Herms

+2

Incorrect. Il accède à wordList [i + 1] qui échouera quand i == size-1. –

1

Oui. La condition de limite échoue. vector[size()] est une valeur indéfinie.

if (wordList[i] == wordList[i+1]) ---> out of bounds 

travail pourrait être autour itérer size()-1

0

C'est exactement le problème. Votre vecteur contient des éléments de "taille", mais vous essayez d'accéder à la fin du vecteur. Ce que vous devez faire est d'arrêter la boucle for avant le dernier élément, de sorte que i + 1 accède uniquement au dernier élément.

Par exemple:

for (int i = 0; i < (size - 1); i++) { 
0

changement

for (int i = 0; i != size; i++) { 

à

for (int i = 0; i != size-1; i++) { 
+0

Je recommanderais

0

C'est parce que pour i == taille 1, i + 1 taille de ==. Et wordList [size] est à la fin de votre liste. Vous avez probablement besoin de changer votre condition de boucle pour "i < taille - 1".

2

Vous devez changer votre code à for (int i = 0; i < size-1; i++) { car en wordList[i+1] la valeur de i+1 doit être inférieure à size. Lequel des résultats signifie i < size -1. Les matrices C/C++ peuvent avoir des index de 0 à size-1.

0

Ce n'est pas NULL, c'est en dehors de la plage. Vous devriez au moins vérifier si la taille est < avant de faire cette comparaison.

Je ne suis pas sûr de ce que vous essayez de faire avec la comparaison de toute façon, mais c'est une question plus large.

7

Deux problèmes. Tout d'abord, il est généralement préférable de faire une boucle jusqu'à ce que votre index soit < votre taille, au lieu d'utiliser! =. Ce que vous avez devrait encore travailler ici.

Le problème est cette ligne:

if (wordList[i] == wordList[i+1]) 

Vous devez soit arrêter votre boucle un plus tôt (i < taille - 1) ou modifier votre instruction if afin qu'il vérifie uniquement WordList [i] == WordList [i + 1] quand il y a au moins une entrée de plus dans le tableau.

Un moyen plus facile peut-être à la boucle de i = 1 à i < taille, et vérifiez WordList [i-1] == WordList [i]:

for(int i = 1; i < size; i++) { 
    if(wordList[i - 1] == wordList[i]) { 
    /* same as before */ 
    } 
    /* everything else the same */ 
} 

Cela vous évitera d'avoir besoin supplémentaire si déclarations mais vous protégera encore de quitter les limites du tableau.

EDIT:

Comme mentionné dans les commentaires, si vous utilisez tout le code original et il suffit de changer la boucle comme je l'ai mentionné, il y aura une erreur off-by-1, mais il est facile à corriger. Commencez le nombre de mots à 1 au lieu de 0. Vous savez que vous aurez toujours au moins un mot unique. La boucle incrémente ce nombre chaque fois qu'il voit un nouveau mot, de sorte que vous vous retrouverez avec le nombre approprié.

La seule manipulation supplémentaire dont vous aurez besoin est lorsque le fichier wordList est vide. Vous aurez donc besoin d'une vérification rapide pour voir si la liste de mots est vide, et dans ce cas le nombre est 0.

+0

Meilleure réponse jusqu'à présent. +1 –

+0

Mais cela ne signifie-t-il pas simplement que wordList [0] est exclu du comptage puisque la commande cout sous l'instruction else commence à wordList [1] et s'incrémente à partir de là? – IanWhalen

+0

Egalement dans une série de mots tels que "a b b c c c d", il commencera par le premier 'b' et découvrira b! = A puis affichera "b 1", n'est-ce pas? Quand la sortie correcte commence avec "a 1" puis "b 2"? – IanWhalen

0

Vous pouvez faire une vérification de i == longueur de la liste de mots et quitter/ignorer le si.

0

Parfois, c'est juste que le code pourrait être beaucoup plus simple ... si vous avez utilisé autre chose. Problème: renvoyer une liste de mots dé-doublée avec un nombre associé à chaque mot.

Personnellement, je voudrais aller pour un std :: map pour une telle déclaration.

// Yeah it feels stupid, but I want default construction to initialize... 
struct MyCount 
{ 
    MyCount() : _count(0) {} 
    size_t _count; 
}; 

std::ostream& operator<<(std::ostream& out, const MyCount& rhs) 
{ 
    return out << rhs._count; 
} 

int main() 
{ 
    cout << "Enter a series of words separated by spaces, " 
      "followed by end-of-file: "; 

    typedef std::map<std::string, MyCount> map_type; 
    map_type wordList; 
    std::string x; 
    while (std::cin >> x) 
    wordList[x] += 1; // This is why I have a struct instead of a plain size_t 

    if (wordList.empty()) { 
    cout << endl << "This list appears empty. " 
        "Please try again." << endl; 
    return 1; 
    } 

    cout << "Your word count is as follows:" << endl; 
    for (map_type::const_iterator it = wordList.begin(), end = wordList.end(); it != end; ++ it) { 
    std::cout << it->first << " " << it->second << std::endl; 
    } 
    return 0; 
} 

Je sais que std :: vecteur est le conteneur par défaut, mais quand si vous êtes « » deux entités associant (ici un mot et son nombre d'occurrences), vous serez mieux penser Container Associatif.

+0

Si je le faisais en python, j'aurais certainement utilisé un dictionnaire que je suppose être l'équivalent en python d'un conteneur associé.Jusqu'à présent, même si le texte que j'utilise n'a introduit que des vecteurs, j'ai été bloqué en utilisant un moyen assez hackish pour obtenir la réponse. – IanWhalen

+0

Eh bien, j'espère que pour vous, ils ne garderont pas de carte et ne vous tendront pas trop longtemps! –