2017-09-04 2 views
0

Ne fonctionne pas lorsque j'essaie de créer un vecteur contenant des éléments uniques.ne trouve pas de travail alors que j'essaie de créer un vecteur contenant des éléments uniques en C++

La chaîne est d'abord segmentée, puis elle doit être inversée. mais les éléments en chaîne inversée doivent être uniques.

#include <cstring> 
    #include <vector> 
    #include <algorithm> 
    #include <iostream> 
    using namespace std; 
    int main() 
    { 
     vector<char *> myvec; 
     string input; 
     getline(cin,input); 
     char *token = std::strtok((char *)input.c_str()," "); 
     while (token != NULL) 
     { 
      if(find(myvec.begin(), myvec.end(), token) != myvec.end()) 
       cout<< "\n Skipping duplicate"; 
      else 
       myvec.push_back(token); 
      token = std::strtok(NULL, " "); 
     } 
     cout<<endl; 
     while (!myvec.empty()) 
     { 
      cout<<myvec.back(); 
      myvec.pop_back(); 
      cout<<" "; 
     } 
    cout<<endl; 
    } 

    Input: A bird came down the walk down END 
    Output: END down walk the down came bird A 

    Down should be removed from output as it is duplicate word. 
+1

comportement non défini, car la valeur de retour de '.c_str()' 'est const' – alain

+0

Vous sautez en double pointeurs ** ** ne pas dupliquer du texte. – Galik

+0

@Alain: Il n'y a pas de problème en tokenising. Mais le problème est avec trouver. – user3069523

Répondre

2

Le problème est que vous stockez des pointeurs sur des caractères, et non des chaînes:

vector<char *> myvec; 

au lieu de

vector<string> myvec; 

Alors, quand vous écrivez vos commentaires:

A bird came down the walk down END 
      ^   ^

ces deux "bas" sont des mots différents, et ils sont stockés dans différentes posititions de la mémoire, et à cause de cela leurs adresses sont différentes.

Un code similaire qui fonctionne, mais en utilisant des chaînes, est le suivant:

string input; 
getline(cin, input); 

stringstream str; 
str << input; 

vector<string> v; 
while (str >> input){ 
    if (find(v.begin(), v.end(), input) == v.end()) 
     v.push_back(input); 
} 

cout << '\n'; 

for(auto p = v.rbegin(); p != v.rend(); ++p) 
    cout << *p << ' '; 

cout << '\n'; 
0

Depuis vector<char*> est un vecteur de pointeurs et token est un pointeur aussi bien, que vous comparez des pointeurs. Les deux pointeurs différents pointent vers des valeurs différentes, alors ils ne sont pas égaux.

Insérer dans votre code, et vous verrez la différence:

std::cout << "Memory address: " << token << " value: " << *token << std::endl; 

Vous voulez comparer les valeurs, pas les pointeurs. Comme dit dans les commentaires, vous pouvez essayer d'utiliser vector<char> et ensuite utiliser *token, ou utiliser vector<string> directement (de sorte que vous pouvez également éviter input.c_str()).

PS: si vous souhaitez toujours utiliser char* dans le vecteur, vous pouvez implémenter une fonction simple comme ceci:

bool check_character(vector<char*> vec, char* token) 
{ 
    for (int i = 0; i < vec.size(); i++) 
    { 
     if (*(vec.at(i)) == *token) 
      return true; 
    } 
    return false; 
} 

(code ps non testé)

0

Il y a quelques problèmes avec votre code. D'abord, vous rejetez const lorsque vous faites (char*) input.c_str() ce qui peut provoquer un comportement indéfini.

Sinon, votre std::find() recherche des pointeurs en double il ne compare pas le contenu des chaînes vers lesquelles ils pointent. Pour cela vous avez besoin d'une fonction de comparaison de chaînes comme std::strcmp. La fonction std::find_if vous permet de fournir votre propre fonction de comparaison complexe (dans le code ci-dessous j'ai utilisé un lambda).

int main() 
{ 
    std::vector<char*> myvec; 

    std::string input = "A bird came down the walk down END"; 

    // removed for exposition 
    // std::getline(cin, input); 

    // don't cast away const, use the address of the first element 
    // THIS ONLY WORKS AFTER C++11 
    // (because no guarantee of null terminator before that) 
    char* token = std::strtok(&input[0], " "); 

    while(token != NULL) 
    { 
     // use find_if() to compare zero-terminated strings using std::strcmp 
     if(find_if(myvec.begin(), myvec.end(), 
      [token](char* t){ return std::strcmp(t, token) == 0; }) != myvec.end()) 

      std::cout << "\n Skipping duplicate"; 
     else 
      myvec.push_back(token); 

     token = std::strtok(NULL, " "); 
    } 

    std::cout << '\n'; 

    while(!myvec.empty()) 
    { 
     std::cout << myvec.back(); 
     myvec.pop_back(); 
     std::cout << " "; 
    } 

    std::cout << '\n'; 
}