Hi I'm having trouble with this simple C code since i'm very new to it.
When I try to get empty value from or get if the user only hit ENTER without typing anything.
Tried few variations and still not working
The piece of code is the following:
char user_input[17] = {'\0'};
printf("Type something: ");
prompt = scanf("%s", user_input);
if (prompt <= 0) {
printf("You didn't type anythingt!\n");
return 1;
}
Also:
char user_input[17] = {'\0'};
printf("Type something: ");
scanf("%s", user_input);
if (user_input[0] == '\0') {
printf("You didn't type anything!\n");
return 1;
}
There is many variations on this forum none of them worked for me...
What am I missing?
The problem is that your scanf()
call will not return until it encounters a string that is not whitespace only. You should use fgets()
instead, as it prevents overflow as well.
Example:
char s[80];
fgets(s, sizeof s, stdin);
if(s[0] == '\n') {
puts("line is empty");
}
You can prevent the user from just pressing [enter]
with scanf
, but you must both:
- check the
scanf
return, and
- strip the newline from
stdin
on [enter]
alone.
You must also manually prevent writing beyond the end of your string by limiting the characters scanf
attempts to put in your array. Otherwise, scanf
will happily try and write as many characters as are entered. (which makes line-oriented input like fgets
or getline
preferable)
However, if you take that all into consideration, you can do what it looks like you are attempting with scanf
:
#include <stdio.h>
#define MAXS 17
void fflush_stdin();
int main () {
char user_input [MAXS] = {0}; /* always initialize your variables */
while (printf ("\n Type something (16 char or less): ") &&
scanf ("%16[^\n]%*c", user_input) < 1)
{
printf (" pressing [enter] doesn't count...\n");
fflush_stdin();
}
printf ("\n You entered: '%s'\n\n", user_input);
return 0;
}
/* simple function to strip '\n` from stdin */
void fflush_stdin()
{ int c; while ((c = getchar()) != '\n' && c != EOF); }
Use/Output
$ ./bin/scanfbasic1
Type something (16 char or less):
pressing [enter] doesn't count...
Type something (16 char or less):
pressing [enter] doesn't count...
Type something (16 char or less): 12345678901234567890
You entered: '1234567890123456'
getline Solution
As mentioned above, line-oriented input is the preferred manner for reading strings. Two of the primary tools available are fgets
and getline
. Both have strengths/weaknesses. Two of the primary strengths of getline
is that it (1) will allocate the line buffer for you, and (2) it returns the actual number of characters read into the buffer.
A weakness of getline
is it will read all characters it is given up to the point of memory exhaustion. So if you are limiting your input to 17
(16 chars + null-terminator), it is up to you to enforce the limit. A weakness of fgets
is that you have no way of knowing how many characters were actually read. All you know is fgets
read somewhere between 1
and max length
generally prompting the need to call strlen
(or iterate over the string until the null-terminator is found.)
Both fgets
and getline
will include the trailing '\n'
in the buffer (as it exists in the file, or as produced when you press [enter]
when reading from stdin
). It is never a good idea to leave stray newlines hanging off the ends of your strings, so it is generally a good idea to strip the newline after it is read.
note: getline
will allocate memory for the buffer if the buffer is initially set to NULL
..and.. getline
will reallocate the buffer it is given if it is insufficient to hold the input. (the current size of the allocation is maintained in 'n'
). Since getline
allocates/reallocates for you, you are responsible for freeing the memory when it is no longer in use.
Taking all that into consideration, the following is an equivalent getline
implementation that prevents the user from leaving an empty string by simply pressing [enter]
at the prompt:
#include <stdio.h>
#include <stdlib.h>
#define MAXS 17
int main (void) {
char *ln = NULL; /* getline requires block allocated by malloc */
size_t n = 0; /* initial size of buffer, if ln NULL, n ignored */
ssize_t nchr = 0; /* getline return - number of chars actually read */
while (printf ("\n Type something (16 char or less): ") &&
((nchr = getline (&ln, &n, stdin)) <= 1)) {
printf (" pressing [enter] doesn't count...\n");
}
while (nchr > 0 && (ln[nchr-1] == '\n' || ln[nchr-1] == '\r'))
ln[--nchr] = 0; /* strip newline or carriage rtn */
if (nchr > MAXS - 1) /* to enforce limit, check length */
ln[MAXS - 1] = 0; /* if exceeds limit, null-terminate */
printf ("\n You entered: '%s'\n\n", ln);
if (ln) free (ln); /* free memory allocated by getline */
return 0;
}
Use/Output
$ ./bin/getlinebasic_noenter
Type something (16 char or less):
pressing [enter] doesn't count...
Type something (16 char or less): 12345678901234567890
You entered: '1234567890123456'