LinuxQuestions.org
Did you know LQ has a Linux Hardware Compatibility List?
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices



Reply
 
Search this Thread
Old 07-24-2007, 01:47 PM   #1
daYz
Member
 
Registered: Nov 2003
Distribution: Debian
Posts: 164

Rep: Reputation: 30
Howto use getchar() multiple times?


Hi,

Can someone tell me why the second getchar(); in the following code is skipped, and can you show me what would be the correct way of doing this?

Code:
#include <stdio.h>

main()
{   


getchar();

getchar();

return 0;

}
Thanks.

Regards,

Ben
 
Old 07-24-2007, 02:44 PM   #2
jlliagre
Moderator
 
Registered: Feb 2004
Location: Outside Paris
Distribution: Solaris10, Solaris 11, Mint, OL
Posts: 9,523

Rep: Reputation: 365Reputation: 365Reputation: 365Reputation: 365
Not that there are no issues with your program, but what makes you feel the second getchar() is skipped given the fact you do not get its return value.
 
Old 07-24-2007, 03:16 PM   #3
95se
Member
 
Registered: Apr 2002
Location: Windsor, ON, CA
Distribution: Ubuntu
Posts: 740

Rep: Reputation: 32
Given your rather short post, I can only guess that you don't realize that the new line entered when you press return is a character as well and that it is what the second getchar is returning. If this is not what your talking about, we're going to need a short example (ie. input, expected output, actual output) or something, because it should work otherwise.

Last edited by 95se; 07-24-2007 at 03:17 PM.
 
Old 07-24-2007, 03:38 PM   #4
daYz
Member
 
Registered: Nov 2003
Distribution: Debian
Posts: 164

Original Poster
Rep: Reputation: 30
Quote:
Originally Posted by 95se
Given your rather short post, I can only guess that you don't realize that the new line entered when you press return is a character as well and that it is what the second getchar is returning. If this is not what your talking about, we're going to need a short example (ie. input, expected output, actual output) or something, because it should work otherwise.
That is exactly what I mean. I was not aware of that.

Thanks for your help guys.

Regards,

Ben
 
Old 07-24-2007, 04:02 PM   #5
jlliagre
Moderator
 
Registered: Feb 2004
Location: Outside Paris
Distribution: Solaris10, Solaris 11, Mint, OL
Posts: 9,523

Rep: Reputation: 365Reputation: 365Reputation: 365Reputation: 365
Beware that your program is using the default cooked (buffered) tty mode, which is inconvenient with getchar. You may want to have a look at this thread about the issue and some solutions to fix it: http://www.linuxquestions.org/questi...d.php?t=122663
 
Old 07-24-2007, 05:08 PM   #6
daYz
Member
 
Registered: Nov 2003
Distribution: Debian
Posts: 164

Original Poster
Rep: Reputation: 30
Thanks jlliagre . I am going to look at this tommorow.

Ben
 
Old 07-24-2007, 06:49 PM   #7
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Something you might additionally consider is a SIGCONT signal handler since pausing a program in a shell will likely cause the shell to turn ICANON back on, severely screwing up your program:
Code:
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <signal.h>


struct termios old_settings, new_settings;

void exit(int);

void cont_handler(int sSignal)
{
	printf("%s\n", "[continue handler]");
	if (sSignal == SIGCONT)
	if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &new_settings) < 0) exit(1);
	printf("%s\n", "[press esc to exit]");
}

void term_handler(int sSignal)
{
	printf("%s\n", "[termination handler]");
	if (sSignal == SIGTERM)
	if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &old_settings) < 0) exit(1);
	exit(0);
}


main()
{
	if (tcgetattr(STDIN_FILENO, &old_settings) < 0) return 1;

	new_settings = old_settings;
	new_settings.c_lflag &= ~ICANON;
	new_settings.c_lflag &= ~ECHO;

	if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &new_settings) < 0) return 1;

	signal(SIGCONT, &cont_handler);
	signal(SIGTERM, &term_handler);

	int value;

	printf("%s\n", "[press esc to exit]");

	while ((value = getchar()) != EOF && value != 0x001b)
	printf("read: %c [0x%.4x]\n", (char) value, value);

	if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &old_settings) < 0) return 1;

	printf("%s\n", "[normal exit]");
	return 0;
}
To see what I mean, run the program above and after typing a few chars (in a Bash shell) press [Ctrl]+Z and then type fg. Now compile with the red line commented out and do the same thing.

Note that the SIGTERM handler won't catch a [Ctrl]+C press, which generates a SIGKILL signal. Luckily Bash will reset to canonical mode itself, but it's polite to have the SIGTERM handler in there anyway.

Take a look at tcgetattr, struct termios, and signal in the libc infopages for a whole lot more info on this.
ta0kira
 
Old 07-25-2007, 03:51 PM   #8
daYz
Member
 
Registered: Nov 2003
Distribution: Debian
Posts: 164

Original Poster
Rep: Reputation: 30
Thanks ta0kira.

I will take a look at this.

Regards,

Ben
 
Old 07-26-2007, 03:39 AM   #9
haxpor
Member
 
Registered: Dec 2006
Distribution: Ubuntu 9.10
Posts: 86

Rep: Reputation: 15
ํAs 95se said, the 'enter' key is also stored in the input-buffer so when the second call of getchar() come to play, it will be skipped. You can fix this by call fflush(stdin) -which means clear the input-buffer out, placing this function between the 2 calls.
 
Old 07-26-2007, 04:10 AM   #10
jlliagre
Moderator
 
Registered: Feb 2004
Location: Outside Paris
Distribution: Solaris10, Solaris 11, Mint, OL
Posts: 9,523

Rep: Reputation: 365Reputation: 365Reputation: 365Reputation: 365
Avoid fflush(stdin) or any input stream. The behaviour of such a command is undefined according to the C standard.

http://www.iso-9899.info/wiki/Implementation
 
Old 07-26-2007, 09:02 AM   #11
daYz
Member
 
Registered: Nov 2003
Distribution: Debian
Posts: 164

Original Poster
Rep: Reputation: 30
I have looked at cooked mode and I have tried the tcflush function, but I cannot get it working. Can someone please provide working example code for me please, and explain what is happening?

I want someone to be able to enter a character whereafter he should use the enter key to enter the value, and I want to do this twice in a row like this:

Code:
#include <stdio.h>

main()
{   

char a[] = "Please enter the character a\n\n";
printf("%s", a);

getchar();


char b[] = "Please enter the character b\n\nr";
printf("%s", b);

getchar();

return 0;

}
 
Old 07-26-2007, 09:12 AM   #12
jlliagre
Moderator
 
Registered: Feb 2004
Location: Outside Paris
Distribution: Solaris10, Solaris 11, Mint, OL
Posts: 9,523

Rep: Reputation: 365Reputation: 365Reputation: 365Reputation: 365
if you want the user to press the enter key after each character, then you can stay in cooked mode. Just call getchar() twice, one for the actual character and the second one to pick the return.
 
Old 07-26-2007, 09:47 AM   #13
daYz
Member
 
Registered: Nov 2003
Distribution: Debian
Posts: 164

Original Poster
Rep: Reputation: 30
Great! Thanks jlliagre.

Salut

Ben
 
Old 07-26-2007, 04:23 PM   #14
daYz
Member
 
Registered: Nov 2003
Distribution: Debian
Posts: 164

Original Poster
Rep: Reputation: 30
Quote:
Originally Posted by 95se
Given your rather short post, I can only guess that you don't realize that the new line entered when you press return is a character as well and that it is what the second getchar is returning. If this is not what your talking about, we're going to need a short example (ie. input, expected output, actual output) or something, because it should work otherwise.
Is '\n' the only character that gets entered when pressing the enter key? I always thought it where both '\r' and '\n'.
 
Old 07-26-2007, 05:30 PM   #15
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Quote:
Originally Posted by daYz
Is '\n' the only character that gets entered when pressing the enter key? I always thought it where both '\r' and '\n'.
Depends on the terminal. This can be controlled with tcsetattr, though.

I would just use gets to obtain an entire line, then strlen it and use the first character if it's longer than 3. Using 2 getchars in non-canonical mode won't do what you want. Whether the input be a then [Enter] or a then [Backspace] you will still have an uncontrolled input operation.
ta0kira
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Konqueror opens multiple times sploit Linux - Newbie 18 07-14-2007 09:11 AM
Shutdown message appears multiple times kluetsch Slackware 12 03-12-2007 02:04 PM
same email, multiple times ?? (exchange... sorry) itsjustme General 1 01-14-2005 03:33 PM
Tar command copied multiple times? cbriscoejr Linux - General 1 11-12-2004 03:09 PM
running wget multiple times quickk Linux - Newbie 1 09-16-2004 07:53 AM


All times are GMT -5. The time now is 05:10 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration