3

For beginner practice I'm trying to create a simple loop that accepts a single character from the user, prints that character to the console and keeps doing that until the user enters 'R'.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SimpleLoop
{
    class Program
    {
        static void Main(string[] args)
        {
            char cplayerSelection = 'R';

            while(cplayerSelection == 'R')
            {
                Console.WriteLine("Enter R, P, or S:");
            cplayerSelection = (char)Console.Read();
            Console.WriteLine(cplayerSelection);
            }
        }

    }
}

How ever no matter what the user enters it only loops once end then exits. What do I need to change to continue the loop?

pravprab
  • 2,301
  • 3
  • 26
  • 43
rsgmon
  • 1,892
  • 4
  • 23
  • 35

6 Answers6

5

I believe that it should be

while(cplayerSelection != 'R' || cplayerSelection != 'r')

You have to check for both the uppercase and lowercase letter since they do not have the same value.

Edit: Also change the cplayerSelection declaration to some other letter so the loop can actually be executed for the first time.

Also replace this line

cplayerSelection = (char)Console.Read();

with

cplayerSelection = Console.ReadKey().KeyChar;

Read the comment by Habib on this answer as to understand why.

liliumdev
  • 1,159
  • 4
  • 13
  • 25
  • 1
    The OP would **also need** `Console.ReadKey().KeyChar`, `Selman22` was right about it. But unfortunately he deleted the answer., Because after the first iteration it will receive the character for carriage return and terminate the loop after first iteration. – Habib Feb 12 '14 at 20:42
4

Try this one, inside of your while loop:

cplayerSelection = Console.ReadKey().KeyChar

That will only work if you type uppercase R

If you want to allow three letters then you can try:

var letters = new[] {'R', 'P', 'S'};
while (letters.Contains(cplayerSelection))
{
    Console.WriteLine("Enter R, P, or S:");
    cplayerSelection = Console.ReadKey().KeyChar;
    Console.WriteLine(cplayerSelection);
}

If you want to make a case-insensitive check simply add lower-case versions of these characters to the array.Or you can use this (suggested by @Habib):

while (letters.Any(r => r == char.ToUpper(cplayerSelection))) 
Selman Genç
  • 100,147
  • 13
  • 119
  • 184
  • 1
    +1, and you were right about `ReadKey().KeyChar` because otherwise the loop will exit on the 2nd iteration, – Habib Feb 12 '14 at 20:46
  • For case insensitive he could also use ToUpper during the test. while (letters.Contains(Char.ToUpper(cplayerSelection)) – tonyriddle Feb 12 '14 at 20:48
  • @tonyriddle yes but he/she should convert that `char` to `string` first.then use ToUpper and convert ToChar again because it is a char array.so ToUpper seems easy but it's painful.adding three extra character to the array is much easier – Selman Genç Feb 12 '14 at 20:49
  • for char insensitive comparison, the OP can use `while (letters.Any(r=> r == char.ToUpper(cplayerSelection)))` – Habib Feb 12 '14 at 20:52
  • @Selman22, there is [char.ToUpper](http://msdn.microsoft.com/en-us/library/system.char.toupper(v=vs.110).aspx) and safer [Char.ToUpperInvariant](http://msdn.microsoft.com/en-us/library/system.char.toupperinvariant(v=vs.110).aspx) – Habib Feb 12 '14 at 20:53
2

Console.Read only reads a single character. The next time you get in the loop, it reads the return character, as well. You have a couple of options, based on whether you want the user to have to hit enter or not.

If you want them to hit enter:

char cplayerSelection = 'R';

while (cplayerSelection == 'R')
{
    Console.WriteLine("Enter R, P, or S:");
    cplayerSelection = (Console.ReadLine())[0];
    Console.WriteLine(cplayerSelection);
}

If you don't want them to hit enter:

char cplayerSelection = 'R';

while (cplayerSelection == 'R')
{
    Console.WriteLine("Enter R, P, or S:");
    cplayerSelection = Console.ReadKey().KeyChar;
    Console.WriteLine(cplayerSelection);
}
Colin DeClue
  • 2,194
  • 3
  • 26
  • 47
2

As others have mentioned, you need to be wary of case sensitivity. You can do so by checking the input with both the upper and lower case of the char. Or you could convert the char to its upper/lower-case form and only compare to that.

Also, for programs that always execute at least once like yours, using do while is more appropriate. For example:

class Program
{
    static void Main()
    {
        char input;
        do
        {
            input = char.ToUpperInvariant(Console.ReadKey().KeyChar);
        } while (input != 'R');
    }
}
cubski
  • 3,218
  • 1
  • 31
  • 33
2

I think you are confused.

...loop that accepts a single character from the user, prints that character to the console and keeps doing that until the user enters a character other than 'R'.

The loop exit condition is any character that is not 'R'. In other words, the only input that continues the loop is 'R'.

no matter what the user enters it only loops once end then exits. What do I need to change to continue the loop?

This is what your first statement means.

What do I need to change to continue the loop?

Change the loop exit condition.

Sam Leach
  • 12,746
  • 9
  • 45
  • 73
1

According to this http://social.msdn.microsoft.com/Forums/vstudio/en-US/5c5b43e2-4536-4411-a34f-290eb8525b4d/why-does-consolereadline-not-wait-for-user-input?forum=csharpgeneral, Console.Read() will return a single character. The second time through the loop it will pull your 'return' character and exit your loop.

CodeMonkey
  • 1,795
  • 3
  • 16
  • 46