使用C语言编写程序时,很多时候需要处理从标准输入输入的字符串。
理论上讲有三种方法:
scanf("%s", str);fgets(str, SIZE + 1, stdin); // +1 是为了存放字符串结尾符'\0'
其中
str : 一个char指针或者char数组名
SIZE : 一个常量
stdin :标准输入
首先要注意的问题是str应为一个char指针,还是一个char数组名。如果str为一个char指针,那么在从标准 输入读取数据时,将无法确定要读取的字节数。这是一个著名的漏洞,当用户输入超出函数使用的数组范围时将造成缓冲区溢出。因此,不能将str定义 为一个char指针,而要定义为一个数组名。
对于以上三个函数,输入字符串时有什么异同呢
当使用scanf函数时,如果在数组范围内有空格,那么第一个空格之后的字符将被忽略,仍然保留在缓存区。而且,scanf函数也不提供对写入数组的数据是否越界的检查。
#include
#define SIZE 20
void main(){
char str[SIZE]={0};
scanf("%s",&str); //输入 my name is c
printf("%s",str);
}
输出结果为my
#include
#define SIZE 10
void main() {
char str1[SIZE] = { 0 }, str2[SIZE] = { 0 }, str3[SIZE] = { 0 },str4[SIZE] = { 0 };
scanf("%s%s%s%s", &str1, &str2, &str3, &str4); //输入 my name is c
printf("%s\n", str1);
printf("%s\n", str2);
printf("%s\n", str3);
printf("%s\n", str4);
}
my
name
is
c
当使用gets函数时,gets也不提供对写入数组的数据进行是否越界的检查。
#include
#define SIZE 20
void main() {
char str[SIZE] = { 0 };
gets_s(str); //输入 my name is c
printf("%s\n", str);
}
使用fgets函数时,只要第二个参数正好等于第一个参数传给它的数组的字节个数,那么fgets函数不会写出数组边界。
#include
#define SIZE 10
void main() {
char str[SIZE] = { 0 };
fgets(str,SIZE,stdin); //输入 my name is c
printf("%s\n", str);
}
输出
字符串str的第十个字符是字符串结尾符'\0'
#include
#define SIZE 10
void main() {
char str[SIZE-1] = { 0 };
fgets(str,SIZE+1,stdin); //输入 my name is c
printf("%s\n", str);
}
输出
my name is
发生了数组越界。