输入输出

从键盘输入的字符首先被储存在电脑的缓存区,当按下回车键的时候,输入函数才会开始从缓存区去读取输入的字符。

从缓存区读取时,如果缓存区为空,命令行界面会暂停,等待用户输入。

1、单个字符输入输出函数getchar();putchar();一次只能读取或输出一个任意字符,包括回车键。

 

2、非标准函数getch()和getche()也是单个字符的读取,但是不是所有的编译器都支持。我用的cfree5就不支持。

但是getch()函数读入用户输入的字符的时候,并不回显到屏幕上,getche()回显到屏幕。

 

3、字符串输入输出gets(),puts(),也读取回车。

int main()
{
     char ch[10];
     gets(ch);
     puts(ch);
}

 

4、格式化输入输出scanf(),printf();

首先是scanf()。这个函数最开始就是为了读取那些相对结构化和格式化输入的场景。但是当实际应用的时候,用户的输入格式一般都不是很规范,所以有时候会导致一些错误。

这个时候就需要用到fgets(),sscanf(),strtol()等函数对输入进行分别读取。这样可以对用户的输入错误有更好的包容性。

所以在使用scanf()函数,当输入的时候一定特别注意格式的对应。避免一些不必要的麻烦。

比如,格式控制字符串中的非空白字符一定要和输入流中下一个输入的字符匹配上。如果匹配不上,scanf()会失败并退出。

scanf(“%c,%d %s",&c,&i,&str);

当上面这种情况,当你从键盘输入的时候,要这样:a,123空格abc回车。输入的时候一定一定特别细心。

总之,scanf、有以下三个特点

(1)输入字符的时候,输入中的任何字符都不会被忽略。

(2)输入数字“%d”或字符“%s”的时候,输入中的空白字符被忽略,或者被当成输入的结束。

(3)如果缓冲区不为空,scanf按自己的格式提取,提取成功,则从缓冲区提走数据;提取失败,不提走数据。scanf函数返回成功提取的数据个数。

 

 其次是printf()函数,格式化输出。他和scanf()函数还是有一定的区别的,最重要的一点就是,printf中使用%f输出double和float类型;scanf函数必须使用%f输入float,%lf输入double。

printf格式控制字符串中,比较常用的就是“m.n”格式。这样可以使我们的输出做到小数点对其。值得注意的是,“m.n”格式中的m不是指整数所占的位数,而是整个数所占的位数。

 

最后,老赵说了 字符串的安全输入法,这是以后能用到的,要是你给人家公司 写程序 ,肯定要求安全。这时就不能像现在这样,只是为了实现功能而写,那时要考虑的安全问题就多多了。

字符串的两种输入方法,scanf和gets,但是这两种输入都不安全,并不会对你的输入进行越界检查。导致一些灾难性的错误。比如下面的例子。

 1 char pw[10] = "pass";
 2 char in[8];
 3 while(1)
 4 
 5     //scanf("%s",&in);
 6     fgets(in);
 7     if(strcmp(in,pw) == 0){
 8         printf("yes\n");
 9         break;
10     }
11     else{
12         printf("no\n");
13     }

这算是我接触的第一个简单的黑客思想吧。还有点小激动。这个程序乍一看没问题,输入pass,打印yes。但是当你先输入“11111111heike”,前面是8个1;输出no,没毛病;

当你再次输入heike的时候,就会输出yes,。。。。这是怎么回事?

其实在你定义的时候,pw【】和in【】两个数组是紧挨在一起的,in【】在前面,占8个字节,当你第一次输入8个1 的时候,他占据了in【】;随后的“heike”越界侵入了pw【】;

由于c语言并不进行越界检查(好懒),最后的结果就是评委【】里面保存的字符是“heike”,然后当你再一次输入“heike”的时候,strcmp()返回0,整个密码系统被破坏。

 

所以c语言中强烈推荐使用fgets()函数来完成c的输入。只是稍微有一点的麻烦。

关于fgets()的内容可以看我的其他博客。

 

posted @ 2017-04-22 10:12  Andrew_qian  阅读(246)  评论(0编辑  收藏  举报