Reputation: 43
I'm having a problem with this code. After compiling with g++, I run a.out and I get a segmentation fault and no "here" displayed. The code is pretty short:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
using namespace std;
bool inWords(vector<string> words, string str);
int main()
{
cout << "here";
vector<string> words;
string str;
istringstream iss;
ifstream file("data.txt", ifstream::in);
// read in words
for(int i = 0; file >> str; /*no i++*/)
{
if(str[str.length() - 1] == '.')
str.erase( str.length()-1);
// if word has a period at the end, erase it
if(!inWords(words, str))
{
// if word is not in vector words, add it
words.push_back(str);
i++;
}
}
// output each word
for (vector<string>::size_type i = 0; i < words.size(); i++)
cout << words[i];
// return to beginning of file
file.clear();
file.seekg(0, ios::beg);
// read in sentences
// to be implemented
file.close();
return 0;
}
bool inWords(vector<string> words, string str)
{
for(int i = 0; !words[i].empty(); i++)
if(words[i] == str) { return true; }
return false;
}
As far as I know, nothing should be a problem. data.txt is definitely in the same directory as the file and I receive no arguments from the command line. Can anyone help?
Upvotes: 1
Views: 2680
Reputation: 11750
The technique for iterating the vector in inWords
is wrong and interacts with elements past the end of the vector causing the segmentation fault.
This program immediately accesses words[0]
in inWords
when the words
vector is empty and words[0]
(the first element of the vector) does not exist yet because the size of the vector is still zero but the loop does not do anything to avoid this condition.
I think inWords
could be better implemented with std::find
, perhaps like this:
bool inWords(const vector<string>& words, const string& str)
{
return std::find(words.begin(), words.end(), str) != words.end();
}
Remember to #include <algorithm>
to make use of std::find
. I also changed the parameters to pass by const reference, so you'll need to change the forward declaration of that function. I also added an endl
to the output to make it readable.
Full text of repair:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
#include <algorithm>
using namespace std;
bool inWords(const vector<string>& words, const string& str);
int main()
{
vector<string> words;
string str;
istringstream iss;
ifstream file("data.txt", ifstream::in);
// read in words
for(int i = 0; file >> str; /*no i++*/)
{
if(str[str.length() - 1] == '.')
str.erase( str.length()-1);
// if word has a period at the end, erase it
if(!inWords(words, str))
{
// if word is not in vector words, add it
words.push_back(str);
i++;
}
}
// output each word
for (vector<string>::size_type i = 0; i < words.size(); i++)
cout << words[i] << std::endl;
// return to beginning of file
file.clear();
file.seekg(0, ios::beg);
// read in sentences
// to be implemented
file.close();
return 0;
}
bool inWords(const vector<string>& words, const string& str)
{
return std::find(words.begin(), words.end(), str) != words.end();
}
Upvotes: 0
Reputation: 1795
It won't be before main. Try using a debugger to see where it happens (eg GDB) which are incredibly handy tool. The reason you don't see "here" is because the buffer isn't flushed. Put a << std::endl
after it so that it forces output at that point.
A technicality: You can segfault before main but that will happen in a constructor. I see you have no custom objects defined/instantiated in global scope.
Upvotes: 2