嗨,我在使用这个简单的 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)
这个论坛上有很多变化,没有一个对我有用......我错过了什么?
问题是您的scanf()
调用在遇到不只是空白的字符串之前不会返回。您应该fgets()
改用,因为它也可以防止溢出。
例子:
char s[80];
fgets(s, sizeof s, stdin);
if(s[0] == '\n') {
puts("line is empty");
}
Run Code Online (Sandbox Code Playgroud)
您可以防止用户只需按[enter]
用scanf
,但你必须既要:
scanf
退货,以及stdin
上[enter]
单独。您还必须通过限制scanf
尝试放入数组的字符来手动防止写入超出字符串的末尾。否则,scanf
将愉快地尝试写尽可能多的字符。(这使得面向行的输入像fgets
或getline
更可取)
但是,如果您将所有这些都考虑在内,您就可以执行看起来像您正在尝试的操作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)
如上所述,面向行的输入是读取字符串的首选方式。可用的两个主要工具是fgets
和getline
。两者都有优点/缺点。的两个主要优点getline
是它(1)将为您分配行缓冲区,以及(2)它返回读入缓冲区的实际字符数。
的一个弱点getline
是它会读取所有字符,直到内存耗尽。因此,如果您将输入限制为17
(16 个字符 + 空终止符),则由您来执行限制。的一个弱点fgets
是您无法知道实际阅读了多少个字符。您所知道的只是fgets
在两者之间读取1
,max length
通常会提示需要调用strlen
(或遍历字符串直到找到空终止符。)
既fgets
和getline
将包括所述后'\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)