Fedora Linux Support Community & Resources Center
  #1  
Old 10th July 2012, 08:42 AM
casp3r Offline
Registered User
 
Join Date: Jun 2012
Location: Kuala Lumpur
Posts: 10
linuxfirefox
alternative for getchar in Linux ?

Hello forumers,

So i had this problem since my first C programming class, and i did a google search and try to replace getchar() with fgetc and others and it just not work. So here is the sample of exercise that i'm working on now.

The system waits for price of an item from the user, and ask whether there is another item by pressing 'y' || 'Y'. This is when i used the function of getchar and it doesn't work. It doesn't wait for input from the user

Can anybody tell me what i'm doing wrong here ?

P/s : its working well in Windows

Code:
#include <stdio.h>


void main ()
{
	
	void checkout();
	char morecust;
	//int getchar(void);	
	
	do
	{
		system("clear");
		checkout();		//function call
		printf("\n\n\tAnother customer? ");
		morecust=getchar();fflush(stdin);
	}
	while(morecust=="y" || morecust=="Y");
}

void checkout()
{

	float price,total=0;
	char moreitem;
	//int getchar(void);

	do
	{
		printf("\n\n\tEnter price :");
		scanf("%f",&price);
		total+=price;
		printf("\n\n\tAnother item?");
		moreitem=getchar();fflush(stdin);
	}
	while(moreitem=='y' || moreitem=='Y');
	printf("\n\n\tAmount %.2f: ",total);
	printf("\n\n\tTax %.2f: ",total*0.05);
	printf("\n\n\tTotal amt %.2f: ",total + (total*0.05));

}
Reply With Quote
  #2  
Old 10th July 2012, 09:51 AM
Fenrin Offline
Registered User
 
Join Date: Apr 2010
Location: Earth
Posts: 857
linuxopera
Re: alternative for getchar in Linux ?

a few month ago I tried to find a replacement for getch() (under Windoze you must include conio.h to use getch()).
Under Linux it looks like this:

Code:
#include <unistd.h> 
#include <termios.h>

int getch(void)
{
    int ch;
    struct termios oldt;
    struct termios newt;
    tcgetattr(STDIN_FILENO, &oldt); /*store old settings */
    newt = oldt; /* copy old settings to new settings */
    newt.c_lflag &= ~(ICANON | ECHO); /* make one change to old settings in new settings */
    tcsetattr(STDIN_FILENO, TCSANOW, &newt); /*apply the new settings immediatly */
    ch = getchar(); /* standard getchar call */
    tcsetattr(STDIN_FILENO, TCSANOW, &oldt); /*reapply the old settings */
    return ch; /*return received char */
}
the difference between getchar() and getch() is that it works without the return key. Above code doesn't work under windoze.

Is this function any help for you?

Last edited by Fenrin; 10th July 2012 at 09:56 AM.
Reply With Quote
  #3  
Old 10th July 2012, 11:29 AM
casp3r Offline
Registered User
 
Join Date: Jun 2012
Location: Kuala Lumpur
Posts: 10
linuxfirefox
Re: alternative for getchar in Linux ?

Thanks for clarify this, i have two questions here.

Code:
int getch(void)
why did you use void , because since we create a new function called "getch" so it surely takes something (value) right ?


Code:
int ch;
should i change it to the char since i'm accepting the character here ?

sadly, the code still doesn't make any difference



Sorry, i'm still a noob

Here is how i did it :

Code:
#include <stdio.h>
#include <unistd.h> 
#include <termios.h>

void main ()
{
	
	void checkout();
	char morecust;
		
	
	do
	{
		system("clear");
		checkout();		//function call
		printf("\n\n\tAnother customer? ");
		morecust=getch();fflush(stdin);
	}
	while(morecust=="y" || morecust=="Y");
}

void checkout()
{

	float price,total=0;
	char moreitem;
	

	do
	{
		printf("\n\n\tEnter price :");
		scanf("%f",&price);
		total+=price;
		printf("\n\n\tAnother item?");
		moreitem=getch();fflush(stdin);

	}
	while(moreitem=="y" || moreitem=="Y");
	

	printf("\n\n\tAmount %.2f: ",total);
	printf("\n\n\tTax %.2f: ",total*0.05);
	printf("\n\n\tTotal amt %.2f: ",total + (total*0.05));
	
}

int getch(void)
{
    int ch;
    struct termios oldt;
    struct termios newt;
    tcgetattr(STDIN_FILENO, &oldt); /*store old settings */
    newt = oldt; /* copy old settings to new settings */
    newt.c_lflag &= ~(ICANON | ECHO); /* make one change to old settings in new settings */
    tcsetattr(STDIN_FILENO, TCSANOW, &newt); /*apply the new settings immediatly */
    ch = getchar(); /* standard getchar call */
    tcsetattr(STDIN_FILENO, TCSANOW, &oldt); /*reapply the old settings */
    return ch; /*return received char */
}


and return this :



Code:
Enter price :50


	Another item?

	Amount 50.00: 

	Tax 2.50: 

	Total amt 52.50: 

	Another customer?
Reply With Quote
  #4  
Old 10th July 2012, 11:30 AM
aleph's Avatar
aleph Offline
Banned (for/from) behaving just like everybody else!
 
Join Date: Jul 2007
Location: Beijing, China
Posts: 1,307
linuxfirefox
Re: alternative for getchar in Linux ?

TO the OP: your code probably won't work under any system anyway. The problem is that you're comparing morecust to (the address of ) a literal string, in the while condition. And morecust should be int, there's no reason to cast it into char and cast back when comparing with the return value of getchar().

Just don't surround the "y" and "Y" characters with double quotes. Use the single quotes, which tells the compiler here's an int literal, not a string.
__________________
I believe in nerditarianism. I read FedoraForum for the Fedora-related posts.
Reply With Quote
  #5  
Old 10th July 2012, 04:41 PM
casp3r Offline
Registered User
 
Join Date: Jun 2012
Location: Kuala Lumpur
Posts: 10
linuxfirefox
Re: alternative for getchar in Linux ?

Quote:
Originally Posted by aleph View Post
TO the OP: your code probably won't work under any system anyway. The problem is that you're comparing morecust to (the address of ) a literal string, in the while condition. And morecust should be int, there's no reason to cast it into char and cast back when comparing with the return value of getchar().

Just don't surround the "y" and "Y" characters with double quotes. Use the single quotes, which tells the compiler here's an int literal, not a string.
Thanks for correcting me that, but this system does work on Windows, because this code directly copied from my lecturer in the class today and its working well on her machine, even after changed double quote with single, the results still the same. actually i have done 4-5 system using getchar() function and none of them are waiting for user input. If only my lecturer knows how to use Linux, i'd have asked her tho

---------- Post added at 11:41 PM ---------- Previous post was at 11:38 PM ----------

Here is the code directly from my lecturer :

(i removed conio.h and Windows.h)

Code:
//POS at grocery store
#include<stdio.h>



void main()
{
	void checkout(); //function prototype
	char ans;
	do
	{
		system("clear");
		checkout();  //function call returning back total
		printf("\n\n\t Another customer?:");
		ans=getchar();fflush(stdin);
	}while(ans=='y' || ans=='Y');
}
//function definition
void checkout()
{
	float price,total=0;
	char con;
	do
	{
		printf("\n\n\t Enter price: ");
		scanf("%f",&price);fflush(stdin);
		total+=price;
		printf("\n\n\t Another item ?:");
		con=getchar();fflush(stdin);
	}while(con=='y' || con=='Y');
	printf("\n\n\t   Amount %.2f: ",total);
	printf("\n\n\t      Tax %.2f: ",total*.05);
	printf("\n\n\tTotal amt %.2f: ",total + total*.05);
	
}

Last edited by casp3r; 10th July 2012 at 04:43 PM. Reason: cls already changed to "clear"
Reply With Quote
  #6  
Old 10th July 2012, 05:42 PM
Skull One's Avatar
Skull One Offline
Registered User
 
Join Date: Jun 2010
Location: Lost...
Posts: 550
linuxredhatmozilla
Re: alternative for getchar in Linux ?

The problem is not with 'getchar', but with 'fflush': it only works for _output_ streams.
For _input_ you can use '__fpurge' (from "stdio_ext.h"), or some function:
Code:
/* Discard rest of input line. */
int c;
while (c != '\n' && c != EOF)
        c = fgetc (stdin);
Ref:
info fflush
info __fpurge
info getchar
__________________
:confused:
Reply With Quote
  #7  
Old 10th July 2012, 06:38 PM
jpollard Offline
Registered User
 
Join Date: Aug 2009
Location: Waldorf, Maryland
Posts: 6,102
linuxfirefox
Re: alternative for getchar in Linux ?

The real issue is the scanf. It reads the input number, and stops on the first non-numeric value.

In this case, that value is a newline - it has not been processed yet.

When you do the "con=getchar()", what is returned is the newline.

Since the newline character is neither 'y' or 'Y', it terminates the checkout function.

Now, adding a "\n" to the format scan would terminate the line... but buffer handling gets strange. Now you are fighting both stdin buffering and stdout buffering. (the prompt for the next input doesn't occur because the scanf is waiting for the buffer...)

This problem is caused by mixing both buffered I/O and wanting non-buffered operation (sometimes).

This CAN work, but only on systems that don't use buffered I/O in the library... and I believe that is how windows does its unix "compatibility" (which isn't really compatible).

You would do better to have your own I/O (and any buffering you do/don't want.

the following will "work" for most systems:
Code:
//POS at grocery store
#include <stdio.h>
#include <stdlib.h>

void main(void)
{
        void checkout(void); //function prototype
        char ans;
        do
        {
                system("clear");
                checkout();  //function call returning back total
                printf("\n\n\t Another customer?:");
                fflush(stdout);
                while ((ans=getchar()) == '\n');
        }while(ans=='y' || ans=='Y');
}
//function definition
void checkout(void)
{
        float price,total=0;
        char con;
        do
        {
                printf("\n\n\t Enter price: ");
                fflush(stdin);
                scanf("%f",&price);
                total+=price;
                printf("\n\n\t Another item ?:");
                fflush(stdin);
                while ((con = getchar()) == '\n');
fprintf(stdout,"con=%d",con);
        }while(con=='y' || con=='Y');
        printf("\n\n\t   Amount %.2f: ",total);
        printf("\n\n\t      Tax %.2f: ",total*.05);
        printf("\n\n\tTotal amt %.2f: ",total + total*.05);

}
Note: the use of fflush(stdout) is reasonable, but most UNIX like systems don't need it when stdin/stdout is connected to a terminal.

The change is to replace the simple "xx=getchar" line with "while ((xx=getchar()) == '\n');" This causes the input to skip the terminating newline.

This is still not exactly reasonable - data lines like "25.5 and more" will not be processed correctly as the space following the 25.5 will terminate the loop, and the test for y or Y will fail (using the " ") and the outer loop for new customers will fail on the "a" of "and more".

There are a lot of "improper input" handling that isn't done.

Last edited by jpollard; 10th July 2012 at 06:52 PM. Reason: a solution
Reply With Quote
  #8  
Old 10th July 2012, 06:43 PM
Skull One's Avatar
Skull One Offline
Registered User
 
Join Date: Jun 2010
Location: Lost...
Posts: 550
linuxredhatmozilla
Re: alternative for getchar in Linux ?

Quote:
Originally Posted by jpollard View Post
The real issue is the scanf. It reads the input number, and stops on the first non-numeric value.

In this case, that value is a newline - it has not been processed yet.

When you do the "con=getchar()", what is returned is the newline.

Since the newline character is neither 'y' or 'Y', it terminates the checkout function.

Now, adding a "\n" to the format scan would terminate the line... but buffer handling gets strange. Now you are fighting both stdin buffering and stdout buffering. (the prompt for the next input doesn't occur because the scanf is waiting for the buffer...)

This problem is caused by mixing both buffered I/O and wanting non-buffered operation (sometimes).

This CAN work, but only on systems that don't use buffered I/O in the library... and I believe that is how windows does its unix "compatibility" (which isn't really compatible).

You would do better to have your own I/O (and any buffering you do/don't want.
We're saying the same: the stdin is not emptied.
It works fine using __fpurge.
__________________
:confused:
Reply With Quote
  #9  
Old 10th July 2012, 06:52 PM
jpollard Offline
Registered User
 
Join Date: Aug 2009
Location: Waldorf, Maryland
Posts: 6,102
linuxfirefox
Re: alternative for getchar in Linux ?

The __fpurge doesn't exist on some systems as it is definitely a non-standard function.
Reply With Quote
  #10  
Old 10th July 2012, 07:06 PM
Skull One's Avatar
Skull One Offline
Registered User
 
Join Date: Jun 2010
Location: Lost...
Posts: 550
linuxredhatmozilla
Re: alternative for getchar in Linux ?

Quote:
Originally Posted by jpollard View Post
The __fpurge doesn't exist on some systems as it is definitely a non-standard function.
You're right.
That's why we could also define a procedure to do the job, like the one used in the example of 'info getchar'.
__________________
:confused:
Reply With Quote
  #11  
Old 10th July 2012, 07:10 PM
RupertPupkin's Avatar
RupertPupkin Offline
Registered User
 
Join Date: Nov 2006
Location: Detroit
Posts: 4,616
linuxfedorafirefox
Re: alternative for getchar in Linux ?

I like Fenrin's solution, which is similar to the one here: http://wesley.vidiqatch.org/code-sni...tche-on-linux/
__________________
OS: Fedora 18 x86_64 | CPU: AMD64 3700+ 2.2GHz | RAM: 2GB PC3200 DDR | Disk: 160GB PATA | Video: ATI Radeon 7500 AGP 64MB | Sound: Turtle Beach Santa Cruz CS4630 | Ethernet: Realtek 8110SC
Reply With Quote
  #12  
Old 10th July 2012, 07:59 PM
jpollard Offline
Registered User
 
Join Date: Aug 2009
Location: Waldorf, Maryland
Posts: 6,102
linuxfirefox
Re: alternative for getchar in Linux ?

For unix based systems fenrin's solution will work. But again, not all systems have the tcgetattr libraries.

For basic classwork (which this looks like) it would be much better to implement a local function that does what you want. The example shown in "info getchar" is much more flexible (slightly reformatted):
Code:
int y_or_n_p (const char *question)
{
    fputs (question, stdout);
    while (1) {
        int c, answer;
        /* Write a space to separate answer from question. */
        fputc (' ', stdout);
        /* Read the first character of the line.
        This should be the answer character, but might not be. */
        c = tolower (fgetc (stdin));
        answer = c;
        /* Discard rest of input line. */
        while (c != '\n' && c != EOF)
            c = fgetc (stdin);
        /* Obey the answer if it was valid. */
        if (answer == 'y') return 1;
        if (answer == 'n') return 0;
        /* Answer was invalid: ask for valid answer. */
        fputs ("Please answer y or n:", stdout);
    }
}
Reply With Quote
  #13  
Old 11th July 2012, 06:15 AM
casp3r Offline
Registered User
 
Join Date: Jun 2012
Location: Kuala Lumpur
Posts: 10
linuxfirefox
Re: alternative for getchar in Linux ?

THANKS FOR ALL THOSE WHO HELPED ME CLARIFY THIS MATTER

Fenrin
jpollard
Skull One

Now i understand why and thanks for post some 'tricks' that can overcome this default buffer issue.

oh, and RupertPupkin, thanks for bringing up this useful article

http://wesley.vidiqatch.org/code-sni...tche-on-linux/

Linux FTW!
Reply With Quote
Reply

Tags
alternative, getchar, linux

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

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 On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
is there Tk filerExplorer alternative in linux ziko Wibble 0 1st April 2010 09:39 AM
Reading Keyboard Input without getchar mndar Programming & Packaging 2 16th April 2009 04:10 PM
Linux alternative to Exchange? Robb11 Servers & Networking 12 15th April 2008 08:28 AM
Is there an alternative for linux? cruiseoveride Linux Chat 15 22nd April 2006 05:00 PM


Current GMT-time: 11:02 (Tuesday, 21-05-2013)

TopSubscribe to XML RSS for all Threads in all ForumsFedoraForumDotOrg Archive
logo

All trademarks, and forum posts in this site are property of their respective owner(s).
FedoraForum.org is privately owned and is not directly sponsored by the Fedora Project or Red Hat, Inc.

Privacy Policy | Term of Use | Posting Guidelines | Archive | Contact Us | Founding Members

Powered by vBulletin® Copyright ©2000 - 2012, vBulletin Solutions, Inc.

FedoraForum is Powered by RedHat