# How to 'enter' as soon as you press a key?

#### goutham1995

Joined Feb 18, 2018
94
I have a program where a certain sound is played corresponding to a key pressed on the keyboard. But every time I press a key, I have to press 'enter' for the sound to be played. What I actually want to do is to press the key without having to press enter and a sound should be played. How can I do this?

#### MrChips

Joined Oct 2, 2009
20,277
That's simple. Rewrite the program to respond to a single character instead of waiting for a line entered.

#### WBahn

Joined Mar 31, 2012
25,270
I have a program where a certain sound is played corresponding to a key pressed on the keyboard. But every time I press a key, I have to press 'enter' for the sound to be played. What I actually want to do is to press the key without having to press enter and a sound should be played. How can I do this?
What is this program written in? C? Java? Raptor? Excel? COBAL? Turtle? Python? Jack? What?

#### goutham1995

Joined Feb 18, 2018
94
What is this program written in? C? Java? Raptor? Excel? COBAL? Turtle? Python? Jack? What?
C++

#### goutham1995

Joined Feb 18, 2018
94

#### WBahn

Joined Mar 31, 2012
25,270
Call the getch() function.
The getch() is still going to require that the Enter key be pressed. The standard C/C++ libraries only support buffered keyboard data and the data is transferred into the buffer once the Enter key is pressed. Most development environments have non-portable ways of doing it. A common one that (I think) was made available with the conio.h library from Borland was kbhit() and it was used by several others (Borland may have copied it from someone before them, too). MSVC++ has, I believe, an _getch() function in their conio.h library that should work. There are also commands in the Win32 API specifically intended for this task.

#### goutham1995

Joined Feb 18, 2018
94
The getch() is still going to require that the Enter key be pressed. The standard C/C++ libraries only support buffered keyboard data and the data is transferred into the buffer once the Enter key is pressed. Most development environments have non-portable ways of doing it. A common one that (I think) was made available with the conio.h library from Borland was kbhit() and it was used by several others (Borland may have copied it from someone before them, too). MSVC++ has, I believe, an _getch() function in their conio.h library that should work. There are also commands in the Win32 API specifically intended for this task.
I actually made it work. In conio.h header file, there is a function called kbhit which detects if keyboard is hit. If it is, then I use getch and store it in a variable.

#### MrSoftware

Joined Oct 29, 2013
1,676
Some implementations of getch() will return immediately when a key is pressed, without waiting for enter.

#### WBahn

Joined Mar 31, 2012
25,270
Some implementations of getch() will return immediately when a key is pressed, without waiting for enter.
Hmm. That's news to me. Good to know -- and a bit disturbing since it makes that standard library function nonportable.

#### MrSoftware

Joined Oct 29, 2013
1,676
I could be mistaken, but I do not believe that getch is part of the standard, which is part of the problem.

#### WBahn

Joined Mar 31, 2012
25,270
I could be mistaken, but I do not believe that getch is part of the standard, which is part of the problem.
I thought it was -- time to go take a look. I'm very possibly thinking of one of the other similar functions.

Ah. You are correct. I was thinking of getchar().

#### goutham1995

Joined Feb 18, 2018
94
Code:
 while(1)
{

if (kbhit() != 0) {
button=getch();
}
switch (button)
{
case 'q':
Sleep(20);
button=0;
break;

case 'w':
Sleep(20);
button=0;
break;

case 'e':
Sleep(20);
button=0;
break;

case 'r':
Sleep(20);
button=0;
break;

case 't':
Sleep(20);
button=0;
break;

case 'y':
Sleep(20);
button=0;
break;

case 'u':
Sleep(20);
button=0;
break;

//case 'q':
//exit(0);

default:
printf("No sound");
}
}
This is how I made it work

#### John P

Joined Oct 14, 2008
1,796
When I have to write code for the PC, I do it in C for Windows, and in that environment hitting a key sends a WM_KEYDOWN message to the process. It's pretty easy to deal with.

#### WBahn

Joined Mar 31, 2012
25,270
A couple things you might consider. It's generally a good idea to not repeat code that doesn't need to be repeated. Also, try to make switch() statements as direct and to the point as possible -- they tend to get awfully long as it it.

Except for the default case, all of your switch cases do the same thing except for the filename. So have the switch statement deal only with the filename. This is particularly useful if you have no intention of having different times for the Sleep function.

This can make the code more readable and maintainable.

Code:
#define FOREVER (1)
#define SLEEP_TIME (20)

while(FOREVER)
{
button = kbhit()? getch() : 0;

switch (button)
{

default: fileName = NULL;
}

if (fileName)
{
Sleep(SLEEP_TIME);
PlaySound(TEXT(fileName), NULL, SND_SYNC);
}
else
printf("No sound");
}
See how this separates the code organization into conceptual blocks? You have the first block that deals with the user input. The second block deals only with mapping that input to the appropriate filename. The third block handles the execution details. If you were to decide to use something other than PlaySound() or to change the second or third parameter, you now only have to update the code in one place, instead of making sure that you updated it everywhere throughout the switch statement.

There are other approaches, too, such as putting the basic filenames in an array and using the switch statement to choose which element, then using a function or possibly a macro to build the fill path name from the base name. So something like:

#define WAV_EXT "ext"

Then in the switch statement your cases would look like:

case 'q': fileName = "ardha chapu";

and then in the PlaySound you would have:

PlaySound(TEXT(buildFileSpec(WAV_PATH, fileName, WAV_EXT)), NULL, SND_SYNC);

where the buildFileSpec() function is a reusable function that returns a pointer to a string that has the path, file name, and extension glued together with the appropriate delimiters.

That would be particularly useful if you didn't have just one filename that had the .wav extension and the others without it. Is there a reason for that? If not and that was an oversight, then doing it the way I'm proposing would have made that mistake much harder to make.

Note that I've just modified the code above, I haven't tried to compile it or run it, so it's very possible that I've made a typo or oversight that didn't get caught.

#### Picbuster

Joined Dec 2, 2013
990
I could be mistaken, but I do not believe that getch is part of the standard, which is part of the problem.
You are correct for Microchip I don't know the other compilers
Code below

Picbuster

getch() {
/* retrieve one byte */
while(!RC1IF) /* set when register is not empty */
continue;
return RCREG1;
}

#### goutham1995

Joined Feb 18, 2018
94
A couple things you might consider. It's generally a good idea to not repeat code that doesn't need to be repeated. Also, try to make switch() statements as direct and to the point as possible -- they tend to get awfully long as it it.

Except for the default case, all of your switch cases do the same thing except for the filename. So have the switch statement deal only with the filename. This is particularly useful if you have no intention of having different times for the Sleep function.

This can make the code more readable and maintainable.

Code:
#define FOREVER (1)
#define SLEEP_TIME (20)

while(FOREVER)
{
button = kbhit()? getch() : 0;

switch (button)
{

default: fileName = NULL;
}

if (fileName)
{
Sleep(SLEEP_TIME);
PlaySound(TEXT(fileName), NULL, SND_SYNC);
}
else
printf("No sound");
}
See how this separates the code organization into conceptual blocks? You have the first block that deals with the user input. The second block deals only with mapping that input to the appropriate filename. The third block handles the execution details. If you were to decide to use something other than PlaySound() or to change the second or third parameter, you now only have to update the code in one place, instead of making sure that you updated it everywhere throughout the switch statement.

There are other approaches, too, such as putting the basic filenames in an array and using the switch statement to choose which element, then using a function or possibly a macro to build the fill path name from the base name. So something like:

#define WAV_EXT "ext"

Then in the switch statement your cases would look like:

case 'q': fileName = "ardha chapu";

and then in the PlaySound you would have:

PlaySound(TEXT(buildFileSpec(WAV_PATH, fileName, WAV_EXT)), NULL, SND_SYNC);

where the buildFileSpec() function is a reusable function that returns a pointer to a string that has the path, file name, and extension glued together with the appropriate delimiters.

That would be particularly useful if you didn't have just one filename that had the .wav extension and the others without it. Is there a reason for that? If not and that was an oversight, then doing it the way I'm proposing would have made that mistake much harder to make.

Note that I've just modified the code above, I haven't tried to compile it or run it, so it's very possible that I've made a typo or oversight that didn't get caught.
Thanks for these tips.

#### WBahn

Joined Mar 31, 2012
25,270
Thanks for these tips.
No problem. As you code, always be asking yourself how you can make your code more modular, readable, and maintainable. At some point, many of these techniques will just become how you naturally code, or at least they will suggest themselves very early in the coding process and you will find yourself refactoring the code to craft it into a comfortable form.