Link to home
Start Free TrialLog in
Avatar of scottd1978
scottd1978

asked on

accept only 1 character

I am trying to accept only 1 character from the user.  If they enter more than one, the next cin statement is filled with the input from the previous.  Is is there a function to simply clear the input, or better yet, not allow the user to enter more than one character?
Avatar of sumant032199
sumant032199
Flag of United States of America image

You can use getch() or getche()
getch() ---  No echo.
getche()----- With echo.

These functions take only one character at a time.
return value char.
Avatar of nietod
nietod

Those are not standard C++ function.  Those are available only on C++ implimentations that have added them to the standard library.  (which is likely to be few.)

Scott, what you want to do is not possible in Standard C++.  In standard C++ input is line-buffered, which means the user may enter a whole line of text which does not become available to your program until the user presses enter.  In standard C++ there is no way around this.  However many compilers and many operating systems do provide other ways to perform I/O that do allow you to get around it.  (Like the functions sumant suggested.)  So we may be able to suggest some options if we knew what compiler and/or OS you are using.  However, using these functions will mean that you may not be able to port your program to another compiler or OS.
Avatar of scottd1978

ASKER

nietod,
   I am using gcc 2.7.2.1  ...
I don't have gcc, but it is not likely to have many or even any non-standard functions.  (because it was written to BE the standard.)  But you can try the functions Sumant suggested also the same functions with either 1 or 2 underscores in front of them, like "_getch()".  (Underscores are used to indicate non-standard functions, the names that Sumant suggested are really non-standard as they don't have the standard non-standard indicator.)

If that doesn't work, you will have to resort to OS-specific techniques, what OS are you using?
freebsd 4.3
that's not doin the trick
"freebsd"  Is that the OS?  I never heard of it.  Do you have programmer docs for it?
freebsd is a version of unix.  I hear an RTFM coming on here.
Hi,
 If gcc compiles C Programs (which i think it does) then getchar() will work. This not C++ function it is a C function <stdio.h> i suppose.

Bye
Abdij
abdij, getchar() is a standard C function so it will be avilable on all platforms.  Unfortunately, it does not do what is needed.  It performs line buffering, so the user has to press enter before the character will be returned to the program.

scottd1978,

Most versions of Unix have a library called "curses".  (Look for "curses.h".)  This will provide functions that will allow you to read a single character without buffering.  Now these functions are non-portable.  That is, they won't work on non-unix computers and may not work on some Unix computers.
You cannot do it using "cin" because the PC hangs on this statement until a "carriage return" is recieved. At least I never heard of it being done.
If you can't use the c functions "getch" etc. then the way I think you might be able to do it (if possible) is by calling the OS API functions to get the input. This way you will be able to control the amount of input recieved, but for your operating system I don't know what the API function names would be or what files would you have to include.
I know that for a windows console application I have used the "ReadConsoleInput" function to test for keystrokes in the input buffer. When you have recieved the next keystroke (keep looping in a while loop until a key is hit) then you assign that key to a "char". After that you can keep looping until you recieve a "carriage return" or simply exit the while loop.
If an example of this code may be useful I can supply it.

Regards,
C.
>> If you can't use the c functions "getch"
getch() and _getch() aren't standard C/C++ functions.  You will find them on most DOS/Windows compilers, but often not on a Unix compiler.

>> you might be able to do it (if possible) is
>> by calling the OS API functions to get the input
Didn't I say that?

>> or what files
>> would you have to include
Gee I don't know...."curses.h" maybe?

>> If an example of this code may be
>> useful I can supply it.
For a Unix program?  You might as well give him code for computing prime numbers, it would be just as useful to him.  There is one operating system in the world on which that code will work, its useless on all the others.  
try this :-

const int SOME_CONSTANT = 100;

#include <stdio.h>
#include <stdlib.h>
#include <iostream.h>

int main ()
{
      char c;
      cin >> c;
      cout << c << endl; // just to check the value read
      char* cptr = (char*) malloc(sizeof(char) * SOME_CONSTANT );
      cin.getline( cptr,  SOME_CONSTANT );
      cin >> c;
      cout << c << endl; // again check whether the new character is correct or not
      return 0;
}

Basically, the workaround is to read your character, and then read a line, which will read the rest of the characters till the delimiter is encountered, (getline has a default delim of '\n'), and then read your next character. We are trying to achieve the effect of flushing out here.

That will work to scott's 1st request   That is "Is is there a function to simply clear the input"  But it is usually possible to fill the 2nd request, that is "better yet, not allow the user to enter more than one character".

Also you would be best of using the global geline() procedure or even better the istream::ignore() procedure rather than the istream::getline() procedure.  Then you don't have to worry about the line length.  (i.e. these techniques will allow you to read and ignore a line of any length.)
Hi Nietod,

You are right:

cin << c;
cin.ignore( SOME_CONSTANT, '\n' );
cin << c;

will also server the purpose.

Though I have used curses routines, but that was around 4 years back, hence I need to brush up in that, but yes, using curses will definitely solve the other request: that is do not allow the user to input any more characters.

- Amit.
you can use

cin.ignore(numeric_limits<int>::max,'\n');

to ignore infinitely long.  Ugly, but you can define a constant for that.
Nietod,
My apologies for being a parrot to your answer. I didn't notice that you had mentioned OS functions. I will try be a little more toughtful in future.

But on the point about me supplying an example. I've often found that working from an example (even if its foriegn code) it can help your way of thinking about how you might APPROACH a problem.

And do you not think it was a little unfair to patronise my answer?

>> "For a Unix program?  You might as well give him code for computing prime numbers, it would be just as useful to him.  "
The only reason I supplied a comment was to be of some help. I wouldn't of bothered if I was expecting a remark like that. The reason we are here is to try help others not patronise others, would you not agree?
Rgds,
C.
an example would be a good place to start ... I'm having probs getting these curses functions to work.
>> My apologies for being a parrot to your answer
appology accepted.

>> I've often found that working from an example
>> (even if its foriegn code) it can help
I don't see how if can help in this case.  Your example cwill simply be a series of functions that have no relevance in Unix.  Now if you had a complex example of input, like a procedure that allowed the user to enter numbers, that would display and update the numbr as the user typed digits, but would ignore and not display characters as they were typed, that might make sense in that the logic of the example could be ported to UNIX.  The actually function calls that got the input or displayed it would have to be completely replaced, but the larger logic, that does the validation and display could remain, but that is not the type of example scottd1978 is looking for.

>>  it was a little unfair to patronise my answer?
I may have been a bit harsh, especially if you are new to EE, but this sort of  unfair "plagurism" is not considered ethical on EE.

>> reason we are here is to try help others
>> not patronise others, would you not agree?
True.  But to do it fairly.  

Yesterday alone on two questions I had worked on for several days, experts came along and submitted the very same information I did in a answer, in both cases they were awarded the points.  For the amount of effert I put in, I would have like the recognition for my work.  Those were not flukes, I probably see it happen once a day, although not always to me.

*********************************

>> an example would be a good place to start
I can't help you there..  bhattu, might be able to.  i haven't used it in 10+ years.

If I remember correctly, you just have to initialise the library (look for some sort of init???() function.  Then you can use any of the functions in the library.  You should look for input functions, like getXXXX() or readXXXX().

There should be man pages for the curses library they will give you a good overview of the library's features and its use.   It can be used to do much much more than what you are asking about.  I suspect you will find the other features very useful as well.
I could not seem to get the curses functions to work, I did however solve the problem.      // Accept user input
      do{    
        cout << endl << "Enter starting address (0-7) for your omega switch: ";
     
        // this allows only one character of input (system does not buffer input).
        system("stty raw");
     
        cin >> startc[0];
        cout << startc[0];
        startc[1] = '\0';
     
        // reset the terminal to buffered input
        system("stty sane");
     
        // convert the character to an integer
        starti = atoi(startc);
      }while (starti < 0 || starti > 7 || !(isdigit(startc[0])));

To nietod,
User need not press enter when one uses getch() or getche() functions.
>> User need not press enter when one
>> uses getch() or getche() functions.
That doesn't matter.

You also don't have to press enter when you use windows API ReadConsole().  But that doesn't help him either, does it?  

He isn't  using windows.  A function that isn't available to him isn't of any use to him.  If he were writting VC or other compiler that had these functions, it might be helpful, but he's not.
If you guys want to hack it out, why don't you get each other's email addresses?  I don't care to see an email everytime one of you takes a shot at each other.  As for the points go, I thank you guys for trying to help me out, but you didn't solve my problem.  I would like to get the points back if possible.  
>> I don't care to see an
>> email everytime
You can turn of e-mail notifications, just uncheck the box at the bottom.  (Although actually I don't recommend it, since this is your question.)

>> one of you takes a shot at each other.
I don't think that is what is happening.  

>> I would like to get the points back if possible.
If you delete the question, the points will be refunded.  There shoudl be a delete option at the bottom of the page.  since the question has been answered and rejected, the question will not be deleted right away, this is to give experts a chance to contest the delete.  (I have no objections).

If you need the points refunded immediately (don't want to wait), you will have to post a request in customer service.  But only do this if you really need the points right away, as they do get backed up.
thank you.
i must be blind .... i don't see this delete option on the page.
Try this and it might work. However, I am using scanf instead of cin. I am sure you can change it yourself. I have tried this program and it really works.

#include <stdio.h>

main()
{
    char cFirst = 0;
    char cSecond = 0;
    int  bInputValid = 0;

    while (!bInputValid)
    {
        printf("\nNOTE: Hit Ctrl-D if the prompt stops responding.\n");
        printf("Enter one character and press return:");

        if ((cFirst = getc(stdin)) == EOF)
        {
            printf("Error reading input.\n");
            fflush(stdin);
            continue;
        }
        if ((cSecond = getc(stdin)) == EOF)
        {
            printf("Error reading input.\n");
            fflush(stdin);
            continue;
        }

        fflush(stdin);

        if ( cFirst != '\n' && cSecond == '\n' )
        {
            bInputValid = 1;
        }
        else
        {
            printf("Invalid input.\n");
        }
    }

    printf("\nYou entered %c.\n", cFirst);

}


Hope it helps.

hongjun
hongjun,
    Did you not read the question history?  Or did you not understand it?

>> i must be blind .... i don't see this delete
>> option on the page.
If the question is locked, there is no option to delete it.  Try rejecting the answer, then there should be a delete option at the bottom.
I don't see a delete button for this question, where is it?
The question is still locked.  You cannot delete it when it is locked.  You must reject the answer in order to delete the question.
Now you shoudl have a delete button.  Do you?
NOPE
it used to be that the option was removed once a question was answered--even if the answer was rejected.  This was to prevent "cheating" by rejecting an answer and then deleting.  However, I was under the impression that that feature was no longer in place because there is now a waiting period where experts can object to the delete.  Maybe not.

If you post a request (0 point question) in community support (link on the bottom-right) topic area they will delete if for you and refund the points.  Be sure to include this question's ID.
The option to delete a question is only available until an answer is posted. After that, you will have to post a question in the Community Service area so that the other thread can be reviewed and then deleted if appropriate by one of the CS staff.

I have deleted this question.

darinw
Customer Service
ASKER CERTIFIED SOLUTION
Avatar of darinw
darinw

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>> This information seems very worthy of the PAQ.
This question probably appears several times a week.  And just as in this question it usually gets 4 or 5 compiler-specific answers that are of no use to the client asking the question.

On a UNIX system, the most desirable solution is to use the curses.h library, the solution found, running the stty utility, will work, but will be very inneficient.
There are very few topics, if any, where I will be capable of making a technical assessment of the issues involved. That is the case here. So, I read the thread and if it strikes me as a unique solution based on the interplay between the cusotmer and the expert(s) I will normally save it to the PAQ.

darinw
Agreed, I just didn't want it saved with it appearing as if that is "the" solution, since for most cases that is really not the optimal solution.
Fair enough =)
just posting this so I can uncheck the email notification.  Thanks for all your help guys.  I use this web site on a regular basis, and it really improves my efficiency when I'm trying to solve a problem I can't figure out quickly.