I managed to code the following program to reverse any number the user inputs. However, I need to make it so that it returns an error message if the user input begins with 0 (e.g. 0175). What would be the simplest way to do that?
#include<iostream>
using namespace std;
int main ()
{
char choice;
do {
int n, val, remainder, reverse = 0;
cout << "Enter a number that you would like to reverse: ";
cin >> n;
val = n;
while (n != 0)
{
remainder = n % 10;
reverse = reverse * 10 remainder;
n = n / 10;
}
cout << "The reverse of " << val << " is " << reverse << endl;
cout << "Would you like to reverse another number? (Y/N) ";
cin >> choice;
} while (choice == 'y' || choice == 'Y');
cout << "Thanks for using this program!";
}
CodePudding user response:
You should take it as a string and make the necessary check. You can take this for an example.
#include<iostream>
#include <string>
using namespace std;
int main ()
{
char choice;
do {
string n; int val, remainder, reverse = 0;
cout << "Enter a number that you would like to reverse: ";
cin >> n;
if(n.at(0)=='0')
{
cout<<"error";
return 0;
}
val = atoi(n.c_str());
int temp = atoi(n.c_str());
while (temp != 0)
{
remainder = temp % 10;
reverse = reverse * 10 remainder;
temp = temp / 10;
}
cout << "The reverse of " << val << " is " << reverse << endl;
cout << "Would you like to reverse another number? (Y/N) ";
cin >> choice;
} while (choice == 'y' || choice == 'Y');
cout << "Thanks for using this program!";
}
CodePudding user response:
If you analyze your requirements, then obviously you need to check a single digit, the first digit.
So a formatted input function, which converts the input characters for your into a number, will not work. WIth that, I mean int number; std::cin >> number
will always try to convert, whatever digit sequence you give, to a number.
So, there are 2 possible solutions:
- Read digit (a single character) by digit and build a number out of it (CAVEAT)
- use none formatted input functions, like
std::getline
, make a validation and convert it to a string.
First solution would immediately validate the first digit after input and could give an immediate result. The 2nd solution is even more simpler, because you could could additionally use build in string function.
But, solution 1 will not work, because you cannot read single characters from std::cin
in standard C . Input is buffered by C and the terminal. Please read for example here. Maybe astonishing, but also somehow logical. The user wants to input something, and, if there was a typo, press the backspace button, and after everything done, press enter.
So, the only viable solution for you is to read the number as a string. Then you may either convert it to a number and use your algorithm, or, use existing functions, like std::reverse
or reverse iterators.
In any case, a lot of error checking must be done.
Please see below an example with all kinds of error checking:
#include <iostream>
#include <cctype>
#include <climits>
#include <string>
int main() {
// We need a indicator, if an input is valid or not
bool inputNumberIsValid{};
// Loop. unitl the input number is valid
do {
// Instruct user on what to do
std::cout << "\n\nEnter a number that you would like to reverse:\n";
// Assum for the moment, taht the input is valid
inputNumberIsValid = true;
// This is the number we eventually want to have.
unsigned int number{};
// Read a number as string and check, if that worked
std::string numberAsString{};
if (not std::getline(std::cin, numberAsString)) {
// Problem with input, reported by getline or better said std::cin
std::cerr << "\n*** Error: Problem with input\n";;
inputNumberIsValid = false;
break;
}
else {
// Now, we have a string to work with. In the beginning, we want to check for leading 0s
bool checkForLeadingZeroes{ true };
// Iterate over all characters in the input string and check for all error cases
for (const char c : numberAsString) {
// Only digits are allowed
if (not std::isdigit(c)) {
// Problem found. Show error message, indicate an invalid input and stop loop
std::cerr << "\n*** Error: Only digits are allowed\n";;
inputNumberIsValid = false;
break;
}
else {
// Check for a leading 0
if (checkForLeadingZeroes and c == '0') {
// Problem found. Show error message, indicate an invalid input and stop loop
std::cerr << "\n*** Error: Leading 0s are not allowed\n";;
inputNumberIsValid = false;
break;
}
else {
// Valid number. Convert digit characters to a number
number = number * 10;
number = (c - '0');
// If the number is too big
if (number >= std::numeric_limits<unsigned int>::max() / 10) {
// Problem found. Show error message, indicate an invalid input and stop loop
std::cerr << "\n*** Error: Number is too big\n";
inputNumberIsValid = false;
break;
}
}
}
// After we did the forst check for leading 0es, we will no longer check 0s at all
checkForLeadingZeroes = false;
}
}
// OK, number rerad. If it is valid
if (inputNumberIsValid) {
// Then reverse the number
unsigned int temp {static_cast<unsigned int>(std::stoul(numberAsString))};
unsigned int reversedNumber{};
while (temp != 0) {
const unsigned int remainder = temp % 10;
reversedNumber = reversedNumber * 10 remainder;
temp = temp / 10;
}
// And show the final result
std::cout << "\n\nThe reversed number is: " << reversedNumber << '\n';
}
} while (not inputNumberIsValid);
}
This is a surprisingly long piece of code.
Please remember: Reading from std::cin
is very complex and error prone.
By the way. In C you would do it more efficiently.
Please see below one of many possible examples:
#include <iostream>
#include <cctype>
#include <climits>
#include <string>
#include <algorithm>
#include <iterator>
int main() {
// Loop. unitl the input number is valid
for (bool numberIsValid{}; not numberIsValid;) {
// Instruct user on what to do
std::cout << "\n\nEnter a number (digits only, no leading 0es) that you would like to reverse:\n";
// Read a number as string and check, if it is valid
if (std::string numberAsString{}; std::getline(std::cin, numberAsString) and
not numberAsString.empty() and
std::all_of(numberAsString.begin(), numberAsString.end(), std::isdigit) and
not (numberAsString[0] == '0') and
numberAsString.size() < std::numeric_limits<unsigned int>::digits10)
{
// Number is valid
numberIsValid = true;
std::cout << "\n\nReverse number is:\t ";
std::copy(numberAsString.rbegin(), numberAsString.rend(), std::ostream_iterator<char>(std::cout));
}
else {
std::cerr << "\nError: Invalid input\n\n";
}
}
}
To be compiled with C 17.
Only one if statement (with many "and"s) to check for any kind of error.
Using "std::algorithms"