4

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?

Lost in the code
  • 81
  • 1
  • 1
  • 7
  • It probably contains `\n`. Use `printf` to see what is in `input_input`. – Paco May 13 '15 at 16:42
  • You should really read the [answer to this question](http://stackoverflow.com/questions/1247989/how-do-you-allow-spaces-to-be-entered-using-scanf?answertab=active#tab-top) – pedwards May 13 '15 at 16:49
  • 1
    Try this code: `int k; char st[20]; st[0]=0; k=scanf("%[^\n]",st); printf("%d %s\n",k,st);` ... Although I think is better to use other functions! (`%[^\n]` means get all chars except `\n`) – Sir Jo Black May 13 '15 at 17:01
  • 1
    @Sergio Formiggini `scanf("%[^\n]",st)` will read nothing into `st` if user enters `'\n'`, leaving `st` as it was - possible uninitialized. The `'\n'` remains in `stdin` for the next input function. – chux - Reinstate Monica May 13 '15 at 19:33
  • Yes, but exits! The code I"ve sent you uses st[0]=0 before to call scanf ... But there's another problem, the CR remains into the stdin ... Thus it's not a good idea to use this scanf form! – Sir Jo Black May 13 '15 at 20:56

3 Answers3

5

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");
}
user12205
  • 2,684
  • 1
  • 20
  • 40
  • It's not true that scanf doesn't return also with only hitting enter! I tested this: `scanf("%[^\n]",str);` where `str` is (obviously) a `char *`. The result is scanf terminates also when you hit only enter! But is a better idea to use fgets! – Sir Jo Black May 13 '15 at 17:37
  • @SergioFormiggini I meant OP's `scanf()` call, not `scanf()` in general. Updated my answer. – user12205 May 13 '15 at 17:40
5

You can prevent the user from just pressing [enter] with scanf, but you must both:

  1. check the scanf return, and
  2. 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'
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
0

I don't know why everyone is giving complex solutions.

You can just use the 'system' function and give it "pause" which will check for any key press and then exit the program.

#include <stdio.h>

int main()
{
    // Whatever code here...

    system("pause");

    return 0;
}

This is a simple solution which works for windows.

  • Key thing being `Windows` here ;) If that's the only target platform, yes, it's fine. But it doesn't have to be the case. – alagner Jul 09 '21 at 08:23