2016-11-29 2 views
0

J'ai reçu une erreur Segmentation dans le programme suivant.
Pourquoi cela se produit-il et comment puis-je le réparer?Erreur de segmentation dans le programme qui crée un vecteur à partir d'une chaîne

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

std::vector<std::string> split_words(std::string s) { 
    std::vector<std::string> v(1, ""); 
    int i=0; 
    int wortanzahl = 0; 
    while(i<s.size()) { 
     if (s[i]!=' ') { 
      v.resize(wortanzahl + 1, ""); 
      for (int j=i; s[j]!=' '; ++j) { 
       v[wortanzahl] += s[j]; 
       i=j; 
      } 
      ++wortanzahl; 
     } 
     ++i; 
    } 
} 

int main() { 
    std::string s = "Alpha beta! Gamma"; 
    split_words(s); 
    return 0; 
} 
+3

Utilisez 'std :: istringstream' pour diviser les mots sur un espace. Vous n'avez pas besoin d'écrire ces types de boucles pour faire ce travail. – PaulMcKenzie

+1

Assurez-vous que vous disposez d'une version de débogage et exécutez le programme sous votre débogueur. Lorsque l'erreur de segmentation se produit, elle vous indique la ligne où elle s'est produite et l'état du programme. Ou, vous pouvez examiner un fichier core existant. Post-scriptum, rien ne s'arrête de j courant à la fin ... – Useless

Répondre

0

Je pense, à condition que vous utilisez C++ 11 ou plus, que vous devriez aller pour les expressions régulières, et faire quelque chose comme ceci:

std::vector<std::string> split_words(std::string s) { 
    std::vector<std::string> v; 
    std::regex pattern("[!-~]+"); 
    std::cmatch result; 

    while(regex_search(s.c_str(), result, pattern)) { 
     for(auto it : result) 
      v.push_back(it); 
     s = result.suffix().str(); 
    } 

    return v; 
} 

Pour que votre recherche correspond à tous les combinaison de caractères de table ASCII unique (non étendue) sauf les caractères non imprimables, y compris les espaces, et vous atteignez votre but.

2

Je ne sais pas la raison

Vous avez plusieurs problèmes avec votre code. Le seul flagrant est que vous n'avez pas réussi à retourner le vecteur v dans la fonction split_words. Ne renvoyant pas de valeur à partir d'une fonction définie pour renvoyer une valeur est undefined behavior.

Le deuxième problème est que j tombe à la fin du dernier mot, puisque votre boucle s'arrête seulement sur s[j] étant un blanc. La chaîne ne se termine pas par un caractère vide, donc votre boucle continue d'aller au-delà de la longueur de la chaîne. Cela dit, si votre objectif est de diviser une chaîne sur le caractère espace, il n'est pas nécessaire d'écrire un code comme celui-ci pour faire le travail. Au lieu de cela, il suffit d'utiliser std::istringstream et operator >>:

#include <vector> 
#include <sstream> 
#include <string> 
#include <iostream> 

std::vector<std::string> split_words(std::string s) 
{ 
    std::vector<std::string> v; 
    std::istringstream iss(s); 
    std::string temp; 
    while (iss >> temp) 
     v.push_back(temp); 
    return v; 
} 

int main() 
{ 
    std::string s = "Alpha beta! Gamma"; 
    auto vect = split_words(s); 
    for (auto& word : vect) 
     std::cout << word << "\n"; 
    return 0; 
} 

Live Example

La boucle appelle simplement operator >> sur le flux, et chaque itération appelle push_back pour chaque chaîne analysable rencontré.

0

Le bug est juste ici quand vous arrivez au dernier mot que vous oubliez de vérifier \0 ou la longueur de la chaîne.

for (int j=i; s[j]!=' ' && j < s.size(); ++j) { 
    v[wortanzahl] += s[j]; 
    i=j; 
} 

Ah oublié que je l'avais vu Alexsandrescu parler de factionnaires, donc vous pouvez effectivement avoir résolu le problème si vous aviez ajouté un (espace) après l'entrée. ligne En tant que premier dans votre split_words ajouter

s += ' '; 
0

Ces changements sont nécessaires. Aussi mentionné dans le code ci-dessous.

// 0. peut essayer using namespace std; pour nettoyer le code.

// 1. vérifier la fin de la chaîne dans la boucle inférieure.

// 2. renvoie le vecteur des chaînes. (Cela corrige le crash).

// 3. affiche les chaînes fractionnées en utilisant un vecteur.

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

// 0. can try using std to clean up code. 
std::vector<std::string> split_words(std::string s) 
{ 
    std::vector<std::string> v(1, ""); 
    int i=0; 
    int wortanzahl = 0; 
    while(i<s.size()) 
    { 
     if (s[i]!=' ') 
     { 
      v.resize(wortanzahl+1, ""); 
      // 1. check for end of string in below loop 
      for (int j=i; s[j] && s[j]!=' '; ++j) 
      { 
       v[wortanzahl] += s[j]; 
       i=j; 
      } 
      ++wortanzahl; 
     } 
     ++i; 
    } 

    // 2. return the vector of strings 
    return v; 
} 

int main() 
{ 
    std::string s = "Alpha beta! Gamma"; 
    std::vector<std::string> v = split_words(s); 

    // 3. output the split strings using vector 
    for (int i = 0; i < v.size(); ++i) 
     std::cout << v[i] << std::endl; 
    return 0; 
}