1

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

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

在以下示例中,提示符为“输入?” 并且在同一行之后出现的所有内容都是我输入的内容。提示后面的行与函数读取的内容相呼应。

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

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;
}

我尝试了各种刷新输入缓冲区(fseek、rewind、fflush)的方法(甚至是不安全的方法)。它都没有解决这个问题。

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

4

2 回答 2

4

这部分cleanString

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

\0当字符串为空时跳过。

您应该添加_str[i] != '\0'到循环的条件中。

要检测一个空字符串,只需在输入后检查它的长度:

do {
  printf("%s ", _prompt);
  fgets(_writeTo, STRLEN, stdin);
} while (strlen(_writeTo) < 2);

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

于 2013-06-20T22:53:24.773 回答
2

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

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

继续前进cleanString,您有一个使用一系列不可打印字符的 while 循环(您可以使用isprint它而不是幻数),然后是一个使用一系列可打印字符的 while 循环。如果输入字符串不是由一系列不可打印的序列和一系列可打印的序列组成,那么您将消耗太多或不够。为什么不使用单个循环?

while(str[i]) {
    if(isprint(str[i]))
        temp[j++] = str[i];
    ++i;
}

这保证在终止符之前消耗整个字符串\0,并且它不能继续超过终止符,并且它将“好”字符复制到 temp。我想这就是你想要的。

您甚至不需要使用临时缓冲区,您可以从str[i]to复制str[j],因为j永远不会领先于i您,永远不会覆盖您尚未处理的任何内容。

于 2013-06-20T22:59:36.043 回答