cin unintentionally skipping user input - visual-c++

I am trying to write a loop that validates user input, and then repeats if the input is bad. The input must be either a binary number (as a string) or a decimal number (as an int). I have seperate functions to validate this input, but they are not causing any trouble.
The problem arises when I select 1 or 2, and then willingly enter an invalid binary or decimal number. At this point, the do-while loop repeats successfully. The program prints another request for user input to cout, But when it comes time for the user to enter input, the program thinks that there is input in the console before I even enter anything. I believe this is a problem with whitespace/control characters in the buffer, but I am not sure how to fix it. I have tried using std::cin >> std::ws to clear any straggling white space, but no luck.
#include <iostream>
#include <string>
#include <limits>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
using std::cout;
using std::cin;
using std::endl;
using std::numeric_limits;
using std::max;
using std::streamsize;
using std::string;
//int toDecimal;
//true is is binary
bool validateBinary(const string &binaryNumber){
for(int i = 0; i < binaryNumber.length(); i++){
if((binaryNumber[i] != 1) && (binaryNumber[i] != 0)){
return false;
}
}
return true;
}
//true if is decimal
bool validateDecimal(){
return cin;
}
int main() {
int conversionType = 0; //we initialize conversionType to a default value of 0 to ensure the copiler it will always have a value
bool isBinary = false;
bool isDecimal = false;
string binaryNumberInput;
int decimalNumberInput;
do {
if(conversionType == 0){
cout << "Enter 1 to convert binary to decimal," << endl;
cout << "2 to convert decimal to binary, " << endl;
cout << "or 3 to exit the program: ";
std::cin >> std::ws; //to clear any whitespace fron cin
cin >> conversionType; //upon a second iteration, this value is read in before a user input is given
}
if(!cin || (conversionType != 1 && conversionType != 2)){
cout << "Incorrect input." << endl;
cin.clear(); //clear the fail bit
cin.ignore(numeric_limits<streamsize>::max(), '\n'); //used to ignore not-numeric input
}
cout << "You have selected option " << conversionType << "." << endl;
if(conversionType == 1){
cout << "Please enter a binary number: ";
cin >> binaryNumberInput;
isBinary = validateBinary(binaryNumberInput);
if(!isBinary){
cout << "The numbered you entered is not a binary number!" << endl;
conversionType = 0;
}
}
if(conversionType == 2){
cout << "Please enter a decimal number: ";
cin >> decimalNumberInput;
isDecimal = validateDecimal(); //true if succeeded, meaning is a number
if(!isDecimal){
cout << "The numbered you entered is not a decimal number!" << endl;
conversionType = 0;
}
}
}
while((conversionType != 1 && conversionType != 2) || (isBinary == isDecimal));
return 0;
}

Rather than debug your current program you might want to consider using the standard library to simply things
#include <iostream>
#include <string>
#include <bitset>
#include <climits>
#include <limits>
template<typename T>
void get(T& value)
{
while (!(std::cin >> value)) {
std::cout << "Invalid input\n";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
int main()
{
std::cout << "Enter 1 to convert binary to decimal,\n" <<
"2 to convert decimal to binary\n";
int option;
if (std::cin >> option) {
switch (option) {
case 1: {
std::bitset<CHAR_BIT * sizeof(unsigned long long)> bits;
get(bits);
std::cout << bits.to_ullong() << '\n';
break;
}
case 2: {
unsigned long long i;
get(i);
std::cout << std::bitset<CHAR_BIT * sizeof i>(i) << '\n';
break;
}
}
}
}
If you want this to loop you should be able to add it back in again easily enough.

Related

std::string::find returns npos when the char is present in the string

In a small utility I'm writing, I want to read a file record and:
look for the presence of an XOR checksum in the form *XX, where XX are hex digits
replace it if it's incorrect
add one if it's not present
So far, I'm only to the point of reading the file and looking for the checksum. The problem I'm up against is that std::string::find is not finding the * I know to be present; it returns npos every time.
The find() is on line 37. The first line read into strInput is:
$GPGGA,14240.99,2732.581,S,15301.947,E,1,06,3,65,M,37,M,-1.0,0006*6E\n
Here's the code:
#include <iostream>
#include <string>
int main()
{
std::cout << "Enter input file name:\n";
std::string strFileName = "";
std::getline(std::cin, strFileName);
std::cout << "Filename entered: " << strFileName << '\n';
FILE* fp;
int nErrCode = EXIT_FAILURE;
fopen_s(&fp, strFileName.c_str(), "r+");
if (!fp)
{
std::string strErr = "Failed to open " + strFileName;
perror(strErr.c_str());
return nErrCode;
}
rewind(fp);
std::string strInput;
strInput.reserve(100);
std::string::size_type n;
do
{
fgets(&strInput[0], 99, fp);
std::cout << strInput.c_str();
//n = 0;
n = strInput.find('*');
if (n != std::string::npos)
std::cout << "Found checksum at position " << n;
else
std::cout << "Did not find checksum";
} while (!feof(fp));
}
Thanks in advance.
I've debugged this and all is well up to the find(). At that point, I can see that the return value is npos, even though I can see the value of strInput and verify that it contains an asterisk.

My code is stuck in an infinite loop in C++

I am trying to use a while loop to calculate the average of 3 inputted grades, but I can not enter the next grade as the loops keep on going without giving me the chance to enter the next grade.
#include<iostream>
using namespace std;
int main()
{
int grade = 0;
int count = 0;
int total = 0;
cout << "Enter grade: ";
cin >> grade;
while (grade != -1)
{
total = total + grade;
count = count + 1;
cout << "Enter next grade: ";
cin >> grade;
}
int(average) = total / 3;
cout << "Average: " << int(average) << endl;
system("pause");
}
I tested your code with integer and it works fine.
If you only take int as input, the best is to put something to check the input type. Use cin.fail() to check if user input anything other than int.
for example:
while(cin.fail()) {
cout << "Error" << endl;
cin.clear();
cin.ignore(256,'\n');
cout << "Please enter grade:"
std::cin >> grade;
}
which I refer from https://www.codegrepper.com/code-examples/cpp/how+to+check+type+of+input+cin+c%2B%2B
and here as well Checking cin input stream produces an integer

I'm trying to make a loop to draw multiple lines in cairo but it stops drawing after the first iteration

I'm making a program where a person can input a direction and in the if statement, it adds/subtracts x/y axis and it draws a line after it gets over. The problem is that for some reason, it only works at the first iteration and doesn't draw any more lines after that.
I added a cin >> x >> y to test it out but it only draws one line and doesn't draw anymore.
Initially, the choices were in a switch statement but I changed to if because I thought that was causing the error.
#include "pch.h"
#include <iostream>
#include <fstream>
#include <string.h>
#include <cairo.h>
#define _USE_MATH_DEFINES
#include <math.h>
using namespace std;
char b = NULL;
char u = 'œ';
char d = 'd';
int main()
{
cairo_surface_t *surface = cairo_image_surface_create_from_png("background.png");
cairo_t *cr = cairo_create(surface);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_set_line_width(cr, 5);
double x = 0, y = 240;
cairo_move_to(cr, x, y);
long int count = 0;
int cl = 0;
int crr = 0;
int choice = 0;
int n;
system("cls");
while (choice != 5)
{
cin >> x >> y;
cairo_line_to(cr, x, y);
cairo_stroke(cr);
cairo_surface_write_to_png(surface, "spiral.png");
cout << "Current no. of points are : " << count << "/4096" << endl;
cout << "Enter direction: \n" << endl;
cout << "1 - Top Left \t 2 - Up \t 3 - Top Right " << endl;
cout << "4 - Left \t 5 - Stop \t 6 - Right" << endl;
cout << "7 - Bot. Left \t 8 - Down \t 9 - Bot. Right" << endl << endl;
cout << "Enter you choice: ";
cin >> choice;
if (choice == 1)
cout << "Test";
else
{
//More choices include the direction the person needs to go and it subtracts/adds to the x/y part
cout << "How many times ?: ";
cin >> n;
for (int i = 1; i <= n; i++)
{
x++;
count++;
cl++;
if (cl == 256)
{
cl = 0;
crr++;
}
}
system("cls");
}
}
}
I expect it to draw lines to a particular direction. Say the person inputs right, it draws a line towards right and so on. But here, no lines get drawn at all (except if I add a cin >> x >> y at the start of the while loop, that draws one line and that's it, no more lines.)
This fails because there is no current point anymore. After cairo_stroke(cr);, you can add cairo_move_to(cr, x, y); and it should start drawing more lines in the way you expect. I think... I'm not quite sure what you are up to with this program.

Trying to make a simple client sided chatbox; giving me a cout problem

I am almost completely new to c++ and have been trying to create a simple client sided chat box just to test but have come across the problem that the output of my cin gives only the first letter of the name given.
~ Jayden
I've tried declaring the "userName" as a bool, int and char however two of these give the cout a number as the outcome. I have youtubed this but it seems like it's a noob problem so no one has an answer from what I've seen.
#include <iostream>
#include <string>
using namespace std;
int main()
{
int userName;
bool nameSuccess = false;
cout << "Welcome to ChatBox v1.43" << endl;
cout << "========================" << endl;
do {
cout << "Enter a username: ";
cin >> userName;
cout << "You will now be known as ";
cout << userName;
nameSuccess = true;
} while (!nameSuccess);
system("pause");
cin.ignore();
cin.clear();
cin.get();
return 0;
}
The console should output the user name in this format : "You will now be known as (userName)"
int userName;
This should be.
string userName;
As a name is a string, not an integer.
The type of a variable is super important in C++. So you should definitely take the time and look up what int, char, bool mean. Once you have done that you will see why none of them work for a name.

Do while loop won't break

I am making a Goldilocks game. If the user chooses the wrong answer it would loop back to the beginning of the program. When I try to choose any option it always loops back to the beginning including the correct answer which is 2. I am still new to c++. I do not understand why it is looping to the beginning if the condition is true when 2 is chosen.
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
void FirstSet()
{
bool win = false;
string PName;
int choice;
int num1, num2, result;
do
{
system("CLS");
cout << " Please Enter Name \n";
cin >> PName;
cout << PName << " and the Three Bears\n\n ";
cout << PName << " Walks up and sees 3 Doors, 1 Large Door, 1 Medium
Door and 1 Small Door. \n\n\n " << "Which Door do you want to Open?\n "
<< " 1 for The Large Door\n " << " 2 for the Medium Door\n " << " 3
for the small door\n ";
cin >> choice;
if (choice == '1')
{
cout << " The large door is too heavy it will not budge.\n "
<< " Please Try Again\n\n ";
system("pause");
}
else if (choice == '2')
{
win = true;
}
else if (choice == '3') {
cout << " The Door is too small you would get stuck.\n "
<< "Please Try Again\n\n";
}
} while (!win);
}
int main()
{
FirstSet();
system("pause");
return 0;`
The reason none of your comparisons are turning true is because you are reading the input into an int variable. Then you are comparing to ascii character values of 1,2 and 3 which happen to be 49, 50 and 51 respectively. If you modify your if lines to compare directly with integers, it should work:
if (choice == 1)
{
...
}
else if (choice == 2)
{
...
}
else if (choice == 3)
{
...
}
Although, for readability purposes and also to avoid such cases, I recommend using switch case statements in this case.

Resources