-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
253 lines (207 loc) · 7.48 KB
/
main.cpp
File metadata and controls
253 lines (207 loc) · 7.48 KB
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
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
//TextGun model
#include "TextGun.hpp"
#include <string>//Strings
#include <fstream>//File stream
#include <sstream>//String stream
#include <iostream>//Print to console
#include <exception>//Exception handling
//Number of options
enum Options: int
{
START=0,//Start of valid options
LISTEN,//Read a single line from standard input
THINK,//Produce output
READ,//Read model from file
WRITE,//Write the model to file
LEARN,//Learn model from file
EXIT,//Exit the program
ERROR,//Invalid option
END//End of valid values
};
//Print menu, and return picked option
Options menu();
//Make a yes/no question
bool questYN(const std::string &s, bool def);
//Read a word containing the name of a file on the current path
std::string read_filename();
//Read a complete line, except the new line character
std::string read_line();
int main()
{
//Flags to control program flow
bool in=true;//Stay in the program loop
bool unsaved_changes=false;//Changes to be saved
bool empty_model=true;//Model is completly empty
//Model
TextGun::WordModel model;//TextGun model
while(in)
{
switch(menu())
{
//Learn a line from standard input
case Options::LISTEN:
{
//Read the line
std::cout<<"Input line to learn: ";
std::string s=read_line();
//Feed the line to the model
std::stringstream ss(s);
TextGun::ITextStream ts(ss);
model.learn(ts);
//Adjust the flags
unsaved_changes=true;
empty_model=false;
break;
}
//Generate and write lines
case Options::THINK:
{
//Print lines until users requests to stop
TextGun::OTextStream ots(std::cout);//Output stream
do
{
model.think(ots);
}while(!questYN("Quit?",false));
break;
}
//Read a pregenerated model from a binary file
case Options::READ:
{
if (!empty_model)
std::cout<<"ERROR! Cannot read from file because model isn't empty. Reopen the program, and read the file\n";
else
{
//Path of file to read
std::cout<<"File to read: ";
std::string file=read_filename();
//Try to open the file
std::ifstream input(file,std::ios::in|std::ios::binary);
if(input.is_open())//If the file is open, save
{
model.read(input);
empty_model=false;
}
else
std::cout<<"ERROR: reading from file "<<file<<'\n';
}
break;
}
//Write the current model to file
case Options::WRITE:
{
//Path of file to write
std::cout<<"File to write: ";
std::string file=read_filename();
//Try to open the file
std::ofstream output(file,std::ios::out|std::ios::binary|std::ios::trunc);
if(output.is_open())//If the file is open, write
{
if (unsaved_changes)//If there are unsaved changes, go ahead
{
model.write(output);
unsaved_changes=false;
}
else//If there are no changes, no need to save
std::cout<<"No need to save anything!\n";
}
else
std::cout<<"ERROR: saving to file "<<file<<'\n';
break;
}
case Options::LEARN:
{
//Path of file to open
std::cout<<"File to learn from: ";
std::string file=read_filename();
//Try to open the file
std::ifstream input(file,std::ios::in|std::ios::binary);
if(input.is_open())//If the file is open, read it
{
//Read the file, line by line
for(std::string s;std::getline(input,s);)
{
if (!s.empty())//Don't read blank lines
{
std::stringstream ss(s);
TextGun::ITextStream ts(ss);
model.learn(ts);
//Modify flags
unsaved_changes=true;
empty_model=false;
}
}
}
else
std::cout<<"ERROR! Reading from file "<<file<<'\n';
break;
}
//Exit the program
case Options::EXIT:
{
if(questYN("Close the program?",false))
in=false;
break;
}
case Options::ERROR:
default:
{
std::cout<<"ERROR!\n";
break;
}
}
}
return 0;
}
//Print menu, and return picked option
Options menu()
{
std::cout<<"Menu\n";
std::cout<<'['<<Options::LISTEN<<']'<<" Listen \t- read and learn one line from console input\n";
std::cout<<'['<<Options::THINK<<']'<<" Think \t- generate output\n\n";
std::cout<<'['<<Options::READ<<']'<<" Read \t- read a binary file of a previously saved model\n";
std::cout<<'['<<Options::WRITE<<']'<<" Write \t- write current model to binary format\n";
std::cout<<'['<<Options::LEARN<<']'<<" Learn \t- generate a model from a text file (one entry per new line, no empty lines)\n\n";
std::cout<<'['<<Options::EXIT<<']'<<" Exit \t- leave the program\n";
std::cout<<"Option => ";
std::string opt;
std::getline(std::cin,opt);
int x;
//Parse the string to int, errors may occur
std::stringstream ss(opt);
if(!(ss>>x))
x=Options::ERROR;
if (x<=Options::START||x>=Options::END)
x=Options::ERROR;
return static_cast<Options>(x);
}
//Make a yes/no question
bool questYN(const std::string &s, bool def)
{
for(;;)
{
std::cout<<s<<(def?"[Y/n]":"[y/N]")<<": ";
std::string s;
std::getline(std::cin,s);
if (s=="y"||s=="Y")
return true;
if (s=="n"||s=="N")
return false;
if (s=="")
return def;
std::cout<<"ERROR: Invalid option. Please use y,Y,n,N or a blank line for default value\n";
}
}
//Read a word containing the name of a file on the current path
std::string read_filename()
{
std::string s;
std::getline(std::cin,s);
return std::move(s);
}
//Read a complete line, except the new line character
std::string read_line()
{
std::string s;
std::getline(std::cin,s);
return std::move(s);
}