webusername
asked on
getting input from stdin in C
I am running a program in C that takes input from the stdin . I did this
char input[2];
scanf("%s",input);
The user is able to enter more than 2 characters into input even though the size of the array is 2 .
What is wrong with scanf? I want to be able to restrict the number of characters only to 2 .
Thank You .
char input[2];
scanf("%s",input);
The user is able to enter more than 2 characters into input even though the size of the array is 2 .
What is wrong with scanf? I want to be able to restrict the number of characters only to 2 .
Thank You .
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Thanks for the info sunnycoder,
Here is somre additional ifno
Gets - agree I was actually referring to the fgets solution used earlier on - left the f off - there you have control over how much you read in.
In terms of fflush - this is what MSDN has to say about fflush
The fflush function flushes a stream. If the file associated with stream is open for output, fflush writes to that file the contents of the buffer associated with the stream. If the stream is open for input, fflush clears the contents of the buffer. fflush negates the effect of any prior call to ungetc against stream. Also, fflush(NULL) flushes all streams opened for output. The stream remains open after the call. fflush has no effect on an unbuffered stream.
So, the solution does have validity within MS environments.
However, I do agree with the principle that it should not be used if it is not a standard across all environments - the information in your posts was news to me - you learn something new everyday.
Here is somre additional ifno
Gets - agree I was actually referring to the fgets solution used earlier on - left the f off - there you have control over how much you read in.
In terms of fflush - this is what MSDN has to say about fflush
The fflush function flushes a stream. If the file associated with stream is open for output, fflush writes to that file the contents of the buffer associated with the stream. If the stream is open for input, fflush clears the contents of the buffer. fflush negates the effect of any prior call to ungetc against stream. Also, fflush(NULL) flushes all streams opened for output. The stream remains open after the call. fflush has no effect on an unbuffered stream.
So, the solution does have validity within MS environments.
However, I do agree with the principle that it should not be used if it is not a standard across all environments - the information in your posts was news to me - you learn something new everyday.
Hi Sunny,
>>There's lots of choices, but the terminal i/o routines (scanf(), gets(), etc) are poor ones
>This should work
>scanf("%2s",input);
In this limit scope, that's quite true. But it tends to hide problems when program changes are made. I'm a supporter of defining the length of the object (#define OBJECT_LENGTH 10) and using the length as a parameter to the function. When things change later, you're less likely to get bit.
(Heading you off at the pass....) You can certainly use these constants with scanf(), but it produces some ugly code.
scanf ("%*s", OBJECT_LENGTH, input);
Try THAT with 10 items to decode. :)
Kent
>>There's lots of choices, but the terminal i/o routines (scanf(), gets(), etc) are poor ones
>This should work
>scanf("%2s",input);
In this limit scope, that's quite true. But it tends to hide problems when program changes are made. I'm a supporter of defining the length of the object (#define OBJECT_LENGTH 10) and using the length as a parameter to the function. When things change later, you're less likely to get bit.
(Heading you off at the pass....) You can certainly use these constants with scanf(), but it produces some ugly code.
scanf ("%*s", OBJECT_LENGTH, input);
Try THAT with 10 items to decode. :)
Kent
Hi, webusername
It may be easyier to create a while loop: every cycle you call kbhit, this will return 1 if a key has been pressed and 0 otherwise. if a key has been pressed, you can use getch to read this char. if the char is enter or it's the second char typed, you abort the loop by calling break.
It may be easyier to create a while loop: every cycle you call kbhit, this will return 1 if a key has been pressed and 0 otherwise. if a key has been pressed, you can use getch to read this char. if the char is enter or it's the second char typed, you abort the loop by calling break.
ASKER
kdo
i tried
char input[BUFFER_SIZE+2]; /* The number of characters plus 1 for new-line plus 1 for end-of-line */
fgets (input, BUFFER_SIZE+2, stdin); /* Read up to two characters, new-line, and end-of-line */
now, the program skips the first line and goes to the second question. i am pulling my hair...
i tried
char input[BUFFER_SIZE+2]; /* The number of characters plus 1 for new-line plus 1 for end-of-line */
fgets (input, BUFFER_SIZE+2, stdin); /* Read up to two characters, new-line, and end-of-line */
now, the program skips the first line and goes to the second question. i am pulling my hair...
webusername,
My earlier post (if you are using MSVC) would work but as sunnycoder pointed out this is not portable.
Here is another option for you to try
#include <stdio.h>
int main(int argc, char* argv[])
{
char s[20];
int d;
scanf("%2s",s ) ;
fseek ( stdin, 0, SEEK_END ) ;
printf ( "%s\n", s ) ;
scanf ( "%d", &d ) ;
printf ( "%d\n", d);
return 0;
}
input: ab10
output: ab
input: 123
output: 123
A word on kdo's post. This is a good point but if you need to do type conversion then it makes it a bit easier i.e.
scanf ("%d", &number) as opposed to
fgets ( s, BUFFSIZE+1, stdin ) ;
number = atoi(s) ; etc
However, here is some code that does the above but with fgets
#include <stdio.h>
#define BUFFER_SIZE 2
int main(int argc, char* argv[])
{
char s[BUFFER_SIZE+1];
int d;
fgets ( s,BUFFER_SIZE + 1, stdin ) ;
fseek ( stdin, 0, SEEK_END ) ;
printf ( "%s\n", s ) ;
// the next line is to show that the extra chars input on the line are being dumped.
scanf ( "%d", &d ) ;
printf ( "%d\n", d);
return 0;
}
My earlier post (if you are using MSVC) would work but as sunnycoder pointed out this is not portable.
Here is another option for you to try
#include <stdio.h>
int main(int argc, char* argv[])
{
char s[20];
int d;
scanf("%2s",s ) ;
fseek ( stdin, 0, SEEK_END ) ;
printf ( "%s\n", s ) ;
scanf ( "%d", &d ) ;
printf ( "%d\n", d);
return 0;
}
input: ab10
output: ab
input: 123
output: 123
A word on kdo's post. This is a good point but if you need to do type conversion then it makes it a bit easier i.e.
scanf ("%d", &number) as opposed to
fgets ( s, BUFFSIZE+1, stdin ) ;
number = atoi(s) ; etc
However, here is some code that does the above but with fgets
#include <stdio.h>
#define BUFFER_SIZE 2
int main(int argc, char* argv[])
{
char s[BUFFER_SIZE+1];
int d;
fgets ( s,BUFFER_SIZE + 1, stdin ) ;
fseek ( stdin, 0, SEEK_END ) ;
printf ( "%s\n", s ) ;
// the next line is to show that the extra chars input on the line are being dumped.
scanf ( "%d", &d ) ;
printf ( "%d\n", d);
return 0;
}
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
This still suffers from the problem that if more chars are entered the next scanf or fgets or gets will read the remaining characters from the previous entry.
i.e.
scanf ( "%2[^\n]", str ) ;
If you enter
ab10
str will contain "ab".
However the next scanf will read the 10 and return without prompting the user for any input.
so
scanf ( "%2[^\n]", str ) ;
printf ( "%s\n", str ) ;
scanf ("%d", &d) ;
printf( "%d\n", d ) ;
with an input of "ab10"
will output
ab
10
but only one prompt.
i.e.
scanf ( "%2[^\n]", str ) ;
If you enter
ab10
str will contain "ab".
However the next scanf will read the 10 and return without prompting the user for any input.
so
scanf ( "%2[^\n]", str ) ;
printf ( "%s\n", str ) ;
scanf ("%d", &d) ;
printf( "%d\n", d ) ;
with an input of "ab10"
will output
ab
10
but only one prompt.
Ok so the problem of the to many read still persists. One can try to get away with
scanf("%2[^\n]%*s", str );
....
Regards
Friedrich
scanf("%2[^\n]%*s", str );
....
Regards
Friedrich
>kdo
>i tried
>char input[BUFFER_SIZE+2]; /* The number of characters plus 1 for new-line plus 1 for end-of-line */
> fgets (input, BUFFER_SIZE+2, stdin); /* Read up to two characters, new-line, and end-of-line */
>now, the program skips the first line and goes to the second question. i am pulling my hair...
There are a number of caveats with this approach. For instance, if one character is entered before the new-line, you get just the character and the new-line. If three characters are entered before the new-line, you get those three characters, but NOT the new-line, etc...
Kent
You may use this constuction
This code is slower but aviod buffer overflow(safe code)
#define sz 10
char input[sz];
for(int i=0;i<sz;i++)
{
input[i]=getchar();
}
This code is slower but aviod buffer overflow(safe code)
#define sz 10
char input[sz];
for(int i=0;i<sz;i++)
{
input[i]=getchar();
}
#include <stdio.h>
#include <string.h>
int main()
{
char buf[BUFSIZ];
char *p;
printf ("Please enter a line of text, max %d characters\n", sizeof(buf));
if (fgets(buf, sizeof(buf), stdin) != NULL)
{
printf ("Thank you, you entered >%s<\n", buf);
/*
* Now test for, and remove that newline character
*/
if ((p = strchr(buf, '\n')) != NULL)
*p = '\0';
printf ("And now it's >%s<\n", buf);
}
return 0;
}
/*
Program output:
Please enter a line of text, max 512 characters
this is a test
Thank you, you entered >this is a test
<
And now it's >this is a test<
*/
#include <string.h>
int main()
{
char buf[BUFSIZ];
char *p;
printf ("Please enter a line of text, max %d characters\n", sizeof(buf));
if (fgets(buf, sizeof(buf), stdin) != NULL)
{
printf ("Thank you, you entered >%s<\n", buf);
/*
* Now test for, and remove that newline character
*/
if ((p = strchr(buf, '\n')) != NULL)
*p = '\0';
printf ("And now it's >%s<\n", buf);
}
return 0;
}
/*
Program output:
Please enter a line of text, max 512 characters
this is a test
Thank you, you entered >this is a test
<
And now it's >this is a test<
*/
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Hi webusername,
Is your question answered?
If yes, please close this question.
If not, please give feedback, so that we can continue the discussion.
-ssnkumar
Is your question answered?
If yes, please close this question.
If not, please give feedback, so that we can continue the discussion.
-ssnkumar
>There's lots of choices, but the terminal i/o routines (scanf(), gets(), etc) are poor ones
This should work
scanf("%2s",input);
cheers
sunnycoder