由linear search引出的getchar()输入字符和数字问题
由linear search引出的getchar()输入字符和数字问题
@C—language
起因:在考研之际,重新拾起快忘光了的C语言,大一的时候没有认真学习,现在还真的发现好多以前遗漏了的问题
主要内容:C语言的获取字符输入方法getchar(),以及如何读取int型变量
操作系统:windows
编译器:Cygwin的gnu环境
getchar()的用途
初始代码(linearSearch.c)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
int linearSearch(int [], int, int);
int main()
{
int nums[LEN] = {5, 10, 22, 32, 45, 67, 73, 98, 99, 101};
int desiredElem, location;
printf("Input the desired element, please: \n");
desiredElem = getchar();
location = linearSearch(nums, LEN, desiredElem);
if(location != -1){
printf("The desired element was found at index location %d.\n", location);
}else{
printf("The desired element was not found in the list. the location is %d.\n", location);
}
return 0;
}
// this function returns the location of key in the list
// a -1 is returned if the value is not found
int linearSearch(int list[], int size, int key)
{
int i;
printf("key = %d.\n", key);
for(i=0; i<size; i++){
if(list[i] == key){
return i;
}
}
return -1;
}
乍看感觉这段代码还像模像样的,但是在Cygwin中编译结果:1
2
3
4
5$ ./cygwinTest.exe
Input the desired element, please:
10
key = 49.
The desired element was not found in the list. the location is -1.
可以轻易发现是getchar()方法出了问题,下面看看getchar():
- 名称:getchar()
- 定义:用在文件读取中,读取文件时要区分文件中有效数据与输入结束符的问题,C语言解决方法是,在没有输入时,getchar函数将返回一个特殊值,这个特殊值与任何实际字符都不同,成为“EOF”(文件结束符),为int类型
- 返回值类型:int类型(对应字符的ASCII值)
- 一般用法:
1
2
3
4读一个字符
while(该字符不是EOF)
输出刚读入的字符
读下一个字符
转换为C:1
2
3
4
5
6
7
8
9
10
11
/* copy input to output; 1st version */
main()
{
int c;
c = getchar();
while(c != EOF){
putchar(c);
c = getchar();
}
}
可以找到问题的原因了:因为我们是要得到int型,但是getchar返回的是输入字符的ASCII码,所以就出错了,应该使用scanf函数:1
scanf("%d", &desiredElem);
编译结果如下:1
2
3
4
5$ ./cygwinTest.exe
Input the desired element, please:
22
key = 22.
The desired element was found at index location 2.
下面引出今天叙述的重点:C语言如何从键盘输入数据
scanf()
scanf == scan format,意思是格式化扫描,即从键盘获得用户输入
一般用法为:1
2
3int a, b;
scanf("%d", &a); //输入整数并赋值给变量a
scanf("%d", &b); //输入整数并赋值给变量b
scanf与printf非常相似:1
2scanf("%d %d", &a, &b); // 获取用户输入的两个整数,分别赋值给变量 a 和 b
printf("%d %d", a, b); // 将变量 a 和 b 的是在显示器上输出。
它们都有格式控制字符串,都有变量列表。不同的是,scanf的变量前要带一个&符号,称为“取地址符”,即获得变量在内存中的地址。
数据都是以二进制的形式保存在内存中的,字节(Byte)是最小的可操作单位。为了便于管理,我们给每个字节分配了一个编号,使用该字节时,只要知道编号就可以,就像每个学生都有学号,老师会随机抽取学号来让学生回答问题。字节的编号是有顺序的,从 0 开始,接下来是 1、2、3……
下图是 4G 内存中每个字节的编号(以十六进制表示):

这个编号,就叫做地址(Address)。int a; 会在内存中分配四个字节的空间,我们将第一个字节的地址称为变量 a 的地址,也就是&a的值。对于的整数、浮点数、字符,都要使用 & 获取它们的地址,scanf 会根据地址把读取到的数据写入内存。
不妨将变量地址数出来看看:1
2
3
4
5
6
7
8
9
10
int main()
{
int a='F';
int b=12;
int c=452;
printf("&a=%#x, &b=%#x, &c=%#x\n", &a, &b, &c);
return 0;
}
输出结果:1
2$ ./scanfAddress.exe
&a=0xffffcbfc, &b=0xffffcbf8, &c=0xffffcbf4

注意:这里看到的地址是虚拟地址,并不等于它在物理内存中的地址。虚拟地址是现代计算机因内存管理的需要才提出的概念。
以上。