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

Discussion in 'Programmer's Corner' started by goutham1995, May 29, 2018.

  1. goutham1995

    Thread Starter Member

    Feb 18, 2018
    80
    2
    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?
     
  2. MrChips

    Moderator

    Oct 2, 2009
    16,874
    5,182
    That's simple. Rewrite the program to respond to a single character instead of waiting for a line entered.
     
  3. WBahn

    Moderator

    Mar 31, 2012
    22,986
    6,883
    What is this program written in? C? Java? Raptor? Excel? COBAL? Turtle? Python? Jack? What?
     
  4. goutham1995

    Thread Starter Member

    Feb 18, 2018
    80
    2
    C++
     
  5. MrChips

    Moderator

    Oct 2, 2009
    16,874
    5,182
    Call the getch() function.
     
    MrSoftware and goutham1995 like this.
  6. goutham1995

    Thread Starter Member

    Feb 18, 2018
    80
    2
    thanks
     
  7. WBahn

    Moderator

    Mar 31, 2012
    22,986
    6,883
    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.
     
    MrSoftware likes this.
  8. goutham1995

    Thread Starter Member

    Feb 18, 2018
    80
    2
    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.
     
  9. MrSoftware

    Well-Known Member

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

    Moderator

    Mar 31, 2012
    22,986
    6,883
    Hmm. That's news to me. Good to know -- and a bit disturbing since it makes that standard library function nonportable.
     
  11. MrSoftware

    Well-Known Member

    Oct 29, 2013
    1,054
    296
    I could be mistaken, but I do not believe that getch is part of the standard, which is part of the problem. ;)
     
  12. WBahn

    Moderator

    Mar 31, 2012
    22,986
    6,883
    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().
     
  13. goutham1995

    Thread Starter Member

    Feb 18, 2018
    80
    2
    Code (Text):
    1.  while(1)
    2. {
    3.  
    4.   if (kbhit() != 0) {
    5.     button=getch();
    6.                     }
    7. switch (button)
    8.   {
    9.     case 'q':
    10.     Sleep(20);
    11.     PlaySound( TEXT("C:\\Users\\Gumm\\Downloads\\real sound of notes\\ardha chapu.wav"),NULL,SND_SYNC );
    12.     button=0;
    13.     break;
    14.  
    15.     case 'w':
    16.     Sleep(20);  
    17.     PlaySound( TEXT("C:\\Users\\Gumm\\Downloads\\real sound of notes\\chapu"),NULL,SND_SYNC );
    18.     button=0;
    19.     break;
    20.  
    21.     case 'e':
    22.        Sleep(20);
    23.     PlaySound( TEXT("C:\\Users\\Gumm\\Downloads\\real sound of notes\\dheem"),NULL,SND_SYNC );
    24.     button=0;
    25.     break;
    26.  
    27.     case 'r':
    28.     Sleep(20);
    29.     PlaySound( TEXT("C:\\Users\\Gumm\\Downloads\\real sound of notes\\dhi"),NULL,SND_SYNC );
    30.     button=0;
    31.     break;
    32.  
    33.     case 't':
    34.        Sleep(20);
    35.     PlaySound( TEXT("C:\\Users\\Gumm\\Downloads\\real sound of notes\\num"),NULL,SND_SYNC );
    36.     button=0;
    37.     break;
    38.  
    39.     case 'y':
    40.     Sleep(20);  
    41.        PlaySound( TEXT("C:\\Users\\Gumm\\Downloads\\real sound of notes\\sampoorna chapu"),NULL,SND_SYNC );
    42.        button=0;
    43.     break;
    44.  
    45.     case 'u':
    46.     Sleep(20);  
    47.     PlaySound( TEXT("C:\\Users\\Gumm\\Downloads\\real sound of notes\\ta"),NULL,SND_SYNC );
    48.     button=0;
    49.     break;
    50.  
    51.     //case 'q':
    52.     //exit(0);
    53.  
    54.     default:
    55.     printf("No sound");
    56.   }
    57. }
    This is how I made it work
     
  14. John P

    AAC Fanatic!

    Oct 14, 2008
    1,716
    254
    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.
     
  15. WBahn

    Moderator

    Mar 31, 2012
    22,986
    6,883
    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 (Text):
    1. #define FOREVER (1)
    2. #define SLEEP_TIME (20)
    3.  
    4. while(FOREVER)
    5. {
    6.    button = kbhit()? getch() : 0;
    7.  
    8.    switch (button)
    9.    {
    10.       case 'q': fileName = "C:\\Users\\Gumm\\Downloads\\real sound of notes\\ardha chapu.wav"; break;
    11.       case 'w': fileName = "C:\\Users\\Gumm\\Downloads\\real sound of notes\\chapu"; break;
    12.       case 'e': fileName = "C:\\Users\\Gumm\\Downloads\\real sound of notes\\dheem"; break;
    13.       case 'r': fileName = "C:\\Users\\Gumm\\Downloads\\real sound of notes\\dhi"; break;
    14.       case 't': fileName = "C:\\Users\\Gumm\\Downloads\\real sound of notes\\num"; break;
    15.       case 'y': fileName = "C:\\Users\\Gumm\\Downloads\\real sound of notes\\sampoorna chapu"; break;
    16.       case 'u': fileName = "C:\\Users\\Gumm\\Downloads\\real sound of notes\\ta"; break;
    17.  
    18.       default: fileName = NULL;
    19.    }
    20.  
    21.    if (fileName)
    22.    {
    23.       Sleep(SLEEP_TIME);
    24.       PlaySound(TEXT(fileName), NULL, SND_SYNC);
    25.    }
    26.    else
    27.       printf("No sound");
    28. }
    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.
     
    MrSoftware and goutham1995 like this.
  16. Picbuster

    Active Member

    Dec 2, 2013
    791
    97
    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;
    }
     
  17. goutham1995

    Thread Starter Member

    Feb 18, 2018
    80
    2
    Thanks for these tips.
     
  18. WBahn

    Moderator

    Mar 31, 2012
    22,986
    6,883
    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.
     
    MrSoftware likes this.
Loading...