MadLibs play again Option

So I am trying to make a madlibs program that will ask for a file and open it, read it, and ask the user for input, then input the words in the story and display them.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
#include <iostream>
#include <fstream>
using namespace std;

void getFileName(char *file);
int readFile(char *file, char story[][256]);
char getInfo(char story[][256], int numWords);
void display(char story[][256], int numWords);
void askQuestions(char story[][256], int i);
void playAgain(char file[256]);
int main();
/**********************************************************************
 * This main funtion will call all other functions and run the entire program.
 ***********************************************************************/

/**********************************
This will bring everything together and display the story
**********************************/



int main()
{
   char story[256][256];
   char file[256];
   int numWords = 0;


   getFileName(file);
   numWords = readFile(file, story);
   getInfo(story,numWords);
   display(story,numWords);
   playAgain(file);

   return 0;
}
/*************************
This will get the file name
*************************/


void getFileName(char *file)
{
   // gets the name of the file
   cout << "Please enter the filename of the Mad Lib: ";
   cin.getline(file, 256);

}

/**************************
This will read the file and check for errors and make sure the
story is the correct size
***********************/



int readFile(char *file, char story[][256])
{
   ifstream fin(file);
   int numWords = 0;

// error checking

   if (fin.fail())
   {
      cout << "Error reading file. ";

      return -1;
   }

// size checking

   while(numWords <= 256 && !fin.eof())
      fin >> story[numWords++];

   fin.close();

   return numWords;

}

/*************************
This will get the words that the user wants to put into the story
************************/

char getInfo(char story[][256], int numWords)
{

   char wordChange[256];

   // this will go through the letters of the words and find the
   // symbols and remove them or add in something else
   for (int i = 0; i < numWords; i++)
 {
      if(story[i][0] == '<')
      {
         if (isalpha(story[i][1]))
         {
            cout << "\t";
            for(int j = 1; story[i][j]!= '>' ; j++)
            {
               if (j == 1)
                  cout << (char)toupper(story[i][1]);
               else if (story[i][j] == '_')
                  cout << ' ';
               else
                  cout << story[i][j];
            }

            cout << ": ";
            askQuestions(story, i);

         }
      }
   }
   cout << endl;
}

/**********************
This will display the story
*********************/
void askQuestions(char story[256][256], int i)
{
   cin.getline(story[i], 256);

}

/**********************
This will display the story
*********************/
void display(char story[][256], int numWords)
{
// goes word for word and displays the story

   // this will go through the letters of the words and find the
   // symbols and remove them or add in something else
   for (int i = 0; i < numWords; i++)
   {
      if(story[i][0] == '<')
      {
          switch (story[i][1])
         {
            case '#':
               cout << '\n';
               story[i][0] = '\n';
               story[i][0] = '\0';

               break;
            case '{':
               cout << '"';
               //story[i][0] = ' ';
               //story[i][0] = '"';
               break;
            case '}':
               cout <<  '"';
               cout << ' ';
               //           story[i][0] = '"';
               //story[i][0] = ' ';
               break;
            case '[':
               cout <<  '\'';
               // story[i][0] = ' ';
               // story[i][0] = '\'';
               break;
            case ']':
               cout << '\'';
               cout <<  ' ';
               break;
            case '.':
               cout << endl;
               break;
            case '?':
               cout << endl;
               break;
            case '"':
               break;
            case '!':
               break;
         }
      }
  else if(story[i + 1][0] == '<' || ispunct(story[i + 1][0]))
      {
         cout << story[i];
         switch (story[i + 1][1])
         {
            case '{':
            case '[':
               cout << ' ';
            break;
            case '#':
            case '}':
            case ']':
            case '.':
            case '?':
            case '!':
               break;
         }
      }

      else
         cout << story[i] << " ";
   }
}


void playAgain(char file[256])
{
  char choice;
  char newFile;

  cout << endl;
  cout << "Do you want to play again (y/n)? " ;
  cin >> choice;

  if (choice == 'y')
  {






  }
  else
     cout << "Thank you for playing." << endl;


}



so I am in need of guidance for my play again option. I need to make it so if they choose 'y' that it will run the program again


I have tried:

if(choice == 'y')
main();

which I was hoping would just run main again to run the entire program again but that does not work, it just says error reading file(that user inputs) and stops there.

EDIT::

Ohh wait nvm What you need to do is put
 
cin.getline(file, 256).clear();

inside your if statment right before you recall main();

so for example:
1
2
3
4
5
6
7
if(choice == 'y'){
cin.getline(file, 256).clear();
main();
}
else{
cout<<"Thank you for playing."<<endl;
}
Last edited on
so I tried this:

1
2
3
4
5
6
7
8
9
10
11

do{
     main();
  }
  while(choice == 'y');

  do{
     cout << "Thank you for playing.";
        }
  while(choice == 'n');




the first one did repeat the program, but it does this:

1
2
3
> Do you want to play again (y/n)? y
> Please enter the filename of the Mad Lib: Error reading file. \n



The error reading file should not happen because later in the program it reads the file just fine and ouputs the story correctly.
Here is a link to some info i provided for someone else:

http://www.cplusplus.com/forum/beginner/84889/#msg455481


Btw, Never ever call main() - not ever !! Nor should you use goto's (just in case you are tempted)

There is also no need to declare the main function.

Always use loops to achieve what you want.

HTH
to maddog: it WORKED - thanks so much




to TheIdeasMan: I can see why in terms of knowing nothing about c++ why you would not want to call main() into anything, but I want to know why not? not to be rude, im just not sure why there would be a problem with that and I want to learn why. Also I declared main to see if it would solve anything (it didnt) and forgot to take it out, thanks for pointing that out!



as to my final problem, I have those case statements in there to determine things for example:

in the file we are given the story which has words in it, but when there are words that we need to replace it looks like this


<{> <adjective> <}>


so I have the logic to remove the first set of <{> and replace it with a " and a space

and the last set with a space and "

so it looks like this:

" <adjective> "

then the logic goes through and says remove the < and > and bring the " in closer and capitalize the first letter and add a tab so it looks like this:

Adjective:

then the enter what they want in there, for this example the enter "happy"
so my program changes Adjective: to "happy" and displays that like the example below however it messes with some other things





   > My pet cat is very "happy" .\n
Exp: My pet cat is very "happy".\n
   > So is my dog.
   >  \n
Exp: \n


there are space before those new lines and there should not be.

I thought it was this section of the program:

1
2
3
 case '}':
               cout <<  '"';
               cout << ' ';



but that just messes up another part of the program as well


so I thought about adding in something that will determine if it is the end of line or file because that's when it happens, but i cant quite get the logic right, here is what i am trying:

if "end of line"

cin.ignore();

im not sure if that would work or not but that is what I am trying to do... any thoughts?
The C++ Standard says that you may not call main() from your own code.

3.6.1.3
"The function main shall not be used within a program."

5.2.2.9
"Recursive calls are permitted, except to the function named main"


It also creates a new main function on the stack, then keeps doing that again and again until you run out of memory.


Did you set up your loops the way I mentioned in the link I provided? I think this is a much better solution than was provided by maddog , IMO, because it is much clearer & easy to follow.

there are space before those new lines and there should not be.
1
2
3
4
case '}':
               cout << ' ';   //swapped these around   ?
               cout <<  '"';
              


but that just messes up another part of the program as well


What did you mean by that ?

By far the easiest way to fix problems like this, is to use the debugger.

Hope this helps.

What did you mean by that?


when I change it around, it will delete the space between the " and the next letter/symbol and I need it there so it would not run together like this "happy"next word instead of "happy"-space-next word.

apparently I can't do this either:

case '!"':
break;

I was hoping that would get rid of the space and immediately go to the default. but on second thought maybe thats what puts the space in the first place. not sure ill go look into it.
Topic archived. No new replies allowed.