使用指针输入数据
- scanf
- 接收字符
- 接受数字
- 注意事项
- 为啥有时不设置长度,不会报错呢?
- fgets()
- fgets()配合sizeof一起使用
scanf
接收字符
//你将把人名保存在这个数组中
char name[40];
printf("Enter your name: ");
//scanf总共会读取39个字符,以及字符串终结符\0。
scanf("%39s", name);
scanf()
是怎么工作的呢?它接收一个char指针,而在这个例子中,传给了它一个数组变量。
这时你一定在想为什么scanf()
要接收指针,这是因为scanf()
函数打算更新数组的内容,一个想要更新变量的函数可不需要变量本身的值,它要的是变量的地址。
接受数字
int age;
printf("Enter your age: ");
//%i 表示用户会输入一个int值
//用&运算符得到int的地址
scanf("%i", &age);
把数值变量的地址传进了函数, scanf()
便可以更新变量的内容。为了帮你排忧解难, scanf()
允许传递格式字符串,就像你对printf()
函数做的那样,甚至可以用scanf()
一次输入多条信息:
char first_name[20];
char last_name[20];
printf("Enter first and last name: ");
//读取名,接着是一个空格,然后是姓。
//名和姓分别保存在两个数组中
scanf("%19s %19s", first_name, last_name);
printf("First: %s Last:%s\n", first_name, last_name);
注意事项
使用scanf()时要小心,scanf()
函数有一个小毛病。到目前为止,你写过的所有代码都小心翼翼地限制了scanf()
能读入的字符数:
scanf("%39s", name);
scanf("%2s", card_name);
为什么要这样做?毕竟scanf()
用了和printf()
一样的格式串,但当我们用printf()
打印字符串时,只用了%s
。如果在scanf()中只用%s
,一旦用户输入得太起劲,就会出问题:
char food[5];
printf("Enter favorite food: ");
scanf("%s", food);
printf("Favorite food: %s\n", food);
报错:
Enter favorite food: liver-tangerine-raccoon-toffee
Favorite food: liver-tangerine-raccoon-toffee
Segmentation fault: 11
程序崩溃了,因为scanf()在写数据时越过了food数组的尾部。
为啥有时不设置长度,不会报错呢?
- scanf()会导致缓冲区溢出
如果忘了限制scanf()
读取字符串的长度,用户就可以输入远远超出程序空间的数据,多余的数据会写到计算机还没有分配好的存储器中。如果运气好,数据不但能保存,而且不会有任何问题。
但缓冲区溢出很有可能会导致程序出错,这种情况通常被称为段错误或abort trap,不管出现什么错误消息,程序都会崩溃。
fgets()
除了scanf()
还可以用另一个函数来输入文本数据: fgets()
。和scanf()
函数一样, fgets()
接收char指针,不同的是,你必须给出最大长度。
//这个程序与之前的一样
char food[5];
printf("Enter favorite food: ");
//首先,它接收指向缓冲区的指针。
//其次,它接收字符串(包含\0”)的最大长度。
//stdin表示数据将来自键盘
fgets(food, sizeof(food), stdin);
也就是说当调用fgets()
时不可能一不小心忘记设置长度,因为它就出现在了函数的签名中,所以不得不加这个参数。另外,注意fgets()缓冲区大小把\0
字符也算了进去,所以不必像scanf()那样把长度减1。
fgets()配合sizeof一起使用
- 上面这段代码用
sizeof
运算符设置了最大长度,小心,别忘了sizeof
返回变量占用空间的大小。 - 在上面这段代码中,
food
是数组变量,所以sizeof
返回了数组的大小;如果food
是指针变量,sizeof
仅仅会返回指针的大小。 - 如果你要向
fgets()
函数传递数组变量,就用sizeof
。
- 如果只是传指针,就应该输入你想要的长度。如下:
printf("Enter favorite food: ");
//如果food是一个指针,就不能用sizeof,而应该显式给出长度。
fgets(food, 5, stdin);