问题
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