scanf函数注意点:
- 函数参数必须一一对应
- 数据类型也要一一对应
scanf是缓冲输入的,也就是说从键盘输入的数据都会先存放在内存中的一个缓冲区,只有按回车键之后scanf才会进入缓冲区读取数据,所取数据的个数取决于 scanf 中“输入参数”的个数(因而我们说参数的个数必须一一对应),从键盘输入的一切数据,不管是数字、字母,还是空格、回车、Tab 等字符,都会被当作数据存入缓冲区。存储的顺序是从前往后。按回车键的时候 scanf 开始进入缓冲区取数据,依次从前往后去取读取数据
例如用%d进行输入,空格、回车、Tab 键都是区分数据与数据的分隔符。当 scanf 进入缓冲区中取数据的时候,如果 %d 遇到空格、回车、Tab 键,那么它并不取用,而是跳过继续往后取后面的数据,直到取到“十进制整数”为止。对于被跳过和取出的数据,系统会将它从缓冲区中释放掉。未被跳过或取出的数据,系统会将它一直放在缓冲区中,直到下一个 scanf 来读取
例如:
但是如果遇到其他的数据类型,那么它不会跳过也不会取用,而是直接从缓冲区跳出。
- 缓冲区信息残留问题:
运行如下:
完全忽略了两个scanf的输入,原因呢,我想就是,每一次scanf进入缓冲区读取数据,是以回车键结束,缓冲区中的’’\n’'还依旧存在缓冲区中,等待下一个scanf来读取,"\n"就会成为下一个scanf读取的数据。
那要怎样解决这个问题
第一种方法:加入rewind(stdin)
,它的意思是清空输入缓冲区
void creatGraph(Graph *G) {
int i, j, k;
printf("请输入顶点数和边数:");
scanf("%d %d", &(G->numVertexs), &(G->numEdges));
rewind(stdin);
for (i = 0; i < G->numVertexs;i++) {//顶点数
printf("请输入顶点信息:");
scanf("%c", &(G->vexs[i]));
rewind(stdin);
}
第二种方法:"%[^\n]%*c"
,原理是用扫描集将缓冲区中的字符全部读取来实现清除输入缓冲区的动作,%[^\n]
将逐个读取缓冲区中的’\n’字符之前的其它字符,%后面的*表示将读取的这些字符丢弃,前遇到’\n’字符时便停止读取操作,此时,缓冲区中尚有一个’\n’字符遗留,所以后面的%*c将读取并丢弃这个遗留的换行符,这里的星号和前面的星号作用相同。由于所有从键盘的输入都是以回车结束的,而回车会产生一个’\n’字符,所以将’\n’连同它之前的字符全部读取并丢弃之后,也就相当于清除了输入缓冲区。
void creatGraph(Graph *G) {
int i, j, k;
printf("请输入顶点数和边数:");
scanf("%d %d", &(G->numVertexs), &(G->numEdges));
getchar();//将缓冲区残留的"\n"读出来
for (i = 0; i < G->numVertexs;i++) {//顶点数
printf("请输入顶点信息:");
scanf("%[^\n]%*c", &(G->vexs[i]));
}