/
getInput.cpp
318 lines (266 loc) · 7.4 KB
/
getInput.cpp
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
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
/*********************************************************************
** Program name: getInput.cpp
** Author: Jesse McKenna
** Date: 9/27/2017
** Description: Helper functions for input validation
*********************************************************************/
#include <iostream>
#include <string>
#include <cctype>
#include "getInput.hpp"
// --- getInt ---
// Requests user input until a valid int is entered. Rejects input containing
// any non-digit characters (except starting hyphen representing negative).
int getInt()
{
// Initialize variables
bool isClean;
std::string input;
int length = 0;
int result;
// Loop until an int value is returned
do
{
isClean = true;
// Get entire line of user input
std::getline(std::cin, input);
// Reject input if length is less than 1 (ex. if user just pressed [enter])
if (input.length() < 1)
{
isClean = false;
}
// Reject input if it contains any non-digit characters
if (isClean && !isdigit(input.at(0)) && input.at(0)!='-')
{
isClean = false; // first character can be digit or - (for negative)
}
for (int i = 1; i < length && isClean; i++)
{
if (!isdigit(input.at(i))) // if any subsequent character is a non-digit
{
isClean = false; // set isClean to false and stop checking characters
}
}
} while (!isClean);
// Convert clean input to an int and assign to result
result = std::stoi(input);
return result;
}
// --- getInt(min) ---
// Requests user input until a valid int is entered. Rejects input containing
// any non-digit characters (except starting hyphen representing negative).
// Input must be greater than or equal to min.
int getInt(int min)
{
int result;
// Keep calling getInt until result is within acceptable range
do
{
result = getInt();
} while (result < min);
return result;
}
// --- getInt(min, max) ---
// Requests user input until a valid int is entered. Rejects input containing
// any non-digit characters (except starting hyphen representing negative).
// Input must be between min and max, inclusive.
int getInt(int min, int max)
{
int result;
// Keep calling getInt until result is within acceptable range
do
{
result = getInt();
} while (result < min || result > max);
return result;
}
// --- getDouble ---
double getDouble()
{
// Initialize variables
bool isClean;
std::string input;
int length = 0;
double result;
int decimalPoints; // count of decimal points (maximum of 1 is accepted)
// Loop until a double value is returned
do
{
isClean = true;
decimalPoints = 0;
// Get entire line of user input
std::getline(std::cin, input);
// Reject input if length is less than 1 (ex. if user just pressed [enter])
if (input.length() < 1)
{
isClean = false;
}
// First character can only be a digit, negative sign, or decimal point
if (isClean && !isdigit(input.at(0)) && input.at(0)!='-' && input.at(0)!='.')
{
isClean = false;
}
else if (input.at(0) == '.')
{
decimalPoints++; // decimal chars are not rejected, but increment count
}
// Subsequent characters can only be digits or decimal points (max 1)
for (int i = 1; i < length && isClean; i++)
{
if (input.at(i) == '.')
{
decimalPoints++; // decimal chars are not rejected, but increment count
}
else if (!isdigit(input.at(i))) // otherwise, if any char is non-digit
{
isClean = false; // set isClean to false and stop checking characters
}
}
// Reject input if more than one decimal point was counted
if (decimalPoints > 1)
{
isClean = false;
}
} while (!isClean);
// Convert clean input to a double and assign to result
result = std::stod(input);
return result;
}
// --- getDouble(min) ---
// Input must be greater than or equal to min.
double getDouble(double min)
{
double result;
// Keep calling getDouble until result is within acceptable range
do
{
result = getDouble();
} while (result < min);
return result;
}
// --- getDouble(min, max) ---
// Input must be between min and max, inclusive.
double getDouble(double min, double max)
{
double result;
// Keep calling getDouble until result is within acceptable range
do
{
result = getDouble();
} while (result < min || result > max);
return result;
}
// --- getYesNo ---
// Requests user input until yes ("y", "yes") or no ("n", "no") is entered,
// then returns true for yes and false for no. Non-case-sensitive.
bool getYesNo()
{
std::string input;
while (true) // loop until appropriate response received
{
std::getline(std::cin, input); // get user input
for (int i = 0, n = input.length(); i < n; i++)
{
input[i] = tolower(input[i]); // convert to lowercase (non-case-sensitive)
}
if (input == "y" || input == "yes")
{
return true;
}
if (input == "n" || input == "no")
{
return false;
}
}
}
// --- getChar ---
// Requests user input until a single character is provided
char getChar()
{
std::string input;
char result;
// Loop until a char value is returned
do
{
// Get entire line of user input
std::getline(std::cin, input);
} while (input.length() != 1); // reject if blank or longer than a single char
result = input[0];
return result;
}
// --- getChar ---
// Requests user input until a single character within validChars is provided
char getChar(std::string validChars)
{
char result;
bool isValid = false;
// Loop until a char value is returned
do
{
result = getChar();
for (int i = 0, n = validChars.length(); i < n && !isValid; i++)
{
if (result == validChars.at(i))
{
isValid = true; // return once result char found in validChars string
}
}
} while (!isValid); // reject if not within validChars
return result;
}
// --- getString ---
// Requests user input until a string is entered; accepts any string containing
// only alphanumeric characters, periods, spaces, hyphens, pounds, and commas
std::string getString()
{
std::string input;
bool isText;
char c;
do
{
isText = true;
std::getline(std::cin, input);
for (int i = 0, n = input.length(); i < n && isText; i++)
{
c = input[i];
if (!isalnum(c) && !isspace(c) && c != '.' && c != '-' && c != '#' &&
c != ',')
{
isText = false; // reject string if non-permitted character is found
}
}
} while (!isText || input.length() < 1);
return input;
}
// --- getFilename ---
// Similar to getString, but appends the file extension if it was not included
// (ex. if requesting a .txt name and user enters "data", returns "data.txt")
std::string getFilename(std::string extension)
{
int extLength = extension.length();
// Add leading . character to extension if not included
if (extLength > 0 && extension.at(0) != '.')
{
extension = '.' + extension;
}
std::string input = getString(); // get string from user
int inputLength = input.length();
bool hasExtension = false;
if (inputLength > extLength) // check whether user added extension
{
hasExtension = true;
for (int i = 0, j = inputLength - extLength;
i < extLength && hasExtension; i++, j++)
{
if (input.at(j) != extension.at(i))
{
hasExtension = false;
}
}
}
if (!hasExtension)
{
input.append(extension);
}
return input;
}