How to reject an integer if certain digits are not wanted - c++

If i want an integer input, but if it contains any digits 2 or 3 in it, it will be rejected.
For example entering 23564 will be invalid.
I was thinking of using do-while loops to solve this, but how do I get it to read the individual digits.

Have a look here:
#include <iostream>
using namespace std;
int main() {
int n,num,flag;
do{
cout<<"Enter number";
cin>>n;
num = n;
flag = 0;
while(num>0)
{
if(num%10 == 2 || num%10 ==3)
{
flag = 1;
break;
}
num = num/10;
}
}while(flag==1);
return 0;
}

If you don't care much about performance, you can convert the integer into a string and look for the digits. This is slower than extracting the last digit and comparing it though.
std::string str = std::to_string(number);
auto found2 = str.find('2');
auto found3 = str.find('3');
//number is valid if it doesn't have a 2 or a 3
bool isValid = found2 == std::string::npos && found3 == std::string::npos;

You can get the last digit of a number with something like:
unsigned int number = 23456;
unsigned int digit = number % 10; // gives 6
You can further "shift" all digits right with:
number = number / 10; // gives 2345
In other words, yes, you can do it using the method you propose:
bool has2Or3(unsigned int number) {
// Do until no more digits left.
while (number != 0) {
// Get last digit, return true if 2 or 3.
int digit = number % 10;
if ((digit == 2) || (digit == 3)) {
return true;
}
// Prepare to get next digit.
number = number / 10;
}
// If NO digits were 2 or 3, return false.
return false;
}
Another way would be to simply convert it to a string and use the string functions to see if it contains a specific digit, something such as:
bool has2Or3(unsigned int number) {
// Get number as string (via string stream).
std::stringstream ss;
ss << number;
std::string s = ss.str();
// If contains 2, return true, else continue.
if (s.find("2") != std::string::npos)
return true;
// If contains 3, return true, else return false.
return (s.find("3") != std::string::npos);
}

Instead of reading the input directly into an integer type, read it into a std::string. Then it's simple to check for unwanted digits; if the string passes the test, convert it to an integer:
int get_value() {
std::string bad = "23";
std::string input = "2"; // start with bad input
while (std::find_first_of(input.begin(), input.end(),
bad.begin(), bad.end()) != input.end()) {
std::cout << "Gimme a number: ";
std::cin >> input;
}
return std::stoi(input);
}

Related

For reversing a number in C++ which ends with zeros

I want to write a program for reversing a number. For reversing a number like 2300 to 32 so that the ending zeros are not printed, I found this method:
#include<iostream>
using namespace std;
int main()
{
int l;
cin>>l;
bool leading = true;
while (l>0)
{
if ((l%10==0)&& (leading==true))
{
l /= 10;
leading = false; // prints 032 as output
continue;
}
// leading = false; this prints correct 32
cout<<l%10;
l /= 10;
}
return 0;
}
The instruction of assigning boolean leading false inside the if statement is not giving a valid answer, but I suppose assigning it false should give 32 as output whether we give it outside or inside if statement as its purpose is just to make it false once you get the last digit to be a non zero.
Please tell the reason of difference in outputs.
The reason for the difference in output is because when you make leading = false inside the if statement, you are making it false right after encountering the first zero. When you encounter the remaining zeroes, leading will be false and you will be printing it.
When you make leading = false outside the if statement, you are basically waiting till you encounter all zeroes before making it false.
If you are looking to reverse a number, this is the well known logic to do so:
int reverse(int n)
{
int r; //remainder
int rev = 0; //reversed number
while(n != 0)
{
r = n%10;
rev = rev*10 + r;
n /= 10;
}
return rev;
}
EDIT:
The above code snippet is fine if you just want to understand the logic to reverse a number. But if you want to implement the logic anywhere you have to make sure you handle integer overflow problems (the reversed number could be too big to be stored in an integer!!).
The following code will take care of integer overflow:
int reverse(int n)
{
int r; //remainder
int rev = 0; //reversed number
while(n != 0)
{
r = n%10;
if(INT_MAX/10 < rev)
{
cout << "Reversed number too big for an int.";
break;
}
else if(INT_MAX-r < rev*10)
{
cout << "Reversed number too big for an int.";
break;
}
rev = rev*10 + r;
n /= 10;
}
if(n != 0)
{
//could not reverse number
//take appropriate action
}
return rev;
}
First, rewrite without continue to make the flow clearer,
while (l > 0)
{
if ((l % 10 == 0) && (leading == true))
{
l /= 10;
leading = false; // prints 032 as output
}
else
{
// leading = false; this prints correct 32
cout << l % 10;
l /= 10;
}
}
and move the division common to both branches out of the conditional,
while (l > 0)
{
if ((l % 10 == 0) && (leading == true))
{
leading = false; // prints 032 as output
}
else
{
// leading = false; this prints correct 32
cout << l % 10;
}
l /= 10;
}
and now you see that the only difference between the two is the condition under which the assignment leading = false happens.
The correct version says, "If this digit is non-zero or a non-leading zero, remember that the next digit is not a leading zero, and print this digit. Then divide."
Your broken version says, "If this is a leading zero, the next digit is not a leading zero." which is pretty obviously not the case.
Just try this ,
#include <iostream>
using namespace std;
int main() {
int n, reversedNumber = 0, remainder;
cout << "Enter an integer: ";
cin >> n;
while(n != 0) {
remainder = n%10;
reversedNumber = reversedNumber*10 + remainder;
n /= 10;
}
cout << "Reversed Number = " << reversedNumber;
return 0;
}
Working for me...
When reversing digits of numbers or generally when working with digits and the actual
value does not matter then treating the number as an array of digits is simpler than working with the whole int. How to treat a number as an array of digits conveniently? std::string:
#include <iostream>
#include <string>
#include <sstream>
int reverse_number(int x) {
std::string xs = std::to_string(x);
std::string revx{ xs.rbegin(),xs.rend()};
std::stringstream ss{revx};
int result;
ss >> result;
return result;
}
int main() {
std::cout << reverse_number(123) << "\n";
std::cout << reverse_number(1230) << "\n";
}
std::to_string converts the int to a std::string. std::string revx{ xs.rbegin(),xs.rend()}; constructs the reversed string by using reverse iterators, and eventually a stringstream can be used to parse the number. Output of the above is:
321
321

How to reverse a negative integer recursively in C++?

I am working on some recursion practice and I need to write a program that reverse the input of an integer
Example of input : cin >> 12345; The output should be 54321
but if that integer is negative the negative sign needs to be appended to only the first number.
Example of input : cin >> -1234; output -4321
I am having a hard time getting my program to adapt to the negative numbers. The way I have it set up if I run
Example of test : 12345 I get the right output 54321
So my recursion and base are successful. But if I run a negative I get
Example of test : -12345 I get this for a reason I don't understand -5-4-3-2 1
#include<iostream>
using namespace std;
void reverse(int);
int main()
{
int num;
cout << "Input a number : ";
cin >> num;
reverse(num);
return 0;
}
void reverse(int in)
{
bool negative = false;
if (in < 0)
{
in = 0 - in;
negative = true;
}
if (in / 10 == 0)
cout << in % 10;
else{
if (negative == true)
in = 0 - in;
cout << in % 10;
reverse(in / 10);
}
}
To reverse a negative number, you output a - and then reverse the corresponding positive number. I'd suggest using recursion rather than state, like this:
void reverse(int in)
{
if (in < 0)
{
cout << '-';
reverse(-in);
}
else
{
// code to recursively reverse non-negative numbers here
}
}
Split the reverse function into two parts: the first part just prints - (if the input is negative) and then calls the second part, which is the recursive code you have. (You don't need any of the if (negative) ... handling any more, since the first part already handled it.)
Incidentally, if (bool_variable == true) ... is overly verbose. It's easier to read code if you say something like if (value_is_negative) ....
Your recursive function doesn't hold state. When you recurse the first time, it prints the '-' symbol but every time you send back a negative number to the recursion, it runs as if it is the first time and prints '-' again.
It's better to print '-' first time you see a negative number and send the rest of the number as a positive value to the recursion.
#include<iostream>
using namespace std;
void reverse(int);
int main()
{
int num;
cout << "Input a number : ";
cin >> num;
reverse(num);
return 0;
}
void reverse(int in)
{
bool negative = false;
if (in < 0)
{
in = 0 - in;
negative = true;
}
if (in / 10 == 0)
cout << in % 10;
else{
if (negative == true) {
cout << '-';
negative = false;
}
cout << in % 10;
reverse(in / 10);
}
}
int reverse(long int x) {
long int reversedNumber = 0, remainder;
bool isNegative = false;
if (x <0){
isNegative = true;
x *= -1;
}
while(x > 0) {
remainder = x%10;
reversedNumber = reversedNumber*10 + remainder;
x= x/10;
}
if (isNegative) {
if (reversedNumber > INT_MAX){
return 0;
}
else
return reversedNumber*(-1);
}
else
{
if (reversedNumber > INT_MAX){
return 0;
}
else
return reversedNumber;
}
}

Integer to String: Without using stoi library

I found this question in the book where it asks us to transfer an Int to a string. Without using stoi library
so for example if x = 10, s="10"
the code should handle negative numbers.
I found this solution in the book. I typed it in my compiler however it is giving the string of the first number only
so if x= 45, it is giving "4"
I do not understand this line s = '0' + x%10; to be able to fix the code.
why is he adding '0' to the string. What is the best solution.
here is the code: I added comments to the parts I understand
#include<iostream>
#include<string>
using namespace std;
void IntToString(int x);
int main()
{
int num;
cout << "Please enter a number" << endl;
cin >> num;
IntToString(num);
}
void IntToString(int x)
{
bool isNegative = false;
if(x < 0) //if its negative make boolean true
{
x = -x;
isNegative = true;
}
string s;
do
{
s = '0' + x%10; //modulus for getting the last number
x = x/10; //shorten the number
}while(x);
reverse(s.begin(), s.end()); //reverse the string since it starts from end
if(isNegative)
s = '-' + s;
cout << s << endl;
}
s = '0' + x%10;
will grabs the last digit from x%10 and add ASCII of 0 i.e. 48, giving the ASCII of desired last digit, which get copy assigned to string s using its assignment operator.
And btw, you need :
s += '0' + x%10;
~~ // += operator
The problem with the do ... while loop is that you just extract the last digit of the changed x only to replace it with the second last digit and so on, until you get the first digit of x stored in s.
There is no effect of reverse(s.begin(), s.end()) since s practically holds only one character.
Also, we add '0' to s because s initially stores the integer value of the number, and adding '0' converts it into its ASCII form.
Example:
void IntToString(int x)
{
bool isNegative = false;
if(x < 0)
{
x = -x;
isNegative = true;
}
string s;
do
{
//The below code appends the new number at the beginning of s.
s = ('0' + x%10) + s; //modulus for getting the last number
x = x/10; //shorten the number
}while(x);
if(isNegative)
main_string = '-' + main_string;
cout << main_string << endl;
}

Cannot understand why function will not work

The goal of this program is to input a base followed by any number of spaces and then a sequence of characters, any number as long as they are 1 less than the base. I have the errors covered, but I cannot get it to display.
If I input 2 1101, my output is For the given base 2, "Nothing appears".
The output should be the following: Test Case # 1
Input for Run 1:
2 1101
3 1212
5 66
2 1111
8 36
2 01
The output for Test Run 1:
For the given base 2, the decimal value of the input string is 11.
For the given base 3, the decimal value of the input string is 70.
For the given base 5, the number is NOT valid!
For the given base 2, the decimal value of the input string is 15.
For the given base 8, the decimal value of the input string is 51.
For the given base 2, the decimal value of the input string is 2.
Here is my coding for this section of the program I have issues with:
#include <iostream>
#include <cmath>
using namespace std;
const int MAX_CHARS = 256;
const int MAX_BASE = 10;
int readUntiValidBaseRead();
int readNumbersReturningValue( int base );
int decimalValueOf( char chDigit );
bool isValid( char chDigit, int base );
//---------------------------------------------------------------------
// This function reads bases until a valid base is read or eof occurs.
// If an invalid base is read, an error message is displayed and the
// rest of the line is ignored and another attempt to read a base value
// will be attempted.
// -1 is returned if eof occurs otherwise a valid base value is
// returned.
//---------------------------------------------------------------------
int readUntilValidBaseRead()
{
int readingBase;
cin >> readingBase;
while( !cin.eof() && (readingBase < 1 || readingBase > MAX_BASE))
{
cout << "Invalid base given, " << endl;
cin.ignore(MAX_CHARS, '\n');
cin >> readingBase;
}
if(readingBase > 1 && readingBase <= MAX_BASE)
return readingBase;
else
return -1;
}
//---------------------------------------------------------------------
// This function reads in a sequence of characters that represent
// a number in the given base. A valid sequence is given in a
// "backwards" format such that the rightmost digit is given first,
// the second to the rightmost digit is next, etc.
// This function returns the value of this sequence of characters if
// it is a valid sequence. If it is not valid it returns -1.
// params: base -> IN
//---------------------------------------------------------------------
int readNumbersReturningValue( int base )
{
char readingNumber;
int sum = 0;
int theValue = 1;
bool flaq = true;
cin >> readingNumber;
while(readingNumber != '\n' && flaq)
{
flaq = isValid(readingNumber, base);
sum += (theValue* decimalValueOf(readingNumber));
theValue *= base;
cin >> readingNumber;
flaq = isValid(readingNumber, base);
}
if(flaq == true)
return sum;
else
return -1;
}
//---------------------------------------------------------------------
// This function returns the numeric value of the character digit that
// is stored in chDigit.
// params: chDigit -> IN
//---------------------------------------------------------------------
int decimalValueOf( char chDigit )
{
int decimalNum;
decimalNum = chDigit - '0';
return decimalNum; //return integer value of
}
//---------------------------------------------------------------------
// This function returns true if chDigit is a valid digit in the given
// base, it returns false otherwise.
// params: chDigit -> IN, base -> IN
//---------------------------------------------------------------------
bool isValid( char chDigit, int base )
{
if(decimalValueOf(chDigit) >= 0 && decimalValueOf(chDigit) < base)
return true;
else
return false;
}
//---------------------------------------------------------------------
//
//
//
int main()
{
int totalSum = 0;
int base;
int singleSum;
base = readUntilValidBaseRead();
while(!cin.eof())
{
cout << "For the given base " << base << ", ";
singleSum = readNumbersReturningValue(base);
if(singleSum == -1)
{
cout << "Not valid. Throwing away rest of line. " << endl;
cin.ignore(MAX_CHARS, '\n');
}
else
{
cout << "The decimal value of the input string is " << singleSum;
totalSum += singleSum;
}
base = readUntilValidBaseRead();
}
cout << totalSum;
return 0;
}
Here:
cin >> readingNumber;
while(readingNumber != '\n' && flaq)
{
flaq = isValid(readingNumber, base);
sum += (theValue* decimalValueOf(readingNumber));
theValue *= base;
cin >> readingNumber;
flaq = isValid(readingNumber, base);
}
you increment sum on the first read, regardless of whether or not the character read is valid. And it never will be valid, since your isValid() function returns false for spaces. You should skip over any spaces, and only then start checking for digits. You don't need to worry about spaces when you read into an int, but you do when you're reading into a char, because whitespace characters are characters, and cin doesn't know whether or not you want to skip them.
You can skip them with something like:
do {
cin >> readingNumber;
} while ( isspace(readingNumber) );
You'll need to #include <cctype> for isspace(). Note this will skip any whitespace character, including tabs and newlines, so you might want to check for \n individually if you might have completely missing input.
Here's a working example, just for the skipping the spaces and reading your numbers (i.e. ignoring reading the base):
#include <iostream>
#include <cctype>
int decimalValueOf(char chDigit) {
return chDigit - '0';
}
bool isValid(char chDigit, int base) {
return (decimalValueOf(chDigit) >= 0 && decimalValueOf(chDigit) < base );
}
int readNumbersReturningValue(int base) {
char readingNumber;
int sum = 0;
int theValue = 1;
bool flaq = true;
do {
std::cin >> readingNumber;
} while ( std::isspace(readingNumber) );
while ( readingNumber != '\n' && (flaq = isValid(readingNumber, base)) ) {
sum += (theValue* decimalValueOf(readingNumber));
theValue *= base;
readingNumber = std::cin.get();
}
if ( flaq ) {
return sum;
} else {
return -1;
}
}
int main() {
int sum = readNumbersReturningValue(2);
std::cout << "Sum is: " << sum << std::endl;
return 0;
}
outputs:
paul#local:~/src/cpp/scratch$ ./readchars
1101
Sum is: 11
paul#local:~/src/cpp/scratch$
Note that std::cin >> readingNumber; won't work for picking up newlines, since std::cin is line buffered, so you have to use std::cin.get() instead.

testing a string to see if a number is present and asigning that value to a variable while skipping all the non-numeric values?

given a string say " a 19 b c d 20", how do I test to see if at that particular position on the string there is a number? (not just the character '1' but the whole number '19' and '20').
char s[80];
strcpy(s,"a 19 b c d 20");
int i=0;
int num=0;
int digit=0;
for (i =0;i<strlen(s);i++){
if ((s[i] <= '9') && (s[i] >= '0')){ //how do i test for the whole integer value not just a digit
//if number then convert to integer
digit = s[i]-48;
num = num*10+digit;
}
if (s[i] == ' '){
break; //is this correct here? do nothing
}
if (s[i] == 'a'){
//copy into a temp char
}
}
These are C solutions:
Are you just trying to parse the numbers out of the string? Then you can just walk the string using strtol().
long num = 0;
char *endptr = NULL;
while (*s) {
num = strtol(s, &endptr, 10);
if (endptr == s) { // Not a number here, move on.
s++;
continue;
}
// Found a number and it is in num. Move to next location.
s = endptr;
// Do something with num.
}
If you have a specific location and number to check for you can still do something similar.
For example: Is '19' at position 10?
int pos = 10;
int value = 19;
if (pos >= strlen(s))
return false;
if (value == strtol(s + pos, &endptr, 10) && endptr != s + pos)
return true;
return false;
Are you trying to parse out the numbers without using any library routines?
Note: I haven't tested this...
int num=0;
int sign=1;
while (*s) {
// This could be done with an if, too.
switch (*s) {
case '-':
sign = -1;
case '+':
s++;
if (*s < '0' || *s > '9') {
sign = 1;
break;
}
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
// Parse number, start with zero.
num = 0;
do {
num = (num * 10) + (*s - '0');
s++;
} while (*s >= '0' && *s <= '9');
num *= sign;
// Restore sign, just in case
sign = 1;
// Do something with num.
break;
default:
// Not a number
s++;
}
}
It seems like you want to parse the string and extract all the numbers from it; if so, here's a more "C++" way to do it:
string s = "a 19 b c d 20"; // your char array will work fine here too
istringstream buffer(s);
string token;
int num;
while (!buffer.eof())
{
buffer >> num; // Try to read a number
if (!buffer.fail()) { // if it doesn't work, failbit is set
cout << num << endl; // It's a number, do what you want here
} else {
buffer.clear(); // wasn't a number, clear the failbit
buffer >> token; // pull out the non-numeric token
}
}
This should print out the following:
19
20
The stream extraction operator pulls out space-delimited tokens automatically, so you're saved from having to do any messy character-level operations or manual integer conversion. You'll need to #include <sstream> for the stringstream class.
You can use atoi().
after your if you need to shift to while to collect subqsequent digits until you hit a non-digit.
BUT, more inportantly, have you clearly defined your requirements? Will you allow whitespace between the digits? What if there are two numbers, like abc123def456gh?
Its not very clear what you are looking for.. Assuming you want to extract all the digits from a string and then from a whole number from the found digits you can try the following:
int i;
unsigned long num=0; // to hold the whole number.
int digit;
for (i =0;i<s[i];i++){
// see if the ith char is a digit..if yes extract consecutive digits
while(isdigit(s[i])) {
num = num * 10 + (s[i] - '0');
i++;
}
}
It is assumed that all the digits in your string when concatenated to from the whole number will not overflow the long data type.
There's no way to test for a whole number. Writing a lexer, as you've done is one way to go. Another would be to try and use the C standard library's strtoul function (or some similar function depending on whether the string has floating point numbers etc).
Your code needs to allow for whitespaces and you can use the C library's isdigit to test if the current character is a digit or not:
vector<int> parse(string const& s) {
vector<int> vi;
for (size_t i = 0; i < s.length();) {
while (::isspace((unsigned char)s[ i ]) i++;
if (::isdigit((unsigned char)s[ i ])) {
int num = s[ i ] - '0';
while (::isdigit((unsigned char)s[ i ])) {
num = num * 10 + (s[ i ] - '0');
++i;
}
vi.push_back(num);
}
....
Another approach will be to use boost::lexical_cast:
vector<string> tokenize(string const& input) {
vector<string> tokens;
size_t off = 0, start = 0;
while ((off = input.find(' ', start)) != string::npos) {
tokens.push_back(input.substr(start, off-start));
start = off + 1;
}
return tokens;
}
vector<int> getint(vector<string> tokens) {
vector<int> vi;
for (vector<string> b = tokens.begin(), e = tokens.end(); b! = e; ++b) {
try
{
tokens.push_back(lexical_cast<short>(*b));
}
catch(bad_lexical_cast &) {}
}
return vi;
}