Segmentation fault in program which creates a vector from a string

寵の児 提交于 2019-12-12 01:57:19

问题


I got a Segmentation fault in the following program.
Why is this happening and how can I fix it?

#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;
}

回答1:


I don't know the reason

You have several issues with your code. The one glaring one is that you failed to return the vector v in the split_words function. Not returning a value from a function that is defined to return a value is undefined behavior.

The second issue is that j falls off the end on the last word, since your loop only stops on s[j] being a blank. The string does not end on a blank character, thus your loop keeps going beyond the length of the string.

Having said this, if your goal is to split a string on the space character, there is no need to write code like this to do the job. Instead, simply use std::istringstream and 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

The loop simply calls operator >> on the stream, and each iteration calls push_back for each parsed string encountered.




回答2:


I think, provided that you're using C++11 or higher, that you should go for regular expressions, and do something like this:

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;
}

So that your search matches every single (non-extended) ASCII table character combination except non printable ones, including spaces, and you achieve your aim.




回答3:


The bug is right here when you get to the last word you forget to check for \0 or the length of the string.

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

Ah forgot I had seen Alexsandrescu talk about sentinels, so you could actually have solved the problem if you had added a (space) after the input. As first line in your split_words add

s += ' ';



回答4:


These changes are required. Also mentioned inline in code below.

// 0. can try using namespace std; to clean up code.

// 1. check for end of string in below loop.

// 2. return the vector of strings. (this fixes the crash).

// 3. output the split strings using vector.

#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;
}


来源:https://stackoverflow.com/questions/40872311/segmentation-fault-in-program-which-creates-a-vector-from-a-string

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!