c检测标准输入的空输入

c检测标准输入的空输入,c,stdio,C,Stdio,这似乎应该是一件简单的事情,但经过几个小时的搜索,我什么也没找到 我有一个函数,可以从stdin读取输入字符串并对其进行清理。问题是,当我在没有输入任何内容的情况下按enter键时,它显然只是从输入缓冲区中读取一些垃圾 在下面的示例中,提示符是“input”,在同一行上出现在它之后的所有内容都是我键入的内容。提示后面的行将回显函数读取的内容 首先,这里是当我在两次输入内容时发生的情况。在这种情况下,该功能完全按照预期工作 input? abcd abcd input? efgh efgh 第二

这似乎应该是一件简单的事情,但经过几个小时的搜索,我什么也没找到

我有一个函数,可以从stdin读取输入字符串并对其进行清理。问题是,当我在没有输入任何内容的情况下按enter键时,它显然只是从输入缓冲区中读取一些垃圾

在下面的示例中,提示符是“input”,在同一行上出现在它之后的所有内容都是我键入的内容。提示后面的行将回显函数读取的内容

首先,这里是当我在两次输入内容时发生的情况。在这种情况下,该功能完全按照预期工作

input? abcd
abcd
input? efgh
efgh
第二,当我第一次键入内容,但第二次按enter键时,会发生以下情况:

input? abcd
abcd
input?
cd
下面是我两次按enter键时发生的情况:

input?
y
input?
y
每次我重新运行它时,它都会返回“y”或“@”因为显而易见的原因,“y”是特别危险的

这是我的密码:

#include <stdio.h>
#include <stdlib.h>

#define STRLEN 128

int main() {
    char str[STRLEN];
    promptString("input?", str);
    printf("%s\n", str);
    promptString("input?", str);
    printf("%s\n", str);

    return EXIT_SUCCESS;
}

void promptString(const char* _prompt, char* _writeTo) {    
    printf("%s ", _prompt);
    fgets(_writeTo, STRLEN, stdin);
    cleanString(_writeTo);

    return;
}

void cleanString(char* _str) {
    char temp[STRLEN];
    int i = 0;
    int j = 0;

    while (_str[i] < 32 || _str[i] > 126) 
        i++;

    while (_str[i] > 31 && _str[i] < 127) {
        temp[j] = _str[i];
        i++;
        j++;
    }

    i = 0;
    while (i < j) {
        _str[i] = temp[i];
        i++;
    }
    _str[i] = '\0';

    return;
}
#包括
#包括
#定义STRLEN 128
int main(){
char-str[STRLEN];
promptString(“输入?”,str);
printf(“%s\n”,str);
promptString(“输入?”,str);
printf(“%s\n”,str);
返回退出成功;
}
void promptString(const char*\u prompt,char*\u writeTo){
printf(“%s”,_提示符);
fgets(写入、打印、打印);
清除字符串(_writeTo);
回来
}
void cleanString(char*\u str){
字符温度[STRLEN];
int i=0;
int j=0;
而(|str[i]<32|||str[i]>126)
i++;
而(_str[i]>31&&u str[i]<127){
温度[j]=_str[i];
i++;
j++;
}
i=0;
而(i
我尝试过各种刷新输入缓冲区的方法(甚至是不安全的方法)(fseek、revind、fflush)。没有人能解决这个问题


如何检测空输入,以便重新提示,而不是这种恼人且潜在危险的行为?

这部分
cleanString

 while (_str[i] < 32 || _str[i] > 126) 
      i++;

(与两个比较,因为
'\n'
fgets
放入缓冲区的末尾)

这部分
cleanString

 while (_str[i] < 32 || _str[i] > 126) 
      i++;

(与两个相比,因为
'\n'
fgets
放入缓冲区的末尾)

为什么有一堆带前导下划线的变量名?真讨厌

无论如何,您必须做的第一件事是检查
fgets
的返回值。如果它返回NULL,则您没有得到任何输入。(然后,您可以测试
feof
ferror
,以找出未获得输入的原因。)

转到
cleanString
,您有一个while循环,它使用一系列不可打印的字符(您可以使用
isprint
而不是幻数),然后是一个while循环,它使用一系列可打印的字符。如果输入字符串不是由一系列非可打印内容和一系列可打印内容组成的,则可能会消耗过多或不足。为什么不使用单个循环

while(str[i]) {
    if(isprint(str[i]))
        temp[j++] = str[i];
    ++i;
}
这保证会消耗整个字符串直到
\0
终止符,并且它不能一直超过终止符,它会将“good”字符复制到temp。我想这就是你想要的


你甚至不需要使用临时缓冲区,你可以直接从
str[i]
复制到
str[j]
,因为
j
永远不能超过
i
,你永远不会覆盖任何你还没有处理过的内容。

为什么你有一堆带前导下划线的变量名?真讨厌

无论如何,您必须做的第一件事是检查
fgets
的返回值。如果它返回NULL,则您没有得到任何输入。(然后,您可以测试
feof
ferror
,以找出未获得输入的原因。)

转到
cleanString
,您有一个while循环,它使用一系列不可打印的字符(您可以使用
isprint
而不是幻数),然后是一个while循环,它使用一系列可打印的字符。如果输入字符串不是由一系列非可打印内容和一系列可打印内容组成的,则可能会消耗过多或不足。为什么不使用单个循环

while(str[i]) {
    if(isprint(str[i]))
        temp[j++] = str[i];
    ++i;
}
这保证会消耗整个字符串直到
\0
终止符,并且它不能一直超过终止符,它会将“good”字符复制到temp。我想这就是你想要的


你甚至不需要使用临时缓冲区,你只需要从
str[i]
复制到
str[j]
,因为
j
永远不会超过
i
你永远不会覆盖任何你还没有处理过的东西。

可能会引起兴趣,尽管事实上,您的具体问题不是输入,而是后处理。尽管如此,该链接中的答案显示了一种更稳健的输入方式。可能会感兴趣,尽管您的具体问题不是输入,而是后处理。尽管如此,该链接中的答案显示了一种更稳健的输入方式。下划线是我个人对输入变量的约定。我曾尝试使用NULL检查fgets的返回,但这并没有解决问题。虽然我不知道isprint(),但这是一个很好的解决方案。不检查
fgets
的返回值是一个单独的问题,您还没有注意到。在提示符处按ctrl-D并观察发生了什么即使fgets返回NULL,也会将缓冲区传递给clean函数。在这种情况下,缓冲区包含垃圾(未初始化的内存或上一次调用的剩余字符串)@evenex_代码请注意下划线。我曾经用过它们,后来因为可能发生冲突,我改为在最后使用它们。我认为只有在这些情况下,这才是一个问题