在C语言里,我们经常用scanf作为输入语句,用printf输出。那么关于输入和输出,你到底了解多少呢?
一、关于“&”
首先我们来看一段程序:
#include <stdio.h>
int main()
{
int num;
printf("Please input num = ");
scanf("%d",num);
printf("num = %d\n",num);
return 0;
}
运行程序,当我们输入 num = 5 时,输出为多少呢?输出结果如下:
Please input num = 5
段错误
我们可以看到,这个时候出现了“段错误”,那么什么是段错误呢?简单来说,段错误就是内存错误。
在我们上述程序中,有一句“scanf("%d",num)”,问题便出在这里。
我们举一个简单的例子,假如在一所学校里,有20个人叫张三,我到了这个学校,说我要找张三,那么我能准确地找到我想找的那个张三么?当然不能。为什么呢?因为这个学校里有20个人叫张三,我只说了我要找的人叫张三,那么我要找的到底是这20个人中的哪一个呢?所以如果我想找到张三,我需要说我要找某某年级某某班的张三,给一个准确的定位,这样我才可以准确地找到他。
那么在这里是一样的,num只是一个名字,如果我说我要输入一个数给num,系统又怎么知道我要输给的num在哪呢?所以这个时候我们要把num的地址加上去,这样才可以找到num在内存空间的地址,即只有名字是不行的,还要有地址。所以以后用scanf
时千万不要忘记加“&”。
二、关于输入字符之前加一个getchar函数
首先参考http://blog.csdn.net/newcong0123/article/details/51853458中提到过的问题,即在输入一个数字之后,略过了字符的输入,直接输入下一个数字的问题。下面我们来解释一下为什么会有这样的情况。
简单来说,就是scanf有一个缓冲区,我们通过scanf输入的数据先存放到缓冲区,然后再依次输出。
下面我们利用之前的程序分析一下:
#include <stdio.h>
int main()
{
int num1;
int num2;
char ch;
printf("Please input num1: ");
scanf("%d",&num1);
printf("Please input ch: ");
scanf("%c",&ch);
printf("Please input num2: ");
scanf("%d",&num2);
printf("%d %c %d\n",num1,ch,num2);
return 0;
}
当我们输入 num1 = 2 之后,2被放到了缓冲区,敲回车,这时,'\n'也被放到了缓冲区内,在分配时,便把2分给了num1,而把'\n'分给了ch,ch已经被分配了值,所以再输入时便直接略过了ch而直接输num2的值。
所以在获得一个数据后,再获得下一个数据而不让输入时,可以用getchar。
三、三种方法输入、输出数组a[3]
1. &a[i]
#include <stdio.h>
int main()
{
int i;
int a[3];
for (i = 0; i < 3; i++)
{
printf("Please input a[%d] = ",i);
scanf("%d",&a[i]);
}
for (i = 0; i < 3; i++)
{
printf("a[%d] = %d\n",i,a[i]);
}
return 0;
}
运行结果:
Please input a[0] = 1
Please input a[1] = 2
Please input a[2] = 3
a[0] = 1
a[1] = 2
a[2] = 3
2. a + i
#include <stdio.h>
int main()
{
int i;
int a[3];
for (i = 0; i < 3; i++)
{
printf("Please input a[%d] = ",i);
scanf("%d",a + i);
}
for (i = 0; i < 3; i++)
{
printf("a[%d] = %d\n",i,*(a + i));
}
return 0;
}
运行结果:
Please input a[0] = 1
Please input a[1] = 2
Please input a[2] = 3
a[0] = 1
a[1] = 2
a[2] = 3
在这里需要注意的是,用a++是不可以的,见如下代码:
#include <stdio.h>
int main()
{
int i;
int a[3];
for (i = 0; i < 3; i++)
{
printf("Please input a[%d] = ",i);
scanf("%d",a++);
}
for (i = 0; i < 3; i++)
{
printf("a[%d] = %d\n",i,a[i]);
}
return 0;
}
运行结果如下:
在函数 ‘main’ 中:
13: 错误:自增运算中的左值无效
因为在这里a是数组名,即数组首元素的地址,在这里是常量,所以不能自加。
3. p++
#include <stdio.h>
int main()
{
int i;
int a[3];
int *p = a; // p = &a[0]; 把a里的地址给p
for (i = 0; i < 3; i++)
{
printf("Please input a[%d] = ",i);
scanf("%d",p++);
}
p = a;
for (i = 0; i < 3; i++)
{
printf("a[%d] = %d\n",i,*(p + i));
}
return 0;
}
运行结果:
Please input a[0] = 1
Please input a[1] = 2
Please input a[2] = 3
a[0] = 1
a[1] = 2
a[2] = 3
四、三种方法输入、输出字符数组src[100]
1. scanf
#include <stdio.h>
#define MAX 10
int main()
{
char src[MAX];
printf("Please input string : ");
scanf("%s",src);
printf("The string is %s.\n",src);
return 0;
}
如果输入hello,输出结果为:
Please input string : hello
The string is hello.
如果输入hello world,输出结果为:
Please input string : hello world
The string is hello.
如果输入helloworld,输出结果为:
Please input string : helloworld
The string is helloworld.
段错误
如果输入hihihihihihihihihihi,输出结果为:
Please input string : hihihihihihihihihihi
The string is hihihihihihihihihihi.
段错误
从上面我们运行时输入不同的字符串,输出的结果也不同,我们可以看到:
①当我们输入的字符串有空格时,输出时只输出空格之前的字符串。
②当我们输入的字符串超出了所定义的字符数组的长度,会报错,即段错误,但不影响输出结果。即无法解决越界问题。
2. gets
#include <stdio.h>
#define MAX 10
int main()
{
char src[MAX];
printf("Please input string : ");
gets(src);
printf("The string is %s.\n",src);
return 0;
}
如果输入hello,输出结果为:
Please input string : hello
The string is hello.
如果输入helloworld,输出结果为:
Please input string : helloworld
The string is helloworld.
如果输入hello world,输出结果为:
Please input string : hello world
The string is hello world.
段错误
如果输入hihihihihihihihihihi,输出结果为:
Please input string : hihihihihihihihihihi
The string is hihihihihihihihihihi.
段错误
从上述结果我们可以看出:
①gets输入字符串不受空格影响,仍然可以输出空格后的字符串。
②当我们输入的字符串超出了长度,同样会报段错误,但仍然输出相应的字符串。同样无法解决越界问题。
3. getchar()
#include <stdio.h>
#define MAX 10
int main()
{
char ch;
char src[MAX];
int i = 0;
printf("Please input string : ");
while ((ch = getchar()) != '\n')
{
src[i] = ch;
i++;
}
src[i] = '\0';
printf("The string is %s.\n",src);
return 0;
}
如果输入hello world,输出结果为:
Please input string : hello world
The string is hello worl
.
可以看出:
①gerchar也不受空格影响。
②输入的字符串超出长度时,会把输出的字符串的长度控制在我们定义的范围内,即可以解决越界问题。
③需要一个字符一个字符获取,所以获取的运行效率低。
控制越界,越界即报错。代码如下:
#include <stdio.h>
#define MAX 10
int main()
{
char ch;
char src[MAX];
int i = 0;
printf("Please input string : ");
while ((ch = getchar()) != '\n')
{
src[i] = ch;
i++;
if (i == 9)
{
printf("Too long!\n");
break;
}
}
src[i] = '\0';
printf("The string is %s.\n",src);
return 0;
}
如果输入helloworld,输出结果为:
Please input string : helloworld
Too long!
The string is helloworl.
如果输入hihihihihihihihihihi,输出结果为:
Please input string : hihihihihihihihihihi
Too long!
The string is hihihihih.
如果输入hello world,输出结果为:
Please input string : hello world
Too long!
The string is hello wor.
五、关于printf
如果你认为你对printf足够了解,那么看一下下面这段程序:
#include <stdio.h>
int main()
{
printf("Hello world!");
while (1) ;
return 0;
}
运行之后的结果是什么呢?是“Hello world!”么?当然不是。当我们运行了之后,会发现什么都不打印,并且陷入死循环。可能有人要问了,为什么不打印“Hello world!”呢?这便是我要给大家介绍的printf的一个特点。
printf是一个行缓冲函数,并且printf与scanf使用同一个缓冲区。先写到缓冲区,当满足一定的条件之后,才会将缓冲区的内容输出。而这里需要满足的一定条件如下:
①缓冲区满
②写入的字符里有'\n'
③手动刷新缓冲区
④调用scanf,需要从缓冲区读取数据
⑤程序退出
针对④,printf与scanf使用同一个缓冲区,当使用scanf时,会吧printf在缓冲区的数据清出来,于是可以输出。针对⑤,在程序退出时,会把缓冲区打扫干净,同样会清缓冲区,在清缓冲区的过程中会输出。
所以希望我们大家在使用printf时,养成加'\n'的好习惯,这样才不会出现一些本不应该出现的错误。
以上为博主的学习笔记,如有错误,望大家指出,O(∩_∩)O谢谢观看。