0

I'm new to C++, and I was doing the exercise found here:

http://www.learncpp.com/cpp-tutorial/32-arithmetic-operators/

I was doing quiz 2 which tells me co create a program that receives an integer from user, and prints true of that integer is even. So I created the following code:

#include "stdafx.h"
#include <iostream>

int getInteger()
{
    std::cout << "Insert an integer" << "\n";

    int8_t x;

    std::cin >> x;

    return x;
}

bool isEven(int8_t x)
{
    bool b;
    b = false;

    std::cout << x % 2 << "\n";

    if(x%2 == 0)
        {
            b = true;
        }

    return b;
}

void printResult(bool b)
{
    std::cout << std::boolalpha;
    std::cout << b << "\n";
}

int main()
{
    int8_t x;
    x = getInteger();

    bool b;
    b = isEven(x);

    printResult(b);

    return 0;
}

So, here is the problem. Unless I'm missing something, this should work, right? And it does, but only for integers that I input from 0 to 10. For some reason, if I input 10, or 12, it prints false, but it works fine with 2, 4, 6, and 8. Why is this happening?

  • did you try just an int instead of int8_t? – Khalil Khalaf Apr 20 '16 at 18:01
  • What is the reason you are using `int8_t` instead of `int`? – Slava Apr 20 '16 at 18:02
  • I used an int8_t because in that same tutorial website, different lesson, it is written that I should use it, since int8_t has a defined size and int can change from machine to machine. Is this wrong? Sorry, kind not very good at this! – Nelson Tethers Apr 20 '16 at 18:05
  • @NelsonTethers do not use that lessons then, they say BS – Slava Apr 20 '16 at 18:12
  • As a side note: `bool isEven(int8_t x) { return x % 2 == 0; }` does the same as your version, except for the printing but is a lot simpler. – stefaanv Apr 20 '16 at 19:57

4 Answers4

2

You have following code:

int8_t x;
std::cin >> x;

int8_t is just an alias for char for your platform and std::istream when it has type char as argument inputs one character, not integer. So solution would be to use type int and you should use it from the beginning as there is no reason at all to use int8_t in this case.

Slava
  • 43,454
  • 1
  • 47
  • 90
1

This function returns a different type than the one it supposed to return:

int getInteger()
{
    std::cout << "Insert an integer" << "\n";

    int8_t x;

    std::cin >> x;

    return x;
}

int should work fine instead of int8_t and see here why Documentation

Community
  • 1
  • 1
Khalil Khalaf
  • 9,259
  • 11
  • 62
  • 104
0

As you have it getInteger() takes character text translated input, not numbers., since int8_t actually expands to char

To fix that take a integer number in 1st place and cast to the int8_t type:

int getInteger()
{
    std::cout << "Insert an integer" << "\n";

    int x; // <<<<
    std::cin >> x;
    return x;
}

x = (int8_t)getInteger();
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
0

The reason that Alex on learncpp.com specifies that it is better to use fixed width integers is because the results of the program will not vary when it is compiled on different compilers. This is not the case for non-fixed-width integral types like char and int, since the size of the type will vary between compilers. As @Slava points out, int8_t is a fixed width integral type for char, so both are used with variables that will only store a single character in memory.

Use fixed width integers whenever the program may be used in a different compiler or machine and it is important that the results will be compiler- and platform-independent. Because the program is asking for user input for any integer, to use a fixed width integer, it would be best to use int32_t. int8_t and 'char' would be suitable for getting digits (i.e. 0–9). int16_t is suitable for integers between -2^16/2 (which equals -2^15) and 2^15-1 (i.e. between -32 768 and 32 767). 'int32_t' is suitable for integers between -2^31 and 2^31-1 (i.e. between -2 147 483 648 and 2 147 483 647).

As Alex explains later in 5.10 — std::cin, extraction, and dealing with invalid text input, it is important to handle all possible invalid user inputs.

Here is some updated code that will work, handle invalid user inputs, and loop to ask the user if they want to check whether another number is even or odd, and so do:

// StackOverflow C++ Even or Odd number program.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream> // for cin and cout
//include <cmath> // pow is no longer used and is commented out below.
#include <cstdint> // std::int32_t

// I changed the variable output for the function to int32_t, since that is the type being returned.
std::int32_t getInteger()
{
 /* If you don't understand some parts, like do-while loops and
 handling invalid user input, come back to it after learning it,
 and just focus on what you can understand.
 */

 // Use int32_t since the user input could potentially be a very large number.
 std::int32_t x{ 0 };
 bool notInt32t = 1;
 bool cinFail{1};
 do
 {
  // Don't use an '/n' character when getting user input, it makes more sense to get it on the same line as the prompt.
  std::cout << "Enter an integer: ";

  std::cin >> x;

  cinFail = std::cin.fail();

  if (cinFail)
  {
   std::cin.clear();
   std::cin.ignore(32767, '\n');
   std::cout << "Oops, that input is invalid. This may be because you entered a number larger \n";
   std::cout << "than 2147483647 (which equals 2^31-1), or less than -2147483648 (which equals -2^31); \n";
   std::cout << "or you did not enter an integer only. Please try again.\n";
  }
  // remove any extraneous input, which would otherwise be left in the buffer, causing unexpected results.
  else
   std::cin.ignore(32767,'\n'); 

  /*Commented out because this will not work, it will fail to extract. Left in the code for education purposes.
  notInt32t = ((x > (pow(2.0, 31.0) - 1)) || (x < -pow(2.0, 31.0)) || !(x % 1 == 0));
  if (notInt32t)
   std::cout << "Oops, you entered incorrectly!\n";
  */
 } while (cinFail);

 return x;
}

bool isEven(std::int32_t x)
{
 bool isEven;

 isEven = (x % 2 == 0) ?(true):(false);

 return isEven;
}

/* I have commented this out and rewrote it, as it is ambiguous.
void printResult(bool b)
{
 std::cout << std::boolalpha;
 std::cout << b << "\n";
}*/

void printIsEven()
{
 auto x = getInteger();

 if (isEven(x))
  std::cout << x << " is an even integer.\n";
 else
  std::cout << x << " is an odd integer.\n";
}
void printIsEvenLoop()
{
 std::int8_t yOrN{};
 bool isLoop{ true };
 bool cinFail{ false };
 bool isYOrN{ false };
 while (isLoop)
 {
  do
  {
   std::cout << "Would you like to check whether another integer is even or odd?\n";
   std::cout << "Enter y or n (yes or no): ";
   std::cin >> yOrN;

   cinFail = std::cin.fail();

   if (cinFail)
   {
    std::cin.clear();
    std::cin.ignore(32767, '\n');
    std::cout << "Oops, that input is invalid! Please try again.\n";
   }
   // remove any extraneous input, which would otherwise be left in the buffer, causing unexpected results.
   else
    std::cin.ignore(32767, '\n');

   isYOrN = ((yOrN == 'y' || yOrN == 'n'));
   if (!isYOrN)
    std::cout << "Oops, you entered incorrectly! Please try again.\n";

  } while (cinFail || !isYOrN);

  if (yOrN == 'y')
  {
   isLoop = true;
   printIsEven();
  }
  else
   isLoop = false;
 }
 
}
int main()
{
 printIsEven();
 
 printIsEvenLoop();

 return 0;
}
James Ray
  • 424
  • 3
  • 15