这是一个格式输入函数,在标准库stdio.h头文件下该函数的声明为:int scanf (const char, ...);scanf函数的一般形式:scanf(格式控制,地址表列)。好了直接上问题吧(这是针对录入字符型数据出现的问题)。看如下几行代码:*
#include <iostream>
#include <cstdio>
int main()
{
char a,b;
scanf("%c",&a); //按照指定的格式从键盘读取字符
scanf("%c",&b);
std::cout << a << b << std::endl;
return 0;
}
当输入一个字母a加一个空格再输入一个字母f时或者当输入一个字母a敲回车再输入字母f时此时程序的运行结果却只是a。此时会想字母f呢?既然运行结果只是a,那么肯定变量b的值为其他的。这个时候考虑以上两种情况:1.当输入一个字母a再加一个空格再输入一个字母时,此时我们再上诉代码中加一句就会发现:
#include <iostream>
#include <cstdio>
int main()
{
char a,b;
scanf("%c",&a); //按照指定的格式从键盘读取字符
int ret = getchar(); //这里是有必要的
scanf("%c",&b);
std::cout << a << b << ret << std::endl;
return 0;
}
输入字母a再加一空格再输入f程序运行结果如下:
![](https://img.haomeiwen.com/i17728742/5ea40f0070d9284d.png)
对比上诉两段代码的运行结果就会发现,第一次运行时的结果其实是a加一个空格,也就是变量b的值为一个空格。当我们输入一个字母a加上一个空格和一个字母f时,这里有三个字符,所以第二个字符(空格)的值给了b变量。
当我们输入一个字母a敲回车在输入一个字母f时,我们还是用如上代码测试看运行结果就会发现
![](https://img.haomeiwen.com/i17728742/d3d7c5fcefec5cb3.png)
查看ASCLL码表可知,ASCLL值为10的是LF(LineFeed)即对应的字符为换行符。原来当我们输入一个字母a敲回车在输入一个字母f时,敲回车时产生了换行符,所以b的值是一个控制符。
查看相关资料说这是键盘缓冲区残留信息的问题解决办法可以是:
1.在每次scanf后加上这行代码(有多次scanf才有意义)
getchar();
getchar也是stdio.h头文件中的一个函数,声明如下:
//成功则返回来自标准输入流的下一字符的Ascll码值
//如果标准输入到了文件末尾或者其他的读取错误就返回EOF
int getchar(void);
2.在每次scanf后加上这行代码(有多次scanf才有意义)
//本函数声明:int getc(FILE * stream);
getc(stdin); //从标准输入流读取一个字符,和getchar一样的效果
3.在每次scanf后加上这行代码:(有多次scanf才有意义)
//本函数声明为:int fflush(FILE * stream);
fflush(stdin); //清空缓冲区
4.最后如果只有一个scanf函数的调用当然是直接输入数据不加空格或者回车啦
附上下午写的一段出错的代码:
//#号法创建一颗二叉树
BiTree createBiTree()
{
BiTreeNode* temp = nullptr;
char temp1;
scanf("%c",&temp1); //按照前序输入二叉树结点的值
getchar(); //这里加上才更不会出错
if (temp1 == '#')
{
return nullptr;
}
else
{
temp = (BiTreeNode*)malloc(sizeof(BiTreeNode));
assert(temp != nullptr);
temp->data = temp1;
//创建左子树
temp->lChild = createBiTree();
//创建右子树
temp->rChild = createBiTree();
return temp;
}
}
上面这段代码中,考虑到用户输入字符数据的格式不同(有的可能会加空格或者敲回车),解决键盘缓冲区残留无用信息是必要的。因此认识其他的输入函数也是有必要的。
网友评论