Use scanf("%d",&rows) instead of scanf("%s",input)
This allows you to get the direct integer value from stdin without the need for conversion to int.
If the user enters a string containing non-digital characters, you must clear your stdin before the next scanf("%d",&rows) .
your code might look like this:
#include <stdio.h> #include <stdlib.h> int clean_stdin() { while (getchar()!='\n'); return 1; } int main(void) { int rows =0; char c; do { printf("\nEnter an integer from 1 to 23: "); } while (((scanf("%d%c", &rows, &c)!=2 || c!='\n') && clean_stdin()) || rows<1 || rows>23); return 0; }
Explanation
1)
scanf("%d%c", &rows, &c)
This means that an integer is entered from the user and a non-digital character is next to him.
Example1: If the user enters aaddk and then ENTER , scanf will return 0. Nothing is closed
Example2: If the user enters 45 and then ENTER , scanf will return 2 (2 items are closed). Here %d is capting 45 and %c is capting \n
Example 3: If the user enters 45aaadd and then ENTER , scanf will return 2 (2 items are closed). Here %d is capting 45 and %c is capting a
2)
(scanf("%d%c", &rows, &c)!=2 || c!='\n')
In Example 1: this is a TRUE condition because scanf return 0 ( !=2 )
In Example 2: this is a FALSE condition because scanf return 2 and c == '\n'
In Example 3: this is a TRUE condition because scanf return 2 and c == 'a' (!='\n')
3)
((scanf("%d%c", &rows, &c)!=2 || c!='\n') && clean_stdin())
clean_stdin() always TRUE because the function always returns 1
In example 1: (scanf("%d%c", &rows, &c)!=2 || c!='\n') - TRUE , so the condition after && must be checked to execute clean_stdin() , and that's it condition TRUE
In Example 2: (scanf("%d%c", &rows, &c)!=2 || c!='\n') is FALSE , so the condition after && will not be checked (since its result will be equal to the whole FALSE ), therefore clean_stdin() will not be executed, and the whole condition is FALSE
In example 3: (scanf("%d%c", &rows, &c)!=2 || c!='\n') - TRUE , so the condition after && must be checked to execute clean_stdin() and the whole condition TRUE
So, you may notice that clean_stdin() will only execute if the user enters a string containing a non-digital character.
And this condition ((scanf("%d%c", &rows, &c)!=2 || c!='\n') && clean_stdin()) will return FALSE only if the user enters integer and nothing else
And if the condition ((scanf("%d%c", &rows, &c)!=2 || c!='\n') && clean_stdin()) is FALSE and integer is between and 1 and 23 , then the while will break otherwise, while will continue