How to find out if string is only numbers, no letters - c++

I have constructed a code that checks if the entered number is a proper divisible of 9 by getting the string length and finding the sum of each digit entered and finding if its perfectly divisible by 9.
The code works well, I just need some error checks and I have two things to try and add to it.
I need to make sure first that the inputted information is only numbers, no letters.
Also I want to find a way to make input limited from 1 to 1000.
I have this bool example that will check if it is in fact a number, but how can I make an if statement for my userNum input to check the boolean?
bool isNumber(const string &line)
{
if (line[0] == '0') return true;
return (atoi(line.c_str()));
}
#include <iostream>
#include <string>
using namespace std;
string userNum;
char userInput;
int sum, i, n;
int main()
{
tryagain:
sum = 0;
cout << "Enter number to test if it is divisible by 9: ";
cin >> userNum;
if (userNum == isNumber) {
cout << "Nah..";
return 0;
// Find sum of digits by seperating
n = userNum.length(); // Gets the sum of the string length in bytes
}
for (i = 0; i < n; i++) // Starting from 0, until num is less than the length of userNum go up one increment
sum = (sum + (userNum[i] - '0'));
if (sum % 9 == 0) {
cout << "Your number, " << userNum << " adds up to " << sum << " which is evenly divisible to 9" << endl << endl;
}
else {
cout << "Your number, " << userNum << " adds up to " << sum << " which IS NOT evenly divisible to 9" << endl << endl;
}
// Restart option begins here.
cout << "Would you like to try another number? (Y/N): ";
cin >> userInput;
if (userInput == 'y' || userInput == 'Y') {
goto tryagain;
cout << endl;
}
else if (userInput == 'n' || userInput == 'N') {
cout << endl;
cout << "Goodbye!" << endl;
}
else {
cout << endl;
cout << "You have entered an unknown input, goodbye!" << endl;
}
system("pause");
return 0;
}

You could do this in 3 ways:
Use a regular expression, with std::regex_match. The regex that you are looking for is ^[0-9]+$ which checks if a string contains only numbers. This is a possible expression but not the absolute one
Use std::stoi which tries to convert a string into an integer. Be sure to surround it with a try-catch statement to ensure that the string can be properly parsed. If you get the exception, then the string is not a number.
As Justin has pointed out in the comments, you could also try using std::isdigit and iterate over the string to check each char.
Rely on std functions and try to avoid writing code by yourself. The second approach is probably what you are looking for because, if the method does not throw an exception, you can check the range of the number.
When you face a problem for which you cannot find a solution, give a look at the list of algorithms on cppreference. Use them as much as you can because they make the code shorter, easier to read and they can give you advantages (some algorithms just need an extra parameter at the end to start a parallel execution of the method!)

for (i = 0; i < n; i++) {
if(userNum[i] < '0' || userNum[i] > '9') {
cout << "Nah..";
return 0;
}
sum = (sum + (userNum[i] - '0'));
}

Given the necessary range-check with the range being 1...1000, you do not gain anything from summing the digits and dividing the sum by 9, instead of just doing the latter on the number itself. So the numerical part could be simple i < 1, i > 1000, i % 9 == 0 checks, where i is the parsed integer.
std::stoi parses a number at the beginning of a string, so while you can use it, it does not replace checking the characters. e.g. 1, 1.2, 1a are all parsed to 1. You need a string which does not start with a number, and only then you get an std::invalid_argument exception. So you will need #Justin's suggestion too, though here I flipped it as "any_of the characters is not a digit:
std::string s;
std::cin >> s;
try {
if (std::any_of(s.begin(), s.end(), [](char c) { return !std::isdigit(c); }))
throw std::invalid_argument(" is not all-digits");
int i = std::stoi(s);
if (i < 1) throw std::invalid_argument(" is less than 1");
if (i > 1000) throw std::invalid_argument(" is more than 1000");
if (i % 9 == 0) std::cout << i << " is divisible by 9" << std::endl;
else std::cout << i << " is not divisible by 9" << std::endl;
}
catch (std::invalid_argument ia) {
std::cout << s << ia.what() << std::endl;
}
catch (std::out_of_range oor) {
std::cout << s << " sure is not between 1 and 1000";
}
(stoi's "own" invalid_argument can not occur here, because of the pre-check for all-digits)
In the case you would want to get a number between 1 and 1010000 inclusive, then yes, you could start doing magics, like checking length of input, various patterns, and summing the digits:
(Example is tuned down to 1010 so it can be tested without getting a headache)
std::string s;
std::cin >> s;
std::string::iterator it = s.begin(), end = s.end();
int len = end - it;
try {
// if(len==0) will not happen because of the cin
if (*it == '0') {
if (len == 1) throw std::invalid_argument(" is less than 1");
throw std::invalid_argument(" starts with 0, multi-digit numbers do not do that");
}
if (len > 11) throw std::invalid_argument(" is too long for not being greater than 10^10");
if (len == 11) {
if (*it != '1'
|| std::any_of(it + 1, end, [](char c) { return c != '0'; }))
throw std::invalid_argument(" is greater than 10^10 or is not all-digits");
// well, here we know that the number is 10^10 (and is not divisible by 9)
// so this could return early
}
int sum = 0;
for (; it != end; ++it) {
if(!std::isdigit(*it)) throw std::invalid_argument(" is not all-digits");
sum += (*it) - '0';
}
if (sum % 9 == 0)std::cout << s << " is divisible by 9" << std::endl;
else std::cout << s << " is not divisible by 9" << std::endl;
}
catch (std::invalid_argument ia) {
std::cout << s << ia.what() << std::endl;
}

Related

How should I do with "std::cerr" and "std::cin.fail()" using c++?

Could you please help me with the small question?
Question:
The program should return an error code(1) and print this exact string in case a failure is encountered:
“Error encountered, exiting...”
My code:
#include <iostream>
#include <random>
int main(int argc, char const *argv[])
{
int number, random;
random = (std::rand() % 100);
while (std::cin >> number)
{
if (number < random && number >= 0)
{
std::cout << "This number is larger." << std::endl;
}
else if (number > random && number <= 99)
{
std::cout << "This number is smaller." << std::endl;
}
else if (std::cin.fail())
{
std::cout << "Error encountered, exiting..." << std::endl;
}
else if (number < 0 || number > 99)
{
std::cout << "[WARNING] : Number must be between 0 and 99" << std::endl;
}
else if (number == random)
{
std::cout << "Great! You're right!" << std::endl;
break;
}
};
return 0;
}
After compilation, I will input e.g. 'write'. My programming is directly finished. I don't get 'Error encountered, exiting...' in my terminal.
Could you give some suggestions about std::cin.fail()? How should I do?
I also don't understand, could I change here std::cout using std::cerr? What is the big difference between std::cout and std::cerr?
Thanks so much
Best regards
You should test std::cin.fail() after the while loop because if std::cin >> number fails, the body of the while loop will not be entered.
You could also restructure the tests a bit to not have to perform the same tests over and over again. Also, std::endl flushes the output stream which is unnecessary in the vast majority of cases and just takes extra time.
// ...
while (std::cin >> number)
{
if (number < 0 || number > 99)
{
std::cout << "[WARNING] : Number must be between 0 and 99\n";
}
else if (number < random) // no need to test if it's out of bounds
{
std::cout << "This number is larger.\n";
}
else if (number > random) // no need to test if it's out of bounds
{
std::cout << "This number is smaller.\n";
}
else // no need to test anything
{
std::cout << "Great! You're right!\n";
break;
}
}
if(std::cin.fail())
{
std::cout << "Error encountered, exiting...\n";
return 1;
}
return 0;
}
The difference between std::cout and std::cerr is which output stream it'll use. People running your program can read both streams separately if they want to do logging of errors for example.

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);

Create a program that takes as input a string of digits and outputs the sum of the even and the sum of the odd digits

Create a program that takes as input a string of digits and outputs
the sum of the even and the sum of the odd digits. This program is in
C++
NOTE: It is recommended that you use a "for" loop to iterate over the
sting of digits. HINT: Use the modulus operator to determine even or
odd digits.
A clever method of converting a "char" to an "int" is as follows link:
char a = '4';
int ia = a - '0';
The above code takes advantage of the character's position in the
ASCII table to convert it to an integer.
Below is the code I have so far:
int main() {
int sumOdd = 0; // For accumulating odd numbers, init to 0
int sumEven = 0; // For accumulating even numbers, init to 0
int digits; // Sum from 1 to this upperbound
// Prompt user for an upperbound
cout << "Please enter a string comprised ONLY of digits:" << endl;
cout << endl;
cin >> digits;
// Use a while-loop to repeatedly add 1, 2, 3,..., to the upperbound
int number = 1;
while (number <= digits) {
if (number % 2 == 0) { // Even number
sumEven += number; // Add number into sumEven
} else { // Odd number
sumOdd += number; // Add number into sumOdd
}
++number; // increment number by 1
}
// Print the results
cout << "The string of digits \"" << digits << "\""
<< " contained "
<< "characters." << endl;
cout << "The sum of the even digits is: " << sumEven << endl;
cout << "The sum of the odd digits is: " << sumOdd << endl;
return 0;
}
This is my output compared to the output I need
Input:
1234567890
Output:
Please enter a string comprised ONLY of digits:
The string of digits "1234567890" contained characters.
The sum of the even digits is: -380436870
The sum of the odd digits is: -997720815
Expected output
Please enter a string comprised ONLY of digits:
The string of digits "1234567890" contained 10 characters.
The sum of the even digits is: 20
The sum of the odd digits is: 25
Overall I'm having trouble counting the input and getting the correct formula for my even and odd numbers. Any help is appreciated thank you so much!
A simple method is to keep the number in text form:
std::string number_as_text;
cout << "Enter number: ";
cin >> number_as_text;
This allows you to check each digit for even or odd:
const size_t length = number_as_text.length();
for (size_t i = 0; i < length; ++i)
{
char digit_character = number_as_text[i];
if (isdigit(digit_character))
{
if (digit_character % 2 == 0)
{
// digit is even
}
else
{
// digit is odd
}
}
}
If you don't like isdigit(), you can replace with:
if ((digit_character >= '0') && (digit_character < '9'))
An important note is that there is a difference between the textual representation of digits and the internal, numeric, representation of digits.
Edit 1: % on char type
The char data type is an integer. The remainder operator, %, works on integer types. Thus you can use % on char types.
Note: this operation assumes that the character mapping of '0' is an even integer and the other digits are successive in values.
Read the inputs in a string field and not an integer as -
std::string digits;
Then, just run a valid loop to find out the sum of the even digits and the odd digits -
for(int i=0; i<digits.length(); i++){
int digit = digits[i]-'0';
if(digit % 2 == 0)
sumEven+=digit;
else
sumOdd+=digit;
}
Below is a running piece of code.
// Example program
#include <iostream>
#include <string>
using namespace std;
int main() {
int sumOdd = 0; // For accumulating odd numbers, init to 0
int sumEven = 0; // For accumulating even numbers, init to 0
std::string digits; // Sum from 1 to this upperbound
// Prompt user for an upperbound
cout << "Please enter a string comprised ONLY of digits:" << endl;
cout << endl;
cin >> digits;
// Use a while-loop to repeatedly add 1, 2, 3,..., to the upperbound
int number = 1;
for(int i=0; i<digits.length(); i++){
int digit = digits[i]-'0';
if(digit % 2 == 0)
sumEven+=digit;
else
sumOdd+=digit;
}
// Print the results
cout << "The string of digits \"" << digits << "\""
<< " contained "
<< "characters." << endl;
cout << "The sum of the even digits is: " << sumEven << endl;
cout << "The sum of the odd digits is: " << sumOdd << endl;
return 0;
}
You got it wrong you are supposed to do sum of 1+3+5+7+9 and sum of 2+4+6+8+0. What are you doing instead is sum of all even numbers smaller than 1234567890 and sum of odd numbers smaller than 1234567890.
Maybe consider instead of getting all numbers in string by cin >> digits read it from input by characters one by one.
Check this code it reads characters from input and spits them back.
#include<iostream>
using namespace std;
int main() {
cout << "Please enter a string comprised ONLY of digits:" << endl;
cout << endl;
char one;
while ( true ) {
cin >> one;
// here will come your part with deciding even / odd and counting instead of pritnting out.
cout << " " << one;
if ( cin.peek() == '\n' ) { break; }
}
return 0;
}
And now it's your turn to put it together.
Use std::getline to read all digits into a std::string:
std::cout << "Enter string of numbers: " << std::endl;
if (std::string numbers; std::getline(std::cin, numbers)) {
/* ... */
}
Note the use of conditional-if above from the upcoming C++1z standard.
Then, you could make use of std::pair to neatly accumulate the odds and evens like this:
std::pair odd_even{0, 0};
for (auto c : numbers) {
(c % 2 ? std::get<0>(odd_even) : std::get<1>(odd_even)) += c - '0';
}
Live example
This one logically should work
for(int i=0; i<digits.lenght; i++){
if(digits[i] % 2 == 0)
sumEven+=digits[i];
else
sumOdd+=digits[i];
}

logic error, need help can't figure out the looping logic

I am a beginner coder and I need a few ideas on how my code can output the right syntax.
If I input number < 25
Outputs and extra(s) ", " because it still runs through and sees that (amount_left > 0).
How would I make it so if there doesn't exist a quarter or dime it does not output the ", "?
#include <cstdio>
#include <iostream>
using namespace std;
void compute_coins(int coin_value, int& number, int& amount_left);
int main(){
int amount_left, number;
while(amount_left > 1 || amount_left < 99){
cout << "Enter number of cents (or zero to quit):" << endl;
cin >> amount_left;
if (amount_left == 0){
break;
}
else{
cout << amount_left << " cents can be given as ";
compute_coins(25, number, amount_left);
if (number == 1){
cout << "1 quarter";
}
else if (number > 0){
cout << number << " quarters";
}
if (amount_left > 0){
cout << ", ";
}
compute_coins(10, number, amount_left);
if (number == 1){
cout << "1 dime";
}
else if (number > 1){
cout << number << " dimes";
}
if (amount_left > 0){
cout << ", ";
}
compute_coins(1, number, amount_left);
if (number == 1){
cout << "1 penny";
}
else if (number > 1){
cout << number << " pennies";
}
std:: cout << ".";
}
cout << endl;
}
return 0;
}
void compute_coins(int coin_value, int& number, int& amount_left){
number = amount_left/coin_value;
amount_left = amount_left - (number * coin_value);
}
The expectation is that a period, and exactly one period must come after all the amounts get printed out.
Therefore, it makes no logical sense to write complicated code that tries to figure out whether it should print a period before the rest of the code, for all the remaining denominations, is done.
Just get rid of that code that prints all those periods, inside all of those awkward if/else statements.
At the very end of everything, simply execute
std::cout << ".";
No ifs, elses, or buts.
Simply focus on the problem of writing out the counts of all the denominations, correctly separated by commas. Forget about the trailing period. Just focus on formatting a comma-separated list of all possible denominations. Put the trailing period out of your mind.
Then, once you get all of that working, simply append
std::cout << ".";
at the end, and call it a day. This is a 100% guaranteed, or your money back, way to end up with exactly one period at the end of your output.

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.