cin a char into an int variable to stop a loop - c++

I would like to read numbers into a static array of fixed size 10, but the user can break the loop by entering character E.
Here's my code:
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int myArray[10];
int count = 0;
cout << "Enter upto 10 integers. Enter E to end" << endl;
for (int i = 0; i < 10; i++)
{
cout << "Enter num " << i + 1 << ":";
cin >> myArray[i];
if (myArray[i] != 'E')
{
cout << myArray[i] << endl;
count++;
}
else
{
break;
}
}
cout << count << endl;
system("PAUSE");
return 0;
}
However, I get the following results while entering E:
Enter upto 10 integers. Enter E to end
Enter num 1:5
5
Enter num 2:45
45
Enter num 3:25
25
Enter num 4:2
2
Enter num 5:E
-858993460
Enter num 6:-858993460
Enter num 7:-858993460
Enter num 8:-858993460
Enter num 9:-858993460
Enter num 10:-858993460
10
Press any key to continue . . .
How can I fix this code in the simplest way?

cin fails for parsing character 'E' to int. The solution would be to read string from user check if it is not "E" (it is a string not a single char so you need to use double quotes) and then try to convert string to int. However, this conversion can throw exception (see below).
Easiest solution:
#include <iostream>
#include <cmath>
#include <string> //for std::stoi function
using namespace std;
int main()
{
int myArray[10];
int count = 0;
cout << "Enter upto 10 integers. Enter E to end" << endl;
for (int i = 0; i < 10; i++)
{
cout << "Enter num " << i + 1 << ":";
std::string input;
cin >> input;
if (input != "E")
{
try
{
// convert string to int this can throw see link below
myArray[i] = std::stoi(input);
}
catch (const std::exception& e)
{
std::cout << "This is not int" << std::endl;
}
cout << myArray[i] << endl;
count++;
}
else
{
break;
}
}
cout << count << endl;
system("PAUSE");
return 0;
}
See documentation for std::stoi. It can throw exception so your program will end suddenly (by termination) that is why there is try and catch blocks around it. You will need to handle the case when user puts some garbage values in your string.

Just use:
char myArray[10];
because at the time of taking input console when get character then try to convert char to int which is not possible and store default value in std::cin i.e. 'E' to 0 (default value of int).
Use below code:
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
char myArray[10];
int count = 0;
cout << "Enter upto 10 integers. Enter E to end" << endl;
for (int i = 0; i < 10; i++)
{
cout << "Enter num " << i + 1 << ":";
cin >> myArray[i];
if (myArray[i] == 'E')
{
break;
}
else
{
cout << myArray[i] << endl;
count++;
}
}
exitloop:
cout << count << endl;
system("PAUSE");
return 0;
}
Output:
Enter upto 10 integers. Enter E to end
Enter num 1:1
1
Enter num 2:E
1
sh: 1: PAUSE: not found

If you debug this, you will find all your myArray[i] are -858993460 (=0x CCCC CCCC), which is a value for the uninitialized variables in the stack.
When you put a E to an int variable myArray[i]. std::cin will set the state flag badbit to 1.
Then when you run cin >> myArray[i], it will skip it. In other words, do nothing.
Finally, you will get the result as above.

The problem is that attempting to read E as an int fails, and puts the stream in an error state where it stops reading (which you don't notice because it just doesn't do anything after that) and leaves your array elements uninitialized.
The simplest possible way is to break on any failure to read an integer:
for(int i = 0; i < 10; i++)
{
cout << "Enter num " << i + 1 << ":";
if (cin >> myArray[i])
{
cout << myArray[i] << endl;
count++;
}
else
{
break;
}
}
If you want to check for E specifically, you need to read a string first, and then convert that to an int if it's not E.
As a bonus, you need to handle everything that's neither int nor E, which complicates the code a bit.
Something like this:
int count = 0;
string input;
while (cin >> input && count < 10)
{
if (input == "E")
{
break;
}
istringstream is(input);
if (is >> myArray[count])
{
cout << myArray[count] << endl;
count++;
}
else
{
cout << "Please input an integer, or E to exit." << endl;
}
}

Related

To confirm only 1 and 0 exist in the Binary

I wanted to use only 1 and 0 for the binary. But instead the answer keep giving me the 2nd option with whatever number I typed. I had tried where did I programmed wrongly but unfortunately I still can't find it. So I hoped that I could get some help here.
#include<iostream>
#include<cmath>
using namespace std;
int DualzahlZuDezimal(long long n)
{
int dez = 0;
int i = 0, rem;
while (n != 0)
{
rem = n % 10;
n /= 10;
dez += rem * pow(2, i);
++i;
}
return dez;
}
string a;
int main()
{
long long n;
int dez;
cout << "Test Ein- und Ausgabe : \n";
cout << "----------------------- \n";
cout << "Eingabe einer Dualzahl : ";
cin >> n;
if ((n == '1') && (n == '0'))
{
cout << "Dual : " << n << endl;
cout << "Dezimal : " << DualzahlZuDezimal(n) << endl;
cout << "cin ok ? : ja-ok" << endl;
return 0;
}
else
{
cout << "Dual : 0" << endl;
cout << "Dezimal : 0" << endl;
cout << "cin ok ? : nein-nicht ok" << endl;
return 0;
}
}
If I understand this right, you want the user to enter a binary number, like 10001101001, and you will show the decimal equivalent (1129 in this case).
There are 2 general ways to do that yourself:
You can read the value as a number, as you do, and then apply your conversion
process, except that you check that rem is either 0 (in which case you do
nothing), or 1 (in which case you add the power of 2). If it's another value,
you report the error, and return 0.
You can read the value as a std::string instead. Then you can use
std::find_first_not_of()
to check for contents other than 0 or 1:
if (n.find_first_not_of("01") != string::npos) { /* complain */ }
but then you need to do the conversion based on characters.
But the best approach is not to reinvent the wheel and instead let the standard library handle it for you via stol():
#include <cstddef>
#include <iostream>
#include <string>
using namespace std;
int
main()
{
string text;
cout << "Enter a binary number: " << flush;
cin >> text;
size_t endpos = 0;
long decimal_number = stol(text, &endpos, 2); // base 2 == binary
if (endpos != text.size()) {
cerr << "'" << text << "' is not a valid binary number!" << endl;
return 1;
}
else {
cerr << "binary number: " << text << endl;
cerr << "decimal number: " << decimal_number << endl;
return 0;
}
}
Keep in mind that input from the console is text. If you need to check that the text matches a particular format (in this case, consists entirely of 1's and 0's), the simplest approach is to look at that text:
std::string input;
std::cin >> input;
bool input_is_valid = true;
for (int i = 0; input_is_valid && i < input.length(); ++i) {
if (input[i] != '0' && input[i] != '1')
input_is_valid = false;
}
then, if the input is valid, convert the text to a numeric value:
long long n = std::stoll(input);

How can I take specific user inputs in an array?

I am coding a program that converts a binary number into decimal number by doubling (link to wikihow article).
If the user input is something other than 1 or 0, then its not a binary number, under that circumstance I want the loop to "break" and say something like:
"Oops! Binary numbers have only 1 or 0".
If not "then" the loop should continue.
That is I want to code something like
for(int digits = 0; digits != digitsINbinNum; ++digits){
if(a condition that checks if user input is anything else than 1 or 0){
coût << ""Oops! Binary numbers have only 1 or 0" << endl;
break;
}else{
cin >> binArray[digits];/*<-----------Here's the part where I am trying to do that*/
}
}
Refer to the code given below for more info:
#include <iostream>
#include <iterator>
using namespace std;
int main(){
int digitsINbinNum;
cout << "If you don't mind. Please enter the number of digits in your binary number: ";
cin >> digitsINbinNum;
int binArray[digitsINbinNum];
cout << "Enter the binary number: ";
for(int digits = 0; digits != digitsINbinNum; ++digits){
cin >> binArray[digits];/*<-----------Here's the part where I am trying to do that*/
}
/*using the doubling method as found in wikihow.com*/
int total = 0;
for(int posiOFdigit = 0; posiOFdigit != sizeof(binNum[noOFdigits]); posiOFdigit++){
total = total * 2 + binNum[posiOFdigit];
}
/*Printing the number*/
cout << "Decimal form of ";
for(int n = 0; n != noOFdigits; n++){
cout << binNum[n];
}
cout << " is " << total;
return 0;
}
The logic for converting a binary number into decimal number by the doubling method can be referred from the given link in the question.
Modifying the given code to keep it as close as possible to the question's reference code.
Note: As ISO C++ forbids variable length array, I am changing
int binArray[digits] to
int *binArray = (int *)malloc(sizeof(int) * digitsINbinNum);.
This modification makes it an integer pointer and it gets the memory of required size allocated at runtime.
#include <iostream>
using namespace std;
int main(){
int digitsINbinNum,
/* variable to keep decimal conversion of given binary */
decimal_val = 0;
bool is_binary = true;
cout << "If you don't mind. Please enter the number of digits in your binary number: ";
cin >> digitsINbinNum;
/*
ISO C++ forbids variable length array,
making it int pointer and allocating dynamic memory
*/
int *binArray = (int *)malloc(sizeof(int) * digitsINbinNum);
if (binArray == NULL)
{
cout << "Memory allocation failure" << endl;
exit -1;
}
cout << "Enter the binary number: ";
for(int digits = 0; digits != digitsINbinNum; ++digits){
cin >> binArray[digits];
/*<-----------Here's the part where I am trying to do that*/
/* doubling method logic for conversion of given binary to decimal */
if ((binArray[digits] == 0) ||
(binArray[digits] == 1))
{
decimal_val = (decimal_val * 2) + binArray[digits];
}
else /* not a binary number */
{
is_binary = false;
cout << "Oops! Binary numbers have only 1 or 0" << endl;
break;
}
}
/* if conversion is successful: print result */
if (is_binary)
{
cout << "Decimal Value for given binary is: " << decimal_val << endl;
}
if (binArray)
{
free(binArray);
}
return 0;
}
You don't need an array for this. Here is a simple solution:
#include <iostream>
int main(){
int digitsINbinNum;
std::cout << "If you don't mind. Please enter the number of digits in your binary number: ";
std::cin >> digitsINbinNum;
std::cout << "Enter the binary number: ";
int ret = 0;
for(int digits = 0; digits != digitsINbinNum; ++digits) {
int bin;
std::cin >> bin;
if (bin == 1 || bin == 0) {
ret = 2 * ret + bin;
} else {
std::cout << "Oops! Binary numbers have only 1 or 0" << std::endl;
return -1;
}
}
std::cout << ret << std::endl;
return 0;
}

How to Accept [ENTER] key as an invalid input and send out error message

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 "".

Counting digits in a number without using strings

i have the next code which asks the user for a really long number like 100000000 and then it prints how many times a given digit appears on that number, the code works fine and does everything correctly, but the professor told me that i dont have to use strings or chars, but when the code asks the user for a number it necessarily needs a string and i don´t know how to modify it, i used the gmp library
#include <iostream>
#include <stdio.h>
#include <gmp.h>
#define MAX 40
using namespace std;
void searchDigit(FILE *fd);
int NewNumber();
int main()
{
FILE *fd;
int otherNumber;
string text;
mpz_t num;
do
{
if((fd = fopen("File.txt","w+"))!= NULL)
{
mpz_init(num);
cout << "Give me the number: " << endl;
cin >> text;
mpz_set_str(num,text.c_str(),10);
mpz_out_str(fd,10,num);
fclose(fd);
searchDigit(fd);
otherNumber = NewNumber();
}
else
cout << "Fail!!" << endl;
}while(otherNumber);
return 0;
}
void searchDigit(FILE *fd)
{
int car,continue = 1,r;
char answer,digit;
if((fd = fopen("File.txt","r"))!= NULL)
{
do
{
r = 0;
fseek(fd,0,SEEK_SET);
cout << "What digit do you want to search? " << endl;
cin >> digit;
while((car = fgetc(fd))!= EOF)
{
if(car == digit)
r++;
}
cout << "The digit x=" <<digit<< " appears " << r << " times" << endl;
cout << "Do you want to search any other digit? " << endl;
cin >> answer;
if(answer != 'S')
continue = 0;
}while(continue);
}
else
cout << "Fail!!" << endl;
}
int NewNumber()
{
char answer;
cout << "DO you wish to work with a new number? " << endl;
cin >> answer;
if(answer == 'S' || answer == 's')
return 1;
else
return 0;
}
Thanks in advance
Depends on how big your input might actually be... but for retrieving digits you could do something like:
#include <iostream>
using namespace std;
typedef unsigned long long UINT64;
int main() {
UINT64 i;
std::cin >> i;
while (i >= 1) {
int digit = i % 10;
std::cout << digit << " ";
i /= 10;
}
}
input: 18446744073709551614
outputs: 4 1 6 1 5 5 9 0 7 3 7 0 4 4 7 6 4 4 8 1

vector-related segmentation fault

void offer_help();
bool play_one_game();
int main() {
offer_help();
play_one_game();
}
void offer_help() {
int help_response;
cout << "Need help? (0/1) ";
cin >> help_response;
if (help_response == 1)
cout << "I will generate a pattern of 4 numbers, each in the range 0 through 9.\n Each guess that you enter will be a line containing 4 integers,\n separated by spaces, such as:\n\t 2 4 7 1\n FOr each guess, I will echo back a lost consisting of\n 0's and 1's, with a 1 in a given position meaning that\n you guessed the number, and a zero meaning that you didn't.\n For example, if the actual solution was 2 3 6 1, I'll respond\n\t 1 0 0 1\n See how many guesses it takes you to get the solution!\n\n If you want to give up, type a negative number for one of\n your guesses, and we'll tell you what the pattern was.\n\n";
}
bool play_one_game() {
srand(time(0)); //needed to start randint
vector<int> solution; //vector of 4 randomly generated
//solutions
vector<int> guess; //vector containing user guesses.
vector<int> result;
int guess_input;
for(int i = 0; i < solution.size(); ++i)
solution[i] = randint(10);
int trial_number = 0; //int that shows what guess the user is on
while (play_one_game() == true) {
//ask user for inputs.
cout << "Guess #" << ++trial_number << "? ";
for (int i = 0; i < guess.size(); ++i){
cin >> guess_input;
guess.push_back(guess_input);
}
//outputs error if user inputs a letter.
if (!cin) {
cerr << "Bad input data! Feed me numbers!\n";
return 43;
}
if (cin < 0){
cout << "Too bad! Solution was " << endl;
for(int i = 0; i < result.size(); i++)
cout << (result[i]);
}
//determines if user correctly guessed any of the
//numbers and tells the user which is correct.
for (int i = 0; i < result.size(); i++) {
if (guess[i]==solution[i])
cout << 1 << " ";
else if (guess[i]!=solution[i])
cout << 0 << " ";
}
cout << endl;
// playagain();
cout << endl << "Play again (0/1)? ";
int replay;
cin >> replay;
if (replay == 0) {
play_one_game() == false;
return 5;
}
else if (replay == 1)
play_one_game() == true;
else {
cerr << "wat?\n";
return 10;
}
}
}
This is designed to allow a player to guess a pattern of random numbers.
No idea why I am getting a segmentation fault. The program is supposed to call the offer_help function, then the play_one_game function within main function. Then it should ask the player whether he wants to play again. If no, then bool play_one_game should be set to false and it should exit.
This is related to the play_one_game bool function.
You're getting a segmentation fault, because you end up in an endless recursion in the following line:
while (play_one_game() == true) {
play_one_game will call play_one_game in this line, and this will call play_one_game in the same line again. This will result in a stack overflow at last.
Better use some bool keepPlaying; and while(keepPlaying) instead.
EDIT: Well, this is a little bit more than a simple answer, but I like games, so... have a look at the following code:
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <vector>
bool play_one_game();
void offer_help() {
int help_response;
std::cout << "Need help? (0/1) ";
std::cin >> help_response;
if (help_response == 1)
std::cout << "I will generate a pattern of 4 numbers, each in the range 0 through 9.\n"
"Each guess that you enter will be a line containing 4 integers,\n"
"separated by spaces, such as:\n"
"\t 2 4 7 1\n"
"For each guess, I will echo back a lost consisting of\n"
"0's and 1's, with a 1 in a given position meaning that\n"
"you guessed the number, and a zero meaning that you didn't.\n"
"For example, if the actual solution was 2 3 6 1, I'll respond\n"
"\t 1 0 0 1\n"
"See how many guesses it takes you to get the solution!\n\n"
"If you want to give up, type a negative number for one of\n"
"your guesses, and we'll tell you what the pattern was.\n\n";
}
int main() {
offer_help();
srand(time(0)); // Initialize random numbers with current time as seed
while(play_one_game()); // if play_one_game returns true, play again
}
bool play_one_game() {
std::vector<int> solution(4); // Four solutions for our guessing game
std::vector<int> guess; // User guesses
for(unsigned i = 0; i < solution.size(); ++i)
solution[i] = rand() % 10;
int trial_number = 0; //int that shows what guess the user is on
bool keepPlaying = true;
while(keepPlaying){
std::cout << "Guess #" << ++trial_number << "? ";
guess.clear(); // Clear old guesses
for(unsigned i = 0; i < solution.size(); ++i){
int guess_input;
//outputs error if user inputs a letter.
if (!(std::cin >> guess_input)) {
std::cerr << "Bad input data! Feed me numbers!\n";
std::cerr << "Try again!" << std::endl;
std::cin.clear(); // Clear flags
continue;
}
if (guess_input < 0){
std::cout << "Too bad! Solution was " << std::endl;
for(unsigned i = 0; i < solution.size(); i++)
std::cout << (solution[i]);
keepPlaying = false;
break;
}else
guess.push_back(guess_input);
}
if(!keepPlaying)
break;
if(solution.size() != guess.size()){
std::cerr << "Wrong number of guesses, try again!" << std::endl;
continue;
}
//determines if user correctly guessed any of the
//numbers and tells the user which is correct.
bool correct = true;
for (unsigned i = 0; i < solution.size(); i++) {
if (guess[i] == solution[i])
std::cout << 1 << " ";
else{
correct = false;
std::cout << 0 << " ";
}
}
if(correct){
std::cout << "Congratulations - you won!" << std::endl;
break;
}
std::cout << std::endl;
}
int replay = -1;
do{
// Ask user for input until input is 0 or 1
std::cout << std::endl << "Play again (0/1)? ";
std::cin >> replay;
}
while(replay != 0 && replay != 1);
return static_cast<bool>(replay); // return user replay answer (false/true)
}
Try to keep your code as simple as possible. Welcome to SO. And don't expect future answers to be that excessive.
You're never inserting anything into your solution vector. You just declare the vector, and then say:
for(int i = 0; i < solution.size(); ++i)
solution[i] = randint(10);
...which won't do anything since at this point solution.size() == 0. Later, when you iterate over your result vector, you end up accessing invalid elements in your empty solution vector. You also can't assume that the result vector and solution vector are the same size.