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

Thread Starter

goutham1995

Joined Feb 18, 2018
104
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?
 

WBahn

Joined Mar 31, 2012
29,978
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?
 

WBahn

Joined Mar 31, 2012
29,978
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.
 

Thread Starter

goutham1995

Joined Feb 18, 2018
104
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.
 

WBahn

Joined Mar 31, 2012
29,978
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().
 

Thread Starter

goutham1995

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

  if (kbhit() != 0) {
    button=getch();
                    }
switch (button)
  {
    case 'q':
    Sleep(20);
    PlaySound( TEXT("C:\\Users\\Gumm\\Downloads\\real sound of notes\\ardha chapu.wav"),NULL,SND_SYNC );
    button=0;
    break;

    case 'w':
    Sleep(20);   
    PlaySound( TEXT("C:\\Users\\Gumm\\Downloads\\real sound of notes\\chapu"),NULL,SND_SYNC );
    button=0;
    break;

    case 'e':
       Sleep(20);
    PlaySound( TEXT("C:\\Users\\Gumm\\Downloads\\real sound of notes\\dheem"),NULL,SND_SYNC );
    button=0;
    break;

    case 'r':
    Sleep(20);
    PlaySound( TEXT("C:\\Users\\Gumm\\Downloads\\real sound of notes\\dhi"),NULL,SND_SYNC );
    button=0;
    break;

    case 't':
       Sleep(20);
    PlaySound( TEXT("C:\\Users\\Gumm\\Downloads\\real sound of notes\\num"),NULL,SND_SYNC );
    button=0;
    break;

    case 'y':
    Sleep(20);   
       PlaySound( TEXT("C:\\Users\\Gumm\\Downloads\\real sound of notes\\sampoorna chapu"),NULL,SND_SYNC );
       button=0;
    break;

    case 'u':
    Sleep(20);   
    PlaySound( TEXT("C:\\Users\\Gumm\\Downloads\\real sound of notes\\ta"),NULL,SND_SYNC );
    button=0;
    break;

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

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

John P

Joined Oct 14, 2008
2,025
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
29,978
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)
   {
      case 'q': fileName = "C:\\Users\\Gumm\\Downloads\\real sound of notes\\ardha chapu.wav"; break;
      case 'w': fileName = "C:\\Users\\Gumm\\Downloads\\real sound of notes\\chapu"; break;
      case 'e': fileName = "C:\\Users\\Gumm\\Downloads\\real sound of notes\\dheem"; break;
      case 'r': fileName = "C:\\Users\\Gumm\\Downloads\\real sound of notes\\dhi"; break;
      case 't': fileName = "C:\\Users\\Gumm\\Downloads\\real sound of notes\\num"; break;
      case 'y': fileName = "C:\\Users\\Gumm\\Downloads\\real sound of notes\\sampoorna chapu"; break;
      case 'u': fileName = "C:\\Users\\Gumm\\Downloads\\real sound of notes\\ta"; break;

      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_PATH "C:\\Users\\Gumm\\Downloads\\real sound of notes"
#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
1,047
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;
}
 

Thread Starter

goutham1995

Joined Feb 18, 2018
104
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)
   {
      case 'q': fileName = "C:\\Users\\Gumm\\Downloads\\real sound of notes\\ardha chapu.wav"; break;
      case 'w': fileName = "C:\\Users\\Gumm\\Downloads\\real sound of notes\\chapu"; break;
      case 'e': fileName = "C:\\Users\\Gumm\\Downloads\\real sound of notes\\dheem"; break;
      case 'r': fileName = "C:\\Users\\Gumm\\Downloads\\real sound of notes\\dhi"; break;
      case 't': fileName = "C:\\Users\\Gumm\\Downloads\\real sound of notes\\num"; break;
      case 'y': fileName = "C:\\Users\\Gumm\\Downloads\\real sound of notes\\sampoorna chapu"; break;
      case 'u': fileName = "C:\\Users\\Gumm\\Downloads\\real sound of notes\\ta"; break;

      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_PATH "C:\\Users\\Gumm\\Downloads\\real sound of notes"
#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
29,978
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.
 
Top