isDigit error

My isDigit automatically detects that an integer is a letter.
I want to make it where it works perfectly and prompts an error message when a letter is inputted and not if i enter an integer.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
//**************************************************
//*This program is designed to print out a calendar*
//*for the year desired by the user and determine  *
//*if the year is a loop year and modify a certain *
//*month based on that criteria, it also shows     *
//*the process of function decomposition in depth  *
//**************************************************

#include<iostream>
#include<cstdlib>
#include<iomanip>   //Used for setw
#include <string>

using namespace std;

int firstWeekDay(/* in */int);  //Function prototype with one value parameter
void getCalendarInput(/* inout */ int&);    //Function prototype with one reference parameter
void yearlyCalendar(/* in */ int);  //Function prototype with one value parameter
bool isLeapYear (/*in*/int); //Function prototype with on value parameter

int main()
{
    int year, month, day, totalDaysinMonth, weekDay = 0, startingDay;   //Place holders for different situations as local variables

    //Array used to store month names more convenient than an if statement that matches number to name
    char * monthNames[] ={"       January", "       February", "        March", "       April", "        May", "        June", "        July", "       August", "      September", "      October", "      November", "      December"};
    int monthDays[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; //1-D Array that hold the total amount of days for each month

    getCalendarInput(year); //Function call with one argument

    yearlyCalendar(year);   //Function call with one argument

    return 0;
}

//List function definitions below

//*************** Function definition ***************
//*This function prompts the user to input their    *
//*desired year they would want a calendar displayed*
//*for and it also includes input validation so the *
//*values entered are unique and not random         *
//***************************************************
void getCalendarInput(/* inout */ int& year)
//Pre:
//The user is prompted with a menu to input the year
//the int value of year is then stored into cin and
//a whole list of months for the year with dates will
//pop up but if the user enters a letter along with
//the integers then isDigit() will prevent it from
//being read.
//Post:
//The value of year is then stored into cin and blocked
//if it has a letter and works as expected.
{
    //Prompts user to enter a year of their choice
    cout << "What year do you want the calendar for? ";
    cin >> year;

    //Used to only read integers and no ASCII values
    if(year != isdigit(year))
    {
        //Fail state validation inside of validation
        while(year < 0 || !cin)
        cin.clear();
        cin.ignore(200 , '\n');
        cout << "non digit entered" << endl;
        cout << "What year do you want the calendar for? ";
        cin >> year;
    }
}

//*********** Function Definition ***************
//*This function is responsible for calculating *
//*the first day of each week in an accurate way*
//***********************************************
int firstWeekDay(/* in */ int year)
//Pre:
//We have the int variables of startday and num's
//so we can pass the value of the year through and
//calculate how the first day of the week should be.
//Post:
//After integrating this formula into the process of
//printing out a whole complete month the first day
//is accurately represented.
{
    //Local variables to have values passed through
    int startday;
    int num1, num2, num3;
    num1 = (year - 1)/ 4;
    num2 = (year - 1)/ 100;
    num3 = (year - 1)/ 400;
    startday = (year + num1 - num2 + num3) %7;
    return startday;    //returns the first day
}


//*************** Function Definition ***************
//*This function is responsible for outputting the  *
//*correct months along with dates in a neat        *
//*formatted manner while passing data through with *
//*the parameters                                   *
//***************************************************
void yearlyCalendar(/* in */ int year)
//Pre:
//This program uses the following local variables to pass data
//within the function and give back the right end day if the year
//is considered a leap year and if it is not then default it
//if it does not meet the criteria while also displaying the months
//and weeks in a spacious manner
//Post:
//The function does as expected and prints out the months
//and weeks with the correct end date considering if its a leap or non
//leap year.
{
    //Local variables to store and pass values
    int month, day, totalDaysinMonth, weekDay = 0, startingDay;
    //Arrays to hold month names and total days of each month
    char * monthNames[] ={"       January", "       February", "        March", "       April", "        May", "        June", "        July", "       August", "      September", "      October", "      November", "      December"};
    int monthDays[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    //Validation to determine if it is a leap year or not
    if(((year%4==0) && (year%100 !=0))||(year%400==0))
    {
         monthDays[1] = 29; //if it is a leap year it will return 29
    }
    else
    {
         monthDays[1] = 28; //if it is not it will return 28
    }

    startingDay = firstWeekDay(year);   //used to determine first day of month

    //for loop designed to display the months and weeks in a neat fashion
    for(month = 0; month < 12; month++)
    {
        cout << endl;
        cout << setw(10) << right << monthNames[month]<< "\n";  //White spaces for month names
        cout << " S  M  T  W  T  F  S\n";   //Manual white spaces for days of week
        cout << "_____________________\n";

        //White spaces of week days using a for loop
        for(weekDay = 0; weekDay < startingDay; weekDay++)
            cout <<"   ";

        totalDaysinMonth = monthDays[month];    //Used to display total days in each month

        //For loop used to generate the integers of the week
        for(day = 1; day <= totalDaysinMonth; day++)
        {
            cout << setw(3)<< day;  //white spaces for integers

            //if statement to detect end of week and then starting a new line
            if(++weekDay > 6)
            {
                cout << "\n";
                weekDay = 0;    //resets counter
            }
            startingDay = weekDay;  //Gets it ready for following month
        }
        cout << endl;   //Ending with a space for next month
    }
}

//function definitions with function related documentation

/*function IsLeapYear returns true if year is a leap year and
/ false otherwise.*/
bool isLeapYear (/*in*/int year)
//pre:value parameter has an assigned value
//post: //Is year not divisible by 4? If so, can't be a leap year
        //Is year not a multiple of 100? If so, is a leap year
        //Is year not a multiple of 400? If so, then is not a leap year
        //returns a truth value
{
    return   ((year%4==0) && (year%100 !=0))||(year%400==0)  ;
}
Hello Depressed,

You keep missing the fundamental problem.

"year" is defined as an "int" so "cin >> year" is expecting you to enter a number. Anything that starts with something that is not a number will cause "cin" to fail and become unusable the rest of the program if not corrected.

The formatted input of "cin >> year" will extract from the input buffer into the variable what it can until it finds a non numeric character, white space or a new line whichever comes first.

Given your earlier example "202o" the "202" will be stored in "year" and it will stop at the "o" leaving this in the input buffer for later problems.

For the "isdigit()". First you missed the header file <cctype> which defines this function. From the reference page http://www.cplusplus.com/reference/cctype/isdigit/ the first line says Check if character is decimal digit.

Since "year" is already a number, i.i., one or more digits, this has no effect if(year != isdigit(year)). Now if you had defined "year" as a "std::string" you could check each element, (character), of the string then convert the "string" to an "int".

As it is what you have may be a nice thought, but does not work.

I get the impression that you are trying to over think the problem and making it more difficult than it needs to be.

Andy
how would i go about it? I try to alter it but I run into conflicts
Hello Depressed,

This is not complete and only slightly tested, but does make a good start.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
void getCalendarInput(/* inout */ int& year)
//Pre:
//The user is prompted with a menu to input the year
//the int value of year is then stored into cin and
//a whole list of months for the year with dates will
//pop up but if the user enters a letter along with
//the integers then isDigit() will prevent it from
//being read.
//Post:
//The value of year is then stored into cin and blocked
//if it has a letter and works as expected.
{
	bool isDigit{ true };
	std::string sYear;

	do
	{
		//Prompts user to enter a year of their choice
		cout << "What year do you want the calendar for? ";
		cin >> sYear;

		for (int index = 0; index < 4; index++)
		{
			if (!isdigit(sYear[index]))
				isDigit = false;
		}

		if (isDigit)
		{
			year = stoi(sYear);

			return;
		}

		// <--- Place error messag here. Check for range of year.

	} while (!isDigit);

	//Used to only read integers and no ASCII values
	//if (year != isdigit(year))
	//{
	//	//Fail state validation inside of validation
	//	while (year < 0 || !cin)
	//		cin.clear();
	//	cin.ignore(200, '\n');
	//	cout << "non digit entered" << endl;
	//	cout << "What year do you want the calendar for? ";
	//	cin >> year;
	//}
}


Andy
See:
https://stackoverflow.com/questions/10828937/how-to-make-cin-take-only-numbers

@Depressed - experience shows that it is often (almost always) better practice to isolate the problem and write code for that part rather than wading though an ever growing project.

Once the immediate problem is solved incorporate that code back into the main project.

From the SO thread this is close to what you need in an isolated form:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<iostream>
#include<limits>
using namespace std;
int main()
{

    cout << "Enter an int: ";
    int x = 0;
    while(!(cin >> x)){
        cin.clear();
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
        cout << "Invalid input.  Try again: ";
    }
    cout << "You entered: " << x << endl;        
}
> I want to make it where it works perfectly and prompts an error message
> when a letter is inputted and not if i enter an integer.

Consider writing a (reusable) function for this.

For instance, with a check for valid range added:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>

// invariant: minval <= maxval
int get_int( int minval, int maxval, const char* prompt = "? " )
{
    std::cout << prompt << " [" << minval << '-' << maxval << "]: " ;

    int value ;
    if( std::cin >> value ) // if the user entered an integer
    {
        // return it if it is within the valid range
        if( value >= minval && value <= maxval ) return value ;

        else std::cout << "error: the value " << value << " is out of range\n" ;
    }

    else // the user did not enter an integer
    {
        std::cout << "error: non-integer input\n" ;

        // https://en.cppreference.com/w/cpp/io/basic_ios/clear#Example
        std::cin.clear() ; // clear the failed state of std::cin

        // https://en.cppreference.com/w/cpp/io/basic_istream/ignore
        std::cin.ignore( 1000, '\n' ) ; // extract and discard the bad input
    }

    // if we reach here, the input failed (return was not executed). so try again
    return get_int( minval, maxval, prompt ) ;
}

int main()
{
    const int year = get_int( 1900, 2100, "year" ) ;
    const int month = get_int( 1, 12, "month" ) ;
    std::cout << "year: " << year << "  month: " << month << '\n' ;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>
#include <sstream>
#include <string>
#include <complex>
using namespace std;

//==========================================================

template<typename T> T getNumber( const string &prompt )   // Input of signed numerical type
{                                                          
   T value;
   string line;
   char c;

   cout << prompt;
   getline( cin, line );

   stringstream ss( line );
   if ( ss >> value && !( ss >> c ) )   // If valid input ... and NOTHING ELSE (other than spaces)
   {
      return value;          
   }
   else
   {
      cout << "Invalid input.\n";
      return getNumber<T>( prompt );
   }
}

//==========================================================

int main()
{
   int    i = getNumber<int>   ( "Enter an int: "   );   cout << "You entered " << i << "\n\n";
   double d = getNumber<double>( "Enter a double: " );   cout << "You entered " << d << "\n\n";
   complex<double> z = getNumber<complex<double>>( "Enter a complex number as (x,y): ");
                                                         cout << "You entered " << z << "\n\n";
}


Enter an int: 123e4
Invalid input.
Enter an int: 123
You entered 123

Enter a double: 123e4
You entered 1.23e+06

Enter a complex number as (x,y): 1 2
Invalid input.
Enter a complex number as (x,y): (1,2)
You entered (1,2)
Last edited on
Out of the 3 the Flying Nun wins - who says there was any competition here?
Anyway templating does make it better/more flexible and creates the question of what constitutes a complex number comparator. Maybe a case for polymorphism.
Topic archived. No new replies allowed.