-3

Task: Write a char do/while loop, where the program will end if the letter is not in capital:

Solution:

Char input;

do{
    scanf("%c", &input);

} while (input <'a' || 'z'< input);

So my program says: "do this, while the input is either a or z". Why does it control all letters from a to z and how come my program ends if it's a little char instead of a capital?

I'm new to C, and I can't find an explanation anywhere, thanks in advance.

tkausl
  • 13,686
  • 2
  • 33
  • 50
  • Are you sure that you have `'z'< input`? shouldn't it be `'z'> input`? – HamZa Jun 10 '17 at 13:24
  • 4
    `input < 'a' || 'z' < input` does not equate to "the input is either a or z". – Peter Jun 10 '17 at 13:25
  • 2
    [Please read this](https://stackoverflow.com/questions/5240789/scanf-leaves-the-new-line-char-in-buffer). – Weather Vane Jun 10 '17 at 13:25
  • To understand the "trick", you need to look at the [ascii table](http://www.asciitable.com). You're reading in a character, which is an integer (number) in memory. – HamZa Jun 10 '17 at 13:27
  • 2
    `Char` is not a standard type. Do you have a `typedef`? Notice you are required to provide a [mcve] for such questions. – too honest for this site Jun 10 '17 at 13:33
  • 3
    Hint: Have a look into `ctype.h`. Or just do `man isupper`. – alk Jun 10 '17 at 13:36
  • 1
    You would need `while (input == 'a' || input == 'z')`instead of testing the whole range. – Weather Vane Jun 10 '17 at 13:38
  • Have a clear goal. –  Jun 10 '17 at 13:42
  • You need to test the result of `scanf()` in case you get EOF — your program won't stop if it does encounter EOF. Using a `do while` loop isn't a particularly good idea for this, but it seems to be part of the assignment, so we can't blame you for that. Just note that it would be better to use a `while` loop instead. – Jonathan Leffler Jun 10 '17 at 13:57

2 Answers2

1

the problem is this statement:

while (input <'a' || 'z'< input);

as this is looking for anything not lower case letters and not taking into account the whole ascii (single char) table of possibilities.

And the criteria is for upper case which those letter are lower case.

you could use:

while ('A' <= input && input <= 'Z')

however, best to use the functionality in the header file: ctype.h because not all systems use the ASCII character set. (IBM mainframe for instance, uses EBCDIC rather than ASCII, where the alphabet is not contiguous )

Remember that the 'enter' key is not upper case, (and not allowed for in the code)

the following proposed code:

  1. cleanly compiles
  2. performs the desired function
  3. properly checks for errors
  4. uses the facilities defined in the header file ctype.h

and now the proposed code

#include <stdio.h>   // scanf(), perror()
#include <stdlib.h>  // exit(), EXIT_FAILURE
#include <ctype.h>   // isupper()


int main( void )
{
    // 'char' is all lower case: 
    // so this statement: Char input;
    // does not compile, suggest:
    char input;

    do
    {
        int scanfStatus = scanf("%c", &input);
        // always check the returned value (not the parameter value)
        if( 1 != scanfStatus )
        {
            perror( "scanf failed" );
            exit( EXIT_FAILURE );
        }
    } while ( isupper( input ) );
} // end function: main
user3629249
  • 16,402
  • 1
  • 16
  • 17
  • 1
    The solution is the facit in my book. And it accepts only capital letters with this code in visual studio. I just don't understand why. – GrittyBowman Jun 10 '17 at 18:47
  • @user3629249, I can now comment your post, since I earned a bit of rep. Your code will not compile "cleanly" with a `gcc -Wall` since you do not end it with `return 0;`. An edit I suggested 4 days ago was rejected (first accepted by a reviewer, and later rejected by you). Warnings in compilation are not a clean compilation, IMHO. Your answer otherwise contains good code and accurate explanations, but I am not sure it does answer the OP's question. He did not ask for his code to be fixed. He said that being new to C, he needed an explanation as to why his code was behaving the way he described. – Tardis Jun 14 '17 at 14:39
  • @Tardis, Regarding the `return 0;` Modern C compilers do not require that statement if the only returned value is always 0. All of the code that I post cleanly compiles with `gcc -ggdb -c -Wall -Wextra -pedantic -Wconversion -std=gnu11` I just ran it through the compiler again. No warnings, nothing. I do agree that I may have not clearly explained why his code fails. – user3629249 Jun 15 '17 at 21:26
  • Re: `return 0;`. Today's Debian uses GCC v4.9.2, which with `gcc -Wall`, says `warning: control reaches end of non-void function [-Wreturn-type]`. That is because GCC 4 defaults to `-std=gnu90` (c90 with GNU extensions). Ubuntu's stock GCC is v4, so is under Windows Codeblocks MinGW's, etc. GCC 5 changes its default to `-std=gnu99`, but most people trying your code in 2017 with GCC won't be using that, or specifying a `-std=` option. When posting code I prefer to do it in the most portable manner (c90 without GNU extensions), especially if I claim that my code "cleanly compiles" :-) – Tardis Jun 16 '17 at 09:08
  • Re: the OP's code and question. The OP's question is unclear, and his code _imperfect_, but his code does not _fail_ in the sense it does exit the loop after the user presses a key with a lowercase letter (and presses enter), and indeed he was not complaining that it was failing (he did not even know his code was _imperfect_). He just didn't understand what the while test was doing or how it was working. – Tardis Jun 16 '17 at 09:51
  • Re: your code. Your code does is far much better written than OP's. I would have written a similar code (adding `return 0;` ;-), possibly also setting the locale since not all languages have letters limited to the default C locale (and that's another important benefit of using `isupper()` or `islower()` worth mentioning), and testing instead `while (!islower(input));` so as to replicate the functionality of his code, i.e.: exiting if a lowercase char was entered (and not looping as long as upcase char were entered), just as the "Task" he quoted was saying. But the OP did not ask for that :-) – Tardis Jun 16 '17 at 10:02
0

Your question is:

Why does it control all letters from a to z and how come my program ends if it's a little char instead of a capital?

The answer is, because of the while test, which tests whether input <'a' or 'z'< input.

Here is some background information that will help you understand why this happens.

In your program, input is a char, and, according to the C standard, the char type is an integral type. This means that 'a' (C's way to designate a char literal) is, in fact, a number, and thus, it can be compared with comparison operators such as < or > to other (integral) numbers or other char (here, the content of input).

Now, what is the actual integral value of a char? While the integral values of the character set are implementation-defined, in general, C compilers (including Visual Studio's) will use the ASCII Character Codes.

So:

  • 'a' in your code, refers to the integral value of ASCII code for the char 'a', which is 97,
  • and 'z' in your code refers to the integral value of ASCII code for the char 'z', which is 122

As you can see also from the ASCII table (ASCII Character Codes Chart 1 from MSDN), the alphabet a-z has consecutive code numbers ('a' is 97, 'b' is 98, etc.), and the lowercase alphabet is effectively an ASCII code from 97 to 122.

So, in your code, the test input <'a' or 'z'< input is equivalent to input < 96 or 122 < input, and this will be true when the entered char has any ASCII value outside the range of 96 - 122, meaning, any char that is entered which is not in the range of ASCII codes for lowercase letters from 'a' to 'z' will result in the while test being true, and repeating the scanf().

Finally, as noted by other commentators or contributors, the right type is char, not Char since C is case-sensitive.

Tardis
  • 465
  • 2
  • 10