如何在C中获取空输入或仅ENTER

Los*_*ode 3 c string input

嗨,我在使用这个简单的 C 代码时遇到了麻烦,因为我对它很陌生。

当我尝试从或获取空值时,如果用户只按 ENTER 而不输入任何内容。尝试了一些变化,但仍然无法正常工作

这段代码如下:

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;
      }
Run Code Online (Sandbox Code Playgroud)

还:

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;
      }
Run Code Online (Sandbox Code Playgroud)

这个论坛上有很多变化,没有一个对我有用......我错过了什么?

pas*_*pkT 5

问题是您的scanf()调用在遇到不只是空白的字符串之前不会返回。您应该fgets()改用,因为它也可以防止溢出。

例子:

char s[80];
fgets(s, sizeof s, stdin);
if(s[0] == '\n') {
    puts("line is empty");
}
Run Code Online (Sandbox Code Playgroud)


Dav*_*ica 5

您可以防止用户只需按[enter]scanf,但你必须既要:

  1. 检查scanf退货,以及
  2. 剥去换行符stdin[enter]单独。

您还必须通过限制scanf尝试放入数组的字符来手动防止写入超出字符串的末尾。否则,scanf将愉快地尝试写尽可能多的字符。(这使得面向行的输入像fgetsgetline更可取)

但是,如果您将所有这些都考虑在内,您就可以执行看起来像您正在尝试的操作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); }
Run Code Online (Sandbox Code Playgroud)

使用/输出

$ ./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'
Run Code Online (Sandbox Code Playgroud)

解决方案

如上所述,面向行的输入是读取字符串的首选方式。可用的两个主要工具是fgetsgetline。两者都有优点/缺点。的两个主要优点getline是它(1)将为您分配行缓冲区,以及(2)它返回读入缓冲区的实际字符数。

的一个弱点getline是它会读取所有字符,直到内存耗尽。因此,如果您将输入限制为17(16 个字符 + 空终止符),则由您来执行限制。的一个弱点fgets是您无法知道实际阅读了多少个字符。您所知道的只是fgets在两者之间读取1max length通常会提示需要调用strlen(或遍历字符串直到找到空终止符。)

fgetsgetline将包括所述后'\n'在缓冲液(当它存在于文件中,或当按下作为产生[enter]从读取时stdin)。将杂散的换行符挂在字符串的末端从来都不是一个好主意,因此在读取换行符后剥离它通常是一个好主意。

注意: getline如果缓冲区最初设置为NULL.. 则将为缓冲区分配内存,如果缓冲区getline不足以容纳输入,则..将重新分配给定的缓冲区。(分配的当前大小保持在 中'n')。由于getline为您分配/重新分配,您有责任在不再使用时释放内存。

考虑到所有这些,以下是一个等效的getline实现,它可以防止用户通过[enter]在提示处简单按下来防止留下空字符串:

#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;
}
Run Code Online (Sandbox Code Playgroud)

使用/输出

$ ./bin/getlinebasic_noenter

 Type something (16 char or less):
 pressing [enter] doesn't count...

 Type something (16 char or less): 12345678901234567890

   You entered: '1234567890123456'
Run Code Online (Sandbox Code Playgroud)