【问题标题】:C safe and proper way to get user input [closed]C获取用户输入的安全且正确的方法[关闭]
【发布时间】:2021-02-23 13:42:00
【问题描述】:

安全输入比我想象的要难。我环顾四周,找到了this,但它是从 2011 年开始的,从那时起情况可能已经发生了变化。

我正在寻找可以处理字符串输入和单字符输入的东西。例如:

Hello, what's your name?
My name is: _
Are you sure?
[Y] Yes, hello
[N] No, goodbye
_

这是我现在的做法:

char input[16];
fgets(input, 16, stdin);
char input = getchar();

我的问题一直是用户可能输入任意长的输入或者无效的输入。如何安全地读取输入并确保以后的输入不会被打扰?

寻找适用于 C 和 Linux/Windows 的解决方案。

感谢您的宝贵时间。

【问题讨论】:

  • ... 之后,刷新标准输入... - 不要想你是否可以fflush(stdin)。它会调用 UB。
  • 在 C 中创建动态字符串非常容易。在 C++ 中,您可以使用 std:string foo; std::cin >> foo。如果你愿意,我可以写 C 版本作为答案?
  • @ImportAccelerate 等待,直到 OP 决定这个问题是关于什么语言的。
  • @RohanBari 是的,我知道我不能这样刷新stdin,我的目的是让未来的输入不会变得无聊。对我来说,一个常见的经验是忘记输入缓冲区中仍然存在换行符,从而阻碍了下一次读取。

标签: c validation input


【解决方案1】:

您可以安全地读取无限标准输入。您可以只使用不断重新分配的缓冲区。

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

char* get_line(size_t* length) {
    size_t len = 0;
    size_t cap = 4;
    char* buffer = malloc(cap);
    if (buffer == NULL) {
        fprintf(stderr, "Virtual memory exhausted\n");
        return NULL;
    }

    char current;
    while ((current = getchar()) != '\n') {
        if (len + 1 > cap) {
            cap *= 2;
            buffer = realloc(buffer, cap);
        }
        buffer[len++] = current;
    }
    // One last time for NUL terminator
    if (len + 1 > cap) {
        cap *= 2;
        buffer = realloc(buffer, cap);
    }        
    buffer[len] = 0;

    if (length) *length = len;
    return buffer;
}

此函数将逐个字符地读取stdin 并将其添加到返回的字符串中。您可以选择询问它的长度。别忘了free

int main() {
    char* line = get_line(NULL);
    printf("You entered: %s\n", line);
    free(line);
}

注意:这段代码的意思是很少冗长,所以省略了一些检查。在生产代码中检查realloc 并使用int for getchar() 来测试EOF 是必要的。

【讨论】:

  • 你没有检查realloc的返回值
  • 确实如此。我将添加一个注释,这意味着它的详细程度很低,并且在生产代码检查realloc 是必要的。
  • 如果我可能会问,这里的参数size_t* length 是什么?是因为“您可以选择询问它的长度”吗?另外,逐个字符阅读不会产生开销吗?我没有任何统计数据要验证,但我觉得按字符阅读会比直接阅读一个块效率低。还是可以忽略不计?
  • 这里没有太多开销,因为大多数终端都是行缓冲的,所以所有字符都已经可用。 size_t* length 是一个可选参数,传递一个指向size_t 的指针,它将在那里存储字符串长度以避免随后的strlen。否则只需传递NULL
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-18
  • 1970-01-01
  • 2010-12-25
  • 1970-01-01
  • 2019-07-20
  • 2015-06-08
  • 1970-01-01
相关资源
最近更新 更多