标题: 软件开发 | 如何在 C 语言中安全地读取用户输入 [打印本页] 作者: 3AAA 时间: 2023-7-29 13:44 标题: 软件开发 | 如何在 C 语言中安全地读取用户输入
getline提供了一种更灵活的方法,可以在不破坏系统的情况下将用户数据读入程序。
在 C 语言中读取字符串是一件非常危险的事情。当读取用户输入时,程序员可能会尝试使用 C 标准库中的 gets函数。它的用法非常简单:
char *gets(char *string);
gets从标准输入读取数据,然后将结果存储在一个字符串变量中。它会返回一个指向字符串的指针,如果没有读取到内容,返回NULL值。
举一个简单的例子,我们可能会问用户一个问题,然后将结果读入字符串中:
#include
输入一个相对较短的值就可以:
Where do you live?Chicago
然而,gets函数非常简单,它会天真地读取数据,直到它认为用户完成为止。但是它不会检查字符串是否足够容纳用户的输入。输入一个非常长的值会导致gets存储的数据超出字符串变量长度,从而导致覆盖其他部分内存。
Where do you live?Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch
最好的情况是,覆盖部分只会破坏程序。最坏的情况是,这会引入一个严重的安全漏洞,恶意用户可以通过你的程序将任意数据插入计算机的内存中。
fgets函数历来是安全读取字符串的推荐方法。此版本的gets提供了一个安全检查,通过仅读取作为函数参数传递的特定数量的字符:
char *fgets(char *string, int size, FILE *stream);
fgets函数会从文件指针读取数据,然后将数据存储到字符串变量中,但最多只能达到size指定的长度。我们可以更新示例程序来测试这一点,使用fgets而不是gets:
#include
如果编译运行,你可以在提示符后输入任意长的城市名称。但是,程序只会读取 size= 10 数据存储到字符串变量中。因为 C 语言在字符串末尾会添加一个空(\0)字符,这意味着fgets只会读取 9 个字符到字符串中。
Where do you live?Minneapolis
虽然这肯定比 fgets读取用户输入更安全,但代价是如果用户输入过长,它会“切断”用户输入。
结果证明这是一种更安全的方法读取任意数据,一次一行。要使用 getline,首先定义一个字符串指针并将其设置为NULL,表示还没有预留内存,再定义一个size_t类型的“字符串大小” 的变量,并给它一个零值。当你调用getline时,你需要传入字符串和字符串大小变量的指针,以及从何处读取数据。对于示例程序,我们可以从标准输入中读取:
#include
使用 getline读取数据时,它将根据需要自动为字符串变量重新分配内存。当函数读取一行的所有数据时,它通过指针更新字符串的大小,并返回读取的字符数,包括分隔符。
Enter a really long string:Supercalifragilisticexpialidociousgetline returned 35
注意,字符串包含分隔符。对于 getline,分隔符是换行符,这就是为什么输出中有换行符的原因。 如果你不想在字符串值中使用分隔符,可以使用另一个函数将字符串中的分隔符更改为空字符。
通过 getline,程序员可以安全地避免 C 编程的一个常见陷阱:你永远无法知道用户可能会输入哪些数据。这就是为什么使用gets不安全,而fgets又太笨拙的原因。相反,getline提供了一种更灵活的方法,可以在不破坏系统的情况下将用户数据读入程序。