i'd be interested in knowing how the c programmers here at LNO handle the following:
1) getting a string from a user (without whitespace)
2) getting a string from a user (with whitespace)
3) getting a single character input from a user
4) getting a number from a user (float, double, int)
i'm just curious, i haven't had any really good experiences using scanf(), and i end up using
getchar() in a while loop.
For any commercial development, you usually don't use any of the Standard C library functions. You use some specialize widget to do the data entry for you. You either write one, or use any of the available libraries out there like curses, gtk+, etc.
aph3x
11-09-2000, 01:32 AM
to safely get a string from a user, with or without whitespace, i would use fgets() to prevent overflowing the buffer. also use fscanf() as an alternative to scanf(), and use getchar() for characters.
printf{"Enter a string: ");
fgets(string, 20, stdin);
printf("The string you entered is: %s", string);
printf("Enter an integer: ");
fscanf(stdin, "%d", &x);
printf("The integer you entered is: %d", x);
printf("Enter a floating point number: ");
fscanf(stdin, "%f", &y);
printf("The float number you entered is :%f", y);
return 0;
}
hope that helps a bit http://www.linuxnewbie.org/ubb/biggrin.gif
TheLinuxDuck
11-09-2000, 12:28 PM
binary:
aph3x has the right idea for sure! fgets is nice for concatenating user input to a specified length.
Here is a C code snippet I've been working on for accepting immediate action for a single character input, and using that to build a string. It's not very fancy and doesn't do a lot of fancy tapdancing, but it handles the job decent enough.
I plan on eventually cleaning this code up to have a few 'bells and whistles' for improved string input, but I just haven't gotten around to it. http://www.linuxnewbie.org/ubb/smile.gif
/* user input functions that allow for immediate response to keyboard input
including a string building function
TheLinuxDuck on linuxnewbie.org - bfkester@yahoo.com
This code works on my machine. I haven't done any extensive testing with it
or anything so it may not work for you. I don't know. I'm just a duck with
a keyboard... whatdoyouwantfromme?
*/
#include <stdio.h> // stdout, fflush, sprintf, printf
#include <string.h> // memset, called from macro FD_ZERO
#include <sys/time.h> // struct timeval
#include <sys/types.h> // fd_set (also FD_ZERO, FD_SET, select from select.h)
#include <termios.h> // struct termios, tcgetattr, tcsetattr, TCSAFLUSH
#include <unistd.h> // read
char singlekey(short int waittime); // one single key press
char stringkey(char *bptr,short int stringlength); // string input
int main(void)
{
struct termios newtty,Savetty; // for new terminal settings, and save
char quit=0,text[256];
if(tcgetattr(0,&Savetty)==-1) { // load current setting
printf("Could not initialize save of terminal settings.\n");
return 1;
}
newtty=Savetty; // copy current to new terminal settings
/* I used the source for the 'top' program to learn how to do this, so the
settings for the new terminal type where taken directly from it. I'm not
sure what these all really do, but they work. http://www.linuxnewbie.org/ubb/smile.gif
*/
newtty.c_lflag &= ~ICANON;
newtty.c_lflag &= ~ECHO;
newtty.c_cc[VMIN]=1;
newtty.c_cc[VTIME]=0;
if(tcsetattr(0,TCSAFLUSH,&newtty)==-1) { // Set new terminal
printf("Could not set new terminal type.\n");
return 1;
}
printf("Press any key, q to quit.\n"); // Single key press loop
while(!quit) {
if((quit=singlekey(5))>0) {
printf("You pressed the %c [%d] key.\n",quit,quit);
if((quit&223)=='Q')
quit=1;
else
quit=0;
}
}
printf("Enter some text:\n");
stringkey(text,100); // Get a string
printf("\nYou entered: %s\n", text);
tcsetattr(0,TCSAFLUSH,&Savetty); // restore original settings
return 0;
}
while(1) {
/*
According to the man info about select, these next four items must be set
each time before select is called, as the vars are reset each time (if I
understood it correctly)
*/
delay.tv_sec=waittime;
delay.tv_usec=0;
FD_ZERO(&input);
FD_SET(0,&input);
/*
We're letting select tell us if a key is waiting in the input buffer, and
reading a char to return if it happens in the alloted 'waittime'
*/
if(select(1,&input,NULL,NULL,&delay)>0 && read(0,&returnchar,1)==1)
return(returnchar);
}
return(0);
}
char stringkey(char *bptr,short int stringlength)
{
char buffer[256]={0};
char quit=0,current=0;
if(stringlength>255) stringlength=255; // set max stringlength
while(quit!=10) {
switch((quit=singlekey(5))) {
case 8: // backspace pressed
if(current>0) {
buffer[(int)(--current)]='\0';
printf("%c %c",8,8); fflush(stdout);
}
break;
case 10: // enter pressed
sprintf(bptr,"%s",buffer);
break;
default: // any other key added to string
if(current+1<stringlength-1) {
buffer[(int)(current++)]=quit;
printf("%c",quit); fflush(stdout);
}
break;
}
}
return(1);
}
------------------
TheLinuxDuck
Wait... that's a penguin?!?!?
:wq
aph3x
11-09-2000, 02:25 PM
Originally posted by TheLinuxDuck:
aph3x has the right idea for sure! fgets is nice for concatenating user input to a specified length.
yeah, some guy metioned this to me a month or so ago when i had a post with scanf() in it. he warned me of the overflow possibilities so i researched fscanf(), fgets(), and other formatted functions.
i vaguely recall this guy having a bit of confusion over whether the linux logo was a duck or a penguin. hmm, maybe its just my imagination... http://www.linuxnewbie.org/ubb/wink.gif http://www.linuxnewbie.org/ubb/tongue.gif
printf{"Enter a string: ");
fgets(string, 20, stdin);
While this one tries to prevent buffer overflow, unfortunately there is not enough room for a null terminator, and may still lead to buffer overflow.
Should be:
fgets(string, 19, stdin);
also use fscanf() as an alternative to scanf(),
fscanf has still the same problem as scanf. scanf is effectively an fscanf on stdin.
You're better off using fgets, then parsing the buffer yourself. Or use fgets, then sscanf on it.
/* I used the source for the 'top' program to learn how to do this, so the
settings for the new terminal type where taken directly from it. I'm not
sure what these all really do, but they work.
*/
newtty.c_lflag &= ~ICANON;
newtty.c_lflag &= ~ECHO;
This basically sets the terminal io to raw mode, so the terminal driver does not do any processing like interpeting control characters. Also turns of echo. The code is basically an implementation of most DOS's libraries' getch().
aph3x
11-10-2000, 01:29 AM
i thought once fgets() reached 20 characters it stopped accepting input and added a null character for string[19], kinda like cin.getline() in c++...
jemfinch
11-10-2000, 02:31 AM
Originally posted by LloydM:
char string[20];
printf{"Enter a string: ");
fgets(string, 20, stdin);
While this one tries to prevent buffer overflow, unfortunately there is not enough room for a null terminator, and may still lead to buffer overflow.
Should be:
fgets(string, 19, stdin)
Originally posted by the man page:
fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A '\0' is stored after the last character in the buffer.
Jeremy
LloydM
11-10-2000, 05:53 AM
Oops my mistake. Have no man page anywhere at all. Been running without Linux for far too long now. Got to get my system at home working again.
Too used to doing things like: snprintf( buf, sizeof(buf)-1, ...), etc. which is BTW, whose behavior is implementation dependent too (as it isn't part of the standard yet).
e.g. sometimes you have to do something like this for snprintf to work:
char buf[ 512 ];
buf[ sizeof(buf)-1 ] = '\0';
snprintf( buf, sizeof(buf)-1, "%s\n", var );
[This message has been edited by LloydM (edited 10 November 2000).]
TheLinuxDuck
11-10-2000, 05:13 PM
Originally posted by aph3x:
i vaguely recall this guy having a bit of confusion over whether the linux logo was a duck or a penguin. hmm, maybe its just my imagination... http://www.linuxnewbie.org/ubb/wink.gif http://www.linuxnewbie.org/ubb/tongue.gif
LOL! Did he ever figure it out?? http://www.linuxnewbie.org/ubb/biggrin.gif This guy doesn't sound too bright.. ::grin::
------------------
TheLinuxDuck
Wait... that's a penguin?!?!?
:wq
justlinux.com
Copyright Internet.com Inc. All Rights Reserved.