I need help debugging this segmentation fault.. I have narrowed it down to the separateComandsAndPrompts function but thats where I run into a brick wall. I can not use strings btw. I have only been programming for a month so I'm sorry if the code isn't as efficient or elegant as possible. I don't necessarily want exactly whats wrong just help on finding it myself so that I can learn from my mistake.
And the inputted file is:
I feel like yelling <{> <web_site_name> <}> every time I <verb> the <#>
Internet . So many <plural_noun> to look for , so many <plural_noun>
to find . <#> <#> My mother asked me , <{> <proper_noun> , what is so
<adjective> about <#> the Web ? <}> <{> Well , <}> I said , <{> just
the other day I did a search for <noun> <#> by entering <[> <noun>
<boolean_operator> <noun> <]> in a search <#> engine . And it returned
<favorite_website> and <another_website> . It's <#> just so <adjective>
! <}> <#> <#> And then she knew what I meant . I felt so <emoticon> ! <#>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <vector>
usingnamespace std;
// Defined types
typedef vector< vector<char> > vectorText;
// Global functions
void getFileName(char fileName[]);
void readMadLib(char fileName[], vectorText& madLib);
void interact(vectorText& madLib);
void separateCommandsAndPrompts(vectorText& madLib,
vectorText& madLibPrompts);
void display(vectorText& madLib);
void setSpace(vectorText& madLib, int vectorLevel);
bool isCarrot(vectorText& madLib, int vectorLevel);
void getMadLibPrompt(vectorText& madLib, vectorText& madLibPrompts);
void changeFormat(vector<char>& madLibPrompt, vector<char>& prompt);
int main()
{
vectorText madLib;
char fileName[256] = "1.txt";
//getFileName(fileName);
readMadLib(fileName, madLib);
interact(madLib);
return 0;
}
void getFileName(char fileName[])
{
cout << "Please enter the filename of the Mad Lib: ";
cin >> fileName;
}
void readMadLib(char fileName[], vectorText& madLib)
{
ifstream inStream;
// Open the file
inStream.open(fileName);
// Declare the input variable
char inputChar[256];
// While there are still words in the file
while (inStream >> inputChar)
{
// Declare the variable used to store the words
vector<char> word;
for (char *p = inputChar; *p; p++)
// Send the pointer p to the next spot in word
word.push_back(*p);
// Add a NULL char to the end of the word
word.push_back('\0');
// Send the word to the next spot in madLib
madLib.push_back(word);
}
inStream.close();
}
void interact(vectorText& madLib)
{
// Compiler create a vectorText variable to store the prompts in
vectorText madLibPrompts;
// Compiler run this to separate the commands and prompts from
// eachother and store them properly
separateCommandsAndPrompts(madLib, madLibPrompts);
// Compiler run this to get the users input
getMadLibPrompt(madLib, madLibPrompts);
// Compiler run this to display the finished mad lib
display(madLib);
}
void separateCommandsAndPrompts(vectorText& madLib, vectorText& madLibPrompts)
{
// Runs through the entire madLib file
for (int i = 0; i < (int)madLib.size(); i++)
{
// If the word starts with a < and ends with a >
if (isCarrot(madLib, i))
{
vector<char> madLibCommandReplace;
// We must ignore the first char which is a < and look
// at the
// proceeding char
switch (madLib[i][1])
{
// If it is a # rewrite the word as a new line
// char
case'#':
madLibCommandReplace.push_back('\n');
madLib[i] = madLibCommandReplace;
break;
// If it is a { rewrite the word as a opening "
// char
case'{':
madLibCommandReplace.push_back('"');
madLib[i] = madLibCommandReplace;
break;
// If it is a } rewrite the word as a closing "
// char with
// a space
case'}':
madLibCommandReplace.push_back('"');
madLibCommandReplace.push_back(' ');
madLib[i] = madLibCommandReplace;
break;
// If it is a [ rewrite the word as a opening '
// char
case'[':
madLibCommandReplace.push_back(' ');
madLibCommandReplace.push_back('\'');
madLib[i] = madLibCommandReplace;
break;
// If it is a ] rewrite the word as a closing '
// char with
// a space
case']':
madLibCommandReplace.push_back('\'');
madLibCommandReplace.push_back(' ');
madLib[i] = madLibCommandReplace;
break;
// If we have got to this point it must be a
// prompt so we
// set madLib[i] TO madLibPrompts[i]
default:
madLibPrompts[i] = madLib[i];
break;
}
}
// Else if it's not a command or prompt do this
else
setSpace(madLib, i);
}
}
bool isCarrot(vectorText& madLib, int vectorLevel)
{
// Simply check if the word is enclosed in <> and return true or
// false
return (madLib[vectorLevel][0] == '<' &&
madLib[vectorLevel][madLib[vectorLevel].size() - 2] == '>');
}
void setSpace(vectorText& madLib, int vectorLevel)
{
// Since I am peaking at the next word it has not been changed to
// the proper format and thus still has the carrots. Thuse we must
// look at the second char in the word to see if it is one of the
// commands and act accordingly
switch((madLib[vectorLevel + 1][0]))
{
// These cases do nothing. You wouldn 't want it looking like
// this ! and it simply shouldn 't look like this .
case'!':
case'"':
case'\'':
case')':
case',':
case'.':
case':':
case';':
case'?':
case']':
case'`':
case'}':
break;
// If it isn't any of these check the next char on these cases
// to see if it is one of the commands
default:
if (madLib[vectorLevel + 1][1] == 91
|| madLib[vectorLevel + 1][1] == 95
|| madLib[vectorLevel + 1][1] == 125)
break;
// If we run through the entire switch statement without
// gettin thown out on our butts we get the pleasure of
// adding a ' ' to the end of the word.
madLib[vectorLevel].push_back(' ');
}
}
void getMadLibPrompt(vectorText& madLib, vectorText& madLibPrompts)
{
// Declare the needed variables
vector<char> prompt;
char answer[256];
vector<char> answerSend;
// While we are not at the end of madLib run through the for loop
// which increments madLibLevel by one every iteration
for (int madLibLevel = 0;
madLibLevel < (int)madLib.size();
madLibLevel++)
{
// If the word is enclosed in <>
if (isCarrot(madLib, madLibLevel))
{
// Run through the following code until we reach the
//end of
// madLibPrompts and add 1 to i every iteration
for (int i = 0; (int)madLibPrompts.size(); i++)
{
// Change the format of the prompt to something
// more
// user friendly
changeFormat(madLibPrompts[i], prompt);
// Display the prompt using a for loop
for (int ndx = 0; ndx < (int)prompt.size();
ndx++)
{
cout << prompt[ndx];
}
// Add this the end of the prompt for clarity
cout << ": ";
// Get the users answer.. including spaces
cin.getline(answer, 256);
// Clear answerSend so that we are sure it is
// completely
// before we use it... love this function
answerSend.clear();
// Send the answer to the vector of chars
// answerSend
answerSend.push_back(*answer);
// Set the users answer to its proper place in
// madLib
madLib[madLibLevel] = answerSend;
}
}
}
}
void changeFormat(vector<char>& madLibPrompt, vector<char>& prompt)
{
// While its not the end of madLibPrompt
for (int i = 0; i < (int)madLibPrompt.size(); i++)
{
// Set p to madLibPrompt[i]
char p = madLibPrompt[i];
// Needed to skip the first and last char in madLibPrompt
if (i == 0 || i == (int)madLibPrompt.size() - 1);
// If it is the first letter in the array Cap it
elseif (i == 1)
{
p -= 32; // Change to caps using the ANSI table
prompt.push_back(p);
}
// If it is _ change it to a space
elseif (p == '_')
prompt.push_back(' ');
// Other wise leave be
else
prompt.push_back(p);
}
// Add a \0 char to the vector for stylistic reasons
prompt.push_back('\0');
}
void display(vectorText& madLib)
{
// Simple for loop that runs through the entire madLib vector
// displaying it character by measly character... Wish there was
// a better way to do this. O wait there is it's called the string
// library :)
cout << endl;
for(int i = 0; i < (int)madLib.size(); i++)
{
for(int ndx = 0; ndx < (int)madLib[i].size(); ndx++)
cout << madLib[i][ndx];
}
}
vector<> works like an array. operator[] on vector<> works like operator[] for arrays. So yes,
if you are going to use vectors and operator[], you need to check the bounds. vector<>::at()
works like operator[], except that it checks the bounds automatically for you and throws an
exception if you attempt to access beyond the vector boundaries.