I need to request a size of array, which should be posite number. Look at the function of input and cheking of it.
indexType get_array_size(){
//indexType - size_t; MAX = max of unsigned int
long long ansver;
while(true){
std:: cout << "Enter size of array{0..." << MAX/2-1 << "} ";
bool ans = std:: cin >> ansver;
if(ansver < 0 || !(ans)){
std:: cout << "Incorect size!" << std::endl;
ansver = 0;
continue;
}
break;
}
return ansver;
}
How it must work: if ansver < 0 or input incorrect(some chars for example) new request, else return obtained value. But in practice only the first request is sent, and then only cout-s "Incorect size" if input was incorrect. Please help. Ps sorry for not good english=)
When an input stream gets in a bad state, you have to:
Clear the state.
Discard the current input.
before entering new data.
while(true){
std:: cin >> ansver;
if (cin.fail()) {
std::cout << "Bad input!" << std::endl;
cin.clear(); // unset failbit
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
continue;
}
if(ansver < 0 ) {
std::cout << "Incorect size!" << std::endl;
continue;
}
break;
}
Related
This is a program that grade user inputs for the questions of Driver's License Exam.
I'm having trouble of validating the user input.
I'd like to accept the [ENTER] key as an invalid input and proceed to my validation rather than just go to an empty line and cannot process to the next question. Purpose is to send out error message and that no input is given and [ENTER] key is not valid input and only accept one more chance to enter valid input which are a/A, b/B, c/C, or d/D. So that is why I'm using if statement here instead of loop.
I tried if (testTakerAnswers[ans] == (or =) '\n') {} but still doesn't solve the problem of newline.
I include curses.h in here hope to use getch() statement from the other post but somehow I can't manage to work in my code with an array instead of regular input.
I'm looking for other methods as well rather than getch()
So should I adjust my bool function, or directly validate input in main() function.
#include <iostream>
#include <iomanip>
#include <string>
#include <cctype>
#include <curses.h>
using namespace std;
const unsigned SIZE = 20; // Number of qns in the test
char testTakerAnswers[SIZE]; //Array to hold test taker's answers
bool validateInput(char);
class TestGrader
{
private:
char answers[SIZE]; // Holds the correct answers // Answer is array
int getNumWrong (char[]);
void missedQuestions (char[]);
public:
void setKey(string); // Initialize object with standard keys
void grade(char[]); // Grades the answers from tester
};
void TestGrader::setKey(string key){
if (key.length()!=SIZE){
cout << "Error in key data.\n";
return;
}
for (unsigned pos = 0; pos < SIZE ; pos ++)
answers [pos] = key [pos];
}
void TestGrader::grade(char test[])
{
int numWrong = getNumWrong(test);
if (numWrong <= 5)
cout << "Congratulations. You passed the exam.\n";
else
cout << "You did not pass the exam. \n";
cout << "You got " << (SIZE-numWrong) << " questions correct. \n";
if (numWrong > 0){
cout << "You missed the following " << numWrong << " questions: \n";
missedQuestions(test);
}
}
int TestGrader::getNumWrong(char test[])
{
int counter = 0;
for (int i = 0; i < SIZE; i++){
if (answers[i] != toupper(testTakerAnswers[i])){
counter++;
}
}
return counter;
}
void TestGrader::missedQuestions(char test[])
{
// cout << testTakerAnswers[i]; This is to print taker's answers
int counter = 0;
for (int i = 0; i < SIZE; i++){
if (answers[i] != toupper(testTakerAnswers[i])){
cout << "\n" << i + 1 << ". Correct answers: " << answers[i];
counter++;
}
}
}
bool validateInput(char ans){ // Only A, B, C, D valid input
if (toupper(ans)!='A' && toupper(ans)!= 'B' && toupper(ans)!='C' && toupper(ans)!= 'D'){
cout << "\n********************WARNING*******************\n";
cout << "Invalid input! Enter only a/A, b/B, c/C, or d/D\n";
return false;
}
if (testTakerAnswers[ans] == '\n'){
return false;
}
return true;
}
int main()
{
const int NUM_QUESTIONS = 20;
string name; //Test taker's name
char doAnother; //Control variable for main processing loop
TestGrader DMVexam; //Create a TestGrader object
DMVexam.setKey("BDAACABACDBCDADCCBDA");
do {
cout << "Applicant Name: ";
getline(cin,name);
cout << "Enter answer for " << name << ".\n";
cout << "Use only letters a/A, b/B, c/C, and d/D. \n\n";
for (int i = 0; i < NUM_QUESTIONS; i++){
// Input and validate it
do{
cout << "Q" << i+1 << ": ";
cin >> testTakerAnswers[i];
if (!validateInput(testTakerAnswers[i])){
cout << "You get one more chance to correct.\nOtherwise, it count as wrong answer.";
cout << "\n*********************************************";
cout << "\nRe-enter: ";
cin >> testTakerAnswers[i];
cout << '\n';
break;
}
}while(!validateInput(testTakerAnswers[i]));
}
//Call class function to grade the exam
cout << "Results for " << name << '\n';
DMVexam.grade(testTakerAnswers);
cout << "\nGrade another exam (Y/N)? ";
cin >> doAnother;
while (doAnother != 'Y' && doAnother != 'N' && doAnother != 'y' && doAnother != 'n'){
cout << doAnother << " is not a valid option. Try Again y/Y or n/N" << endl;
cin >> doAnother;}
cout << endl;
cin.ignore();
}while(doAnother != 'N' && doAnother != 'n');
return 0;
}
Your issue is cin >> testTakerAnswers[i]; cin is whitespace delimited, that means that any whitespace (including '\n') will be discarded. So testTakerAnswers[i] can never be '\n'.
I'm not sure exactly what you want to do, but possibly try
getline(cin,input_string);
then
input_string == "A" | input_string == "B" | ...
So if only the enter key is pressed, input_string will become "".
I have this code that checks if index is an integer between 1 and the size of a vector member called options_ (menu implementation):
int ConsoleMenu::GetSelection() {
int index;
std::cout << "Please enter your selection index. " << std::endl;
while (!(std::cin >> index) || std::cin.get() != '\n' || index < 1 || index > options_.size()) {
std::cout << "Error. index must be a valid integer. Try again: " << std::endl;
std::cin.clear();
std::cin.ignore(256, '\n');
}
}
but sometimes when I input a number and press enter it seems as if the program does not recognize I pressed enter. Can someone please help?
Thanks a lot!
Read a line with getline(), parse it using a std::stringstream, and test if it meets your criteria:
int ConsoleMenu::GetSelection() {
std::cout << "Please enter your selection index. " << std::endl;
while (true) {
std::string line;
std::getline(std::cin, line);
std::stringstream linest(line);
int index;
if ((linest >> index) && index >= 1 && index < options_.size()) {
return index;
}
std::cout << "Error. index must be a valid integer. Try again: " << std::endl;
}
}
is it possible, say your trying to do calculations so the primary variable type may be int... but as a part of the program you decide to do a while loop and throw an if statement for existing purposes.
you have one cin >> and that is to take in a number to run calculations, but you also need an input incase they want to exit:
Here's some code to work with
#include <iostream>
using namespace std;
int func1(int x)
{
int sum = 0;
sum = x * x * x;
return sum;
}
int main()
{
bool repeat = true;
cout << "Enter a value to cube: " << endl;
cout << "Type leave to quit" << endl;
while (repeat)
{
int input = 0;
cin >> input;
cout << input << " cubed is: " << func1(input) << endl;
if (input = "leave" || input = "Leave")
{
repeat = false;
}
}
}
I'm aware they wont take leave cause input is set to int, but is it possible to use a conversion or something...
another thing is there a better way to break the loop or is that the most common way?
One way to do this is read a string from cin. Check its value. If it satisfies the exit condition, exit. If not, extract the integer from the string and proceed to procss the integer.
while (repeat)
{
string input;
cin >> input;
if (input == "leave" || input == "Leave")
{
repeat = false;
}
else
{
int intInput = atoi(input.c_str());
cout << input << " cubed is: " << func1(intInput) << endl;
}
}
You can read the input as a string from the input stream. Check if it is 'leave' and quit.. and If it is not try to convert it to a number and call func1.. look at atoi or boost::lexical_cast<>
also it is input == "leave" == is the equal operator. = is an assignment operator.
int main() {
cout << "Enter a value to cube: " << endl;
cout << "Type leave to quit" << endl;
while (true)
{
string input;
cin >> input;
if (input == "leave" || input == "Leave")
{
break;
}
cout << input << " cubed is: " << func1(atoi(input.c_str())) << endl;
}
}
you can use like
int input;
string s;
cint>>s; //read string from user
stringstream ss(s);
ss>>input; //try to convert to an int
if(ss==0) //not an integer
{
if(s == "leave") {//user don't want to enter further input
//exit
}
else
{
//invalid data some string other than leave and not an integer
}
}
else
{
cout<<"Input:"<<input<<endl;
//input holds an int data
}
This bit of code works. I can also copy paste from start to end several times inside my main and it will still work.
int main()
{
string str;
cout << "Input a palindrome: "; // Start
getline(cin, str);
if (testPalindrome(str) == 1)
cout << "Your input is a palindrome: True" << endl;
else
cout << "Your input is a palindrome: False" << endl;
cout << endl; // End
cout << "\nCreated by,\nNorman Ettedgui" << endl;
system("pause");
return 0;
}
However this bit of code will not work and the error I get is a strings out of bound within my function (oddly enough before the function call).
This is my testPalindrome function:
bool testPalindrome(string str)
{
string newStr;
for (int i = 1; i < str.length() - 1; i++)
newStr += str[i];
if (newStr.length() > 1)
testPalindrome(newStr);
if (str[0] == str[str.length() - 1])
return true;
}
This is what I'm trying to run:
int main()
{
string str;
int i = 0;
while (i != -1)
{
cout << "Input a palindrome: ";
getline(cin, str);
if (testPalindrome(str) == 1)
cout << "Your input is a palindrome: True" << endl;
else
cout << "Your input is a palindrome: False" << endl;
cout << "-1 to Exit or any other number to continue: ";
cin >> i;
cout << endl;
}
cout << "\nCreated by,\nNorman Ettedgui" << endl;
system("pause");
return 0;
}
Try the following function
bool testPalindrome( string s)
{
return ( s.size() < 2 ? true
: s.front() == s.back() && testPalindrome( s.substr( 1, s.size() -2 ) ) );
}
Also in main substitute this statement
if (testPalindrome(str) == 1)
for
if ( testPalindrome(str) )
If you use getline and operator >> simultaneously then you should use ignore to skip ENTER key
(DO not forget include <limits>)
#include <limits>
while (i != -1)
{
cout << "Input a palindrome: ";
cin.ignore( numeric_limits<streamsize>::max() );
getline(cin, str);
//...
cin >> i;
cout << endl;
}
I will explain you why you got the error. Without statement with the call of ignore function getline read an empty string. So str was empty. In function testPalindrome there is statement
for (int i = 1; i < str.length() - 1; i++)
As for an empty string its length is equal to 0 then expression
str.length() - 1
has the maximum value for the unsigned type because the type of this expression is some unsigned integral type and the internal representation of -1 corresponds to the maximim unsigned value.
So variable i will be always less than -1 and you get memory access violation.
Also I would use another loop without using additional variable i.
while ( true )
{
cout << "Input a palindrome: ";
string str;
getline(cin, str);
if ( str.empty() ) break;
//...
}
if (newStr.length()>1) only handles the condition when newStr.length() is >1. You need an else statement to handle when the condition: if (newStr.length()>1) is false.
I'm basically expecting a number as input. The magnitude is negligible now as I know my else if loop works fine. But testing if its a number proves to be a bit trickier. I just want to call the function again and start over if the user enters in something alphanumeric or just plain words. Or pressed enter. Something that is not a number. I tried !cin since I am inputting into int numTemp, but that just results in an infinite loop that spills out "what is the bitrate" countless times. Anyone know what I'm doing wrong? I tried putting cin.clear() and cin.ignore(100, "\n") inside the first if statement but to no avail. Thanks in advance.
bool iTunes::setBitRate()
{
cout << "What is the bitrate? ";
int numTemp;
cin >> numTemp;
if (!cin)
{
cout << "WRONG" << endl;
setBitRate();
}
else if( numTemp < MIN_BITRATE || numTemp > MAX_BITRATE)
{
cout << "Bit Rate out of range" << endl;
setBitRate();
}
else
{
bitRate = numTemp;
}
}
You can just read a string from the user instead of an int, and then check it and prompt for new input if you don't like the string (e.g. if it doesn't cleanly convert to a number, which you can check with strtol).
If you want to check whether the input is a number or character, you can use isdigit, but you have to pass it a char and then when it is a digit you can convert it to a int with atoi.
When the statement cin >> numTemp fails due to non-numeric input the character causing the failure is NOT removed from the input stream. So the next time the stream extraction operator is called it will see the same non-numeric input as the last time. To avoid this you need to skip the existing input.
One way of doing this is to use getline() to read a complete line of text before trying to converting it to and integer. The folllowing code snippet illustrates this:
#include <cstdlib>
bool getint(istream& in, int & out) {
string line;
getline(in, line);
char* endptr;
out = strtol(line.c_str(), &endptr, 10);
return endptr!=line.c_str();
}
bool iTunes::setBitRate()
{
cout << "What is the bitrate? ";
int numTemp;
if ( !getint(cin, numTemp) && cin )
{
cout << "WRONG" << endl;
setBitRate();
}
else if( numTemp < MIN_BITRATE || numTemp > MAX_BITRATE)
{
cout << "Bit Rate out of range" << endl;
setBitRate();
}
else
{
bitRate = numTemp;
}
}
NOTE: You should also check the status of cin after each read to ensure that some error has not occurred.
i think this will helps
bool iTunes::setBitRate()
{
cout << "What is the bitrate? ";
int numTemp = 0;
cin >> numTemp;
if (!numTemp)
{
cout << "WRONG" << endl;
setBitRate();
}
else if( numTemp < MIN_BITRATE || numTemp > MAX_BITRATE)
{
cout << "Bit Rate out of range" << endl;
setBitRate();
}
else
{
bitRate = numTemp;
}
}