1 变量使用常用错误汇总
1.1 问题
在我们使用变量的过程中,会遇到一些问题,在此将这些问题进行汇总,在今后使用的过程中,不出错。即使出现错误也可以很快地找到问题所在。
1.2 方案
变量在使用的过程中,常见问题总结为如下几点:
1) 使用未经声明的变量。
2) 使用不符合C标识符命名规则的变量。
3) 使用未经初始化的变量。
1.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:使用未经声明的变量
C语言语法规定,变量使用之前必须声明,否则会有编译错误。大多数的时候我们都记得这个规范,但是还是会出现变量未经声明就使用的情况,请看如下代码:
- #include <stdio.h>
- int main()
- {
- a = 0;//编译错误,变量a没有声明
- int score = 0;
- scord = 100;//编译错误,变量scord是本应是变量score,拼写错误
- printf(“%d”, score);
- }
编译上述代码,会发现在代码a = 0;处和代码scord = 100;处会出现编译错误。出现编译错误的原因是变量a和变量scord没有被声明。变量的声明包含两点:变量的类型和变量的名称。a变量是没有变量的类型。scord变量也是因为没有变量的类型,但是查看代码scord = 100;的上下行的代码会发现声明了score变量,分析这三行代码,scord = 100 行出现编译错误的原因是变量没有被声明,没有声明的原因是变量score拼写成了scord。
步骤二:使用不符合C标识符命名规则的变量
C语言中的变量命名必须符合C语言标识符的规则:
1) 由字母、数字、下划线‘_‘ 组成。
2) 首字符不能以数字开头。
3) 大小写敏感,命名变量时需要注意。
4) 不能使用C语言的关键字(一些C语言规定好的,有特殊含义的字符),如:int、float、if、for、break等。
下面的代码体现了C语言变量的命名规则:
- #include <stdio.h>
- int main()
- {
- int 123go = 100;//编译错误,不能以数字开头
- int 成绩 = 60;//编译错误,不能是汉字
- int break = 200;//编译错误,break是C语言的关键字
- int score = 80;
- printf(“%d”, Score);//编译错误,C语言大小写敏感,Score变量没有声明
- }
上述代码中,分别有如下错误:
1) 变量“123go”不符合C语言标识符的命名规范,原因是变量名不能以数字开头。
2) 变量“成绩”在C语言中是非法的,原因是C语言不允许是用汉字作为变量名。
3) 变量“break”处会出现编译错误,原因是break是C语言的关键字,关键字不能作为变量名使用。
4) 由于C语言标识符的大小写是敏感的,所以printf(“%d”,Score)出现编译错误,因为在上一行int score=80;中score的第一个字母s是小写,printf(“%d”,Score)中Score的第一个字母S是大写,所以它们是两个不同的变量,这样就造成Score变量在使用前未声明的编译错误。
另外,C语言的变量名的定义应该做到“见名知意”;同时,C语言编程规范要求:变量名的命名需要采用“驼峰命名法”,即如果变量的名字有多个单词组成,除第一个单词外,其他所有单词的首字母大写,其余的字母小写,例如:salary、empNo、studentName。
步骤三:使用未经初始化的变量
C语言规定变量在使用之前应该初始化,即应该给该变量赋予特定的值,如果不进行初始化,该变量的值将是垃圾值。如下面代码所示:
- #include <stdio.h>
- int main()
- {
- int a, b = 10;
- int c = a + b;//变量a没有被初始化,a当中的值将是垃圾值
- printf(“%d”, c);
- }
在上述代码中,代码行int c = a + b;处会出现错误,因为此行代码使用到了变量a,但该变量却没有被初始化,这样a当中将是随机值,一个随机值加变量b的结果也将是一个随机值,随机值的计算结果是没有意义的。
另外,有些语句结构(如if、for等)需要条件满足时才会执行。C语言的编译器不认为在这些语句块儿中的赋值语句可以实现初始化操作,代码如下所示:
- #include <stdio.h>
- int main()
- {
- int sum;
- int a = 20;
- int b = 10;
- if (a > 0)
- {
- sum = 0;//当a大于0的时候,该语句才会被执行
- sum = a + b;
- }
- printf(“%d”,sum);
- }
上述代码中,语句printf处可能会出现错误,因为对于变量sum,如果a的值小于0,那么sum = 0;这句话将不会被执行,此时执行printf时,sum还将是垃圾值。
1.4 完整代码
本案例是总结性的知识,因此,没有完整代码呈现。
2 从键盘上输入两个数,分别求出和、差、积、商
2.1 问题
本案例需要使用交互的方式计算两个数的和差积商:用户从控制台输入两个数,由程序计算这两个数的和差积商。程序交互过程如图-1所示:
图-1
2.2 方案
根据老师课上的讲解和本文档中的步骤,编写程序。
2.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:定义两个变量
首先定义两个变量,用于存储从控制台输入的两个数据,代码如下:
- #include <stdio.h>
- int main(int argc, const char * argv[])
- {
- int number1;
- int number2;
- return 0;
- }
步骤二:从控制台输入两个数
首先,使用printf函数输出一行提示,提示输入第一个数。
然后,使用scanf函数输入第一个数。
然后,再使用printf函数输出一行提示,提示输入第二个数。
最后,使用scanf函数输入第二个数。
代码如下:
- #include <stdio.h>
- int main(int argc, const char * argv[])
- {
- int number1;
- int number2;
- printf("请输入第一个数:");
- scanf("%d", &number1);
- printf("请输入第二个数:");
- scanf("%d", &number2);
- return 0;
- }
步骤三:计算输入的两个数的和
首先,定义一个变量sum,用于保存从控制台输入的两个数的和。
然后,输出两个数的和。
代码如下:
- #include <stdio.h>
- int main(int argc, const char * argv[])
- {
- int number1;
- int number2;
- printf("请输入第一个数:");
- scanf("%d", &number1);
- printf("请输入第二个数:");
- scanf("%d", &number2);
- int sum = number1 + number2;
- printf("两个数的和为:%d\n", sum);
- return 0;
- }
步骤四:计算输入的两个数的和
首先,定义一个变量difference,用于保存从控制台输入的两个数的差。
然后,输出两个数的差。
代码如下:
- #include <stdio.h>
- int main(int argc, const char * argv[])
- {
- int number1;
- int number2;
- printf("请输入第一个数:");
- scanf("%d", &number1);
- printf("请输入第二个数:");
- scanf("%d", &number2);
- int sum = number1 + number2;
- printf("两个数的和为:%d\n", sum);
- int difference = number1 - number2;
- printf("两个数的差为:%d\n", difference);
- return 0;
- }
步骤五:计算输入的两个数的积
首先,定义一个变量product,用于保存从控制台输入的两个数的积。
然后,输出两个数的积。
代码如下:
- #include <stdio.h>
- int main(int argc, const char * argv[])
- {
- int number1;
- int number2;
- printf("请输入第一个数:");
- scanf("%d", &number1);
- printf("请输入第二个数:");
- scanf("%d", &number2);
- int sum = number1 + number2;
- printf("两个数的和为:%d\n", sum);
- int difference = number1 - number2;
- printf("两个数的差为:%d\n", difference);
- int product = number1 * number2;
- printf("两个数的积为:%d\n", product);
- return 0;
- }
步骤六:计算输入的两个数的商
首先,定义一个变量business,用于保存从控制台输入的两个数的商。
然后,输出两个数的商。
代码如下:
- #include <stdio.h>
- int main(int argc, const char * argv[])
- {
- int number1;
- int number2;
- printf("请输入第一个数:");
- scanf("%d", &number1);
- printf("请输入第二个数:");
- scanf("%d", &number2);
- int sum = number1 + number2;
- printf("两个数的和为:%d\n", sum);
- int difference = number1 - number2;
- printf("两个数的差为:%d\n", difference);
- int product = number1 * number2;
- printf("两个数的积为:%d\n", product);
- int business = number1 / number2;
- printf("两个数的商为:%d\n", business);
- return 0;
- }
2.4 完整代码
本案例的完整代码如下所示:
- #include <stdio.h>
- int main(int argc, const char * argv[])
- {
- int number1;
- int number2;
- printf("请输入第一个数:");
- scanf("%d", &number1);
- printf("请输入第二个数:");
- scanf("%d", &number2);
- int sum = number1 + number2;
- printf("两个数的和为:%d\n", sum);
- int difference = number1 - number2;
- printf("两个数的差为:%d\n", difference);
- int product = number1 * number2;
- printf("两个数的积为:%d\n", product);
- int business = number1 / number2;
- printf("两个数的商为:%d\n", business);
- return 0;
- }
3 整数类型(int、long)使用常见问题汇总
3.1 问题
在我们使用整数类型的过程中,会遇到一些问题,在此将这些问题进行汇总,在今后使用的过程中,不出错。即使出现错误也可以很快找到问题所在。
3.2 方案
整数类型在使用的过程中,常见的问题有以下几点:
1) 整数直接超出范围
2) 关于整数的除法:两个整数相除,会舍弃小数的部分,结果也是整数。
3) 整数运算的溢出:两个整数进行运算时,其结果可能会超出整数的范围而溢出。
4) 表示long字面值,需要以L或l结尾。
3.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:整数字面值超出了整数的范围
int是最常用的整数类型。一个int类型的变量占用4个字节(32位),最大表示范围为:-231到231-1,即-2147483648~2147483647。
整数字面值,即直接写出的整数,整数的字面值的类型默认为int类型,如果直接写出的整数超过了int的表达范围将会出现错误。请看如下代码:
- int i = 10000000000;
- printf(“%d”, i);
以上代码,10000000000不属于int类型的字面值,赋值给变量i后,printf输出的i值,将不是10000000000。
步骤二:关于整数的除法
在C语言中,两个整数相除,会舍弃小数部分。请看如下代码:
- int c = 5 / 3;
- printf(“%d”, c);
在上述代码中,运行后,c的值为1。说明两个整数相除,舍弃了小数部分,只保留了整数部分。
步骤三:整数运算的溢出
两个整数进行运算时,其结果可能会超过整数的范围而溢出,请看如下代码:
- int a = 2147483647;
- int b = -2147483648;
- a = a + 1;
- b = b – 1;
- printf(“a = %d”, a);
- printf(“b = %d”, b);
上述代码运行后的输出结果为:
- a = -2147483648
- b = 2147483647
变量a最初的值为2147483647,是int类型的最大值,加1以后出现了溢出现象,a的值变成了int类型的最小值。而b变量最初值为-2147483648,是int类型的最小值,减1以后出现了溢出现象,b的值变成了int类型的最大值。这显然不符合加法和减法的规则,所以,在今后使用的时候要注意类似的问题。
步骤四:表示long字面值,需要以L或l结尾
在表示整数时,如果int类型的范围不够,可以使用long类型,一个long类型的变量占用8个字节(64位),最大表示的范围为:-263~263-1,即-9223372036854775808~9223372036854775807。当一个字面值超过了int类型的最大值时,那要用long类型来表示,需要以L或l结尾。请看以下代码:
- long a = 10000000000;
上述代码中,10000000000超过了int类型的最大值,直接赋值给long类型会出现溢出错误,需要在10000000000后面加上一个L。写成如下代码:
- long a = 10000000000L;
3.4 完整代码
本案例是总结性的知识,没有完成代码。
4 进行二、八、十六进制之间转换练习
4.1 问题
在C语言程序中,一般都使用十进制数据进行计算,这是因为C语言是高级语言,而高级语言是按照人的思维习惯编制程序的。但是我们都知道,计算机在运行的时候,只能采用二进制的方式,即只有0和1.这就需要我们能够在二进制数与十进制数之间进行转换,另外为了方便二进制数的计算,我们还要学习在二进制数与八进制数、十六进制数之间的转换。
4.2 方案
二进制数、八进制数、十进制数、十六进制数的表示方式如表-1:
由表-1可以看出,二进制数中只有0和1两个数字符号,而数字2使用0010来表示的,数字3使用0011来表示的,依此类推;八进制数中有0、1、2、3、4、5、6、7八个数字符号,数字8则使用10来表示,数字9使用11来表示,依此类推;十六进制数中有0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F十六个数字符号,数字16则使用10来表示,数字17使用11来表示。
4.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:十进制数与二进制数相互转换
1) 从十进制到二进制的转换采用辗转相除的方法:
例如:十进制数34转换成二进制数的过程如下
34 / 2 = 17 …… 0
17 / 2 = 8 …… 1
8 / 2 = 4 …… 0
4 / 2 = 2 …… 0
2 / 2 = 1 …… 0
1 / 2 = 0 …… 1
将余数从下向上读出的二进制数即为转换后的二进制数。
即十进制数34转换成的二进制数为 100010。
2) 从二进制到十进制的转换采用按权相加的方法:
例如:二进制数100010转换成十进制数的过程如下:
首先将二进制数100010从最后一位开始算,依次为0、1、2、… 位。
第0位 0乘以2的0次方 = 0
第1位 1乘以2的1次方 = 2
第2位 0乘以2的2次方 = 0
第3位 0乘以2的3次方 = 0
第4位 0乘以2的4次方 = 0
第5位 1乘以2的5次方 = 32
然后把结果加起来 0 + 2 + 0 + 0 + 0 + 32 = 34
即二进制数100010转换成的十进制数为34。
步骤二:十进制数与八进制数、十六进制数相互转换
1) 从十进制到八进制的转换也采用辗转相除的方法:
例如:十进制数134转换成八进制数的过程如下:
134 / 8 = 16 …… 6
16 / 8 = 2 …… 0
2 / 8 = 0 …… 2
将余数从下向上读出的八进制数即为转换后的八进制数。
即十进制数134转换成的八进制数为 206。
2) 从八进制到十进制的转换采用按权相加的方法:
例如:八进制数206转换成十进制数的过程如下:
首先将八进制数206从最后一位开始算,依次为0、1、2、… 位。
第0位 6乘以8的0次方 = 6
第1位 0乘以8的1次方 = 0
第2位 2乘以8的2次方 = 128
然后把结果加起来 6 + 0 + 128 = 134。
即八进制数206转换成的十进制数为134。
3) 从十进制到十六进制的转换也采用辗转相除的方法:
例如:十进制数134转换成十六进制数的过程如下:
134 / 16 = 8 …… 6
8 / 16 = 0 …… 8
将余数从下向上读出的十六进制数即为转换后的十六进制数。
即十进制数134转换成的十六进制数为 86。
4) 从十六进制到十进制的转换采用按权相加的方法:
例如:十六进制数86转换成十进制数的过程如下:
首先将十六进制数86从最后一位开始算,依次为0、1、2、… 位。
第0位 6乘以16的0次方 = 6
第1位 8乘以16的1次方 = 128
然后把结果加起来 6 + 128 = 134。
即十六进制数86转换成的十进制数为134。
步骤三:二进制数转换成八进制数、十六进制数
1) 二进制转换成八进制,从最后一位开始每三位二进制数相当于一个八进制数,最前面不足三位的添0。
例如:二进制数100010,从最后一位向左每数三位一分,这样前面的二进制数被分割成100 010,将100转换成八进制数为4,将010转换成八进制数为2,这样八进制数就是42。
2) 二进制转换成十六进制,从最后一位开始每四位二进制数相当于一个十六进制数,最前面不足三位的添0。
例如:二进制数100010,从最后一位向左每数四位一分,这样前面的二进制数被分割成0010 0010,将左边的0010转换成十六进制数为2,将右边的0010转换成十六进制数为2,这样十六进制数就是22。
4.4 完整代码
本案例是知识的讲解,因此,没有完整代码呈现。
5 char类型使用常见问题汇总
5.1 问题
在我们使用char类型的过程中,会遇到一些问题,在此将这些问题进行汇总,在今后使用的过程中,不出错。即使出现错误也可以很快找到问题所在。
5.2 方案
char类型在使用的过程中,常见的问题有以下几点:
1) 字符类型不可以存储中文。
2) char类型的值可以作为整数类型直接使用。
3) 表示char的字面值,需要用单引号将字符引起来。
5.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:字符类型不可以存储中文
char类型事实上是一个8位无符号整数,这个值是对应字符的编码,C语言的字符类型采用ASCII码字符集编码。其中没有中文。以下代码是错误的:
- char c = ‘中’;
步骤二:整数类型和char类型的关系
char类型的值可以直接作为整数类型的值来使用,字符类型事实上是一个8位的整数,表示范围是-128~127。请看如下代码:
- char ch = ‘a’;
- printf(“%c\n”, ch);
- printf(“%d\n”, ch);
上述代码的输出结果为:
- a
- 97
char类型的变量用占位符%d输出时,将输出成整数。
另外,如果把-128~127范围内的一个int整数赋给char类型变量,系统会自动把这个int类型整数当做char类型来处理。请看如下代码:
- char ch = 97;
- printf(“%c\n”, ch);
上述代码的输出结果为a。这说明系统自动把整数类型97当成char类型来处理,处理结果为a,即97为字母a的ASCII码。
步骤三:表示char的字面值,需要用单引号将字符引起来
在表示char类型的字面值时,需要用单引号将字符引起来。在引起来的时候,一次只能引一个字符,不能引多个字符。请看如下代码:
- char ch = ‘a’;
- printf(“%c\n”, ch);
- ch = ‘abcde’;
- printf(“%c\n”, ch);
上述代码的输出结果为:
- a
- e
第4行代码输出的不是abcde,也不是a,而是e的原因是当用单引号引起多个字符时,C语言将自动把前面的所有字符删除,只留下多个字符中的最后一个字符作为字面值赋值给变量,所以输出结果为e。
5.4 完整代码
本案例是总结性的知识,没有完成代码。
6 浮点类型(float、doule)使用常见问题汇总
6.1 问题
在我们使用浮点类型的过程中,会遇到一些问题,在此将这些问题进行汇总,在今后使用的过程中,不出错。即使出现错误也可以很快找到问题所在。
6.2 方案
浮点类型在使用的过程中,常见的问题有以下几点:
1) 浮点数的字面值为double类型。
2) 浮点数存在舍入误差问题。
6.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:浮点数的字面值为double类型
浮点数,就是小数,包括:float和double两种类型。默认的浮点字面值为double类型,如果需要表示float类型的字面值,需要加’f’或’F’后缀。请看如下代码:
- float f = 3.14f;
- double d = 3.14;
以上代码中,3.14f是float类型的字面值,3.14是double 类型的字面值。
步骤二:浮点数存在舍入误差问题
由于浮点数内部用二进制的方式来表示十进制,会存在舍入误差。二进制系统中无法精确地表示1/10,就好像十进制系统中无法精确表示1/3一样。对于一些要求精确运算的场合会导致代码的缺陷。请看如下代码:
- double money = 3.0;
- double price = 2.9;
- printf("change = %.17lf\n", money - price);
上述代码的输出结果为:
- change = 0.10000000000000009
查看上述结果,并不是我们想象的0.10000000…。后面会出现随机值,这个随机值是会参与运算的。当需要精确的运算时,可采用(money – price) < 1E-6的形式。
6.4 完整代码
本案例是总结性的知识,没有完成代码。
7 使用sizeof获取部分类型的变量内存空间大小
7.1 问题
在C语言中所有的变量都有自己的数据类型,不同数据类型的变量所占的内存空间也不相同。每种数据类型的变量所占的内存空间大小可以通过sizeof求取。
7.2 方案
各种数据类型的变量所占的内存空间见表-2:
7.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:定义变量
定义各种数据类型的变量,代码如下所示:
- #include <stdio.h>
- int main()
- {
- int i;
- short int si;
- long int li;
- unsigned int ui;
- unsigned short int usi;
- unsigned long int uli;
- float f;
- double d;
- long double ld;
- char c;
- unsigned char uc;
- return 0;
- }
步骤二:使用sizeof求取所占字节数
使用printf函数输出数据,代码如下所示:
- #include <stdio.h>
- int main()
- {
- int i;
- short int si;
- long int li;
- unsigned int ui;
- unsigned short int usi;
- unsigned long int uli;
- float f;
- double d;
- long double ld;
- char c;
- unsigned char uc;
- printf("int 型所占的字节数为:%ld\n", sizeof(i));
- printf("short int 型所占的字节数为:%ld\n", sizeof(si));
- printf("long int 型所占的字节数为:%ld\n", sizeof(li));
- printf("unsigned int 型所占的字节数为:%ld\n", sizeof(ui));
- printf("unsigned short int 型所占的字节数为:%ld\n", sizeof(usi));
- printf("unsigned long int 型所占的字节数为:%ld\n", sizeof(uli));
- printf("float 型所占的字节数为:%ld\n", sizeof(f));
- printf("double 型所占的字节数为:%ld\n", sizeof(d));
- printf("long double 型所占的字节数为:%ld\n", sizeof(ld));
- printf("char 型所占的字节数为:%ld\n", sizeof(c));
- printf("unsigned char 型所占的字节数为:%ld\n", sizeof(uc));
- return 0;
- }
注意:上述代码中,sizeof所对应的占位符是%ld。
7.4 完整代码
本案例的完整代码如下所示:
- #include <stdio.h>
- int main()
- {
- int i;
- short int si;
- long int li;
- unsigned int ui;
- unsigned short int usi;
- unsigned long int uli;
- float f;
- double d;
- long double ld;
- char c;
- unsigned char uc;
- printf("int 型所占的字节数为:%ld\n", sizeof(i));
- printf("short int 型所占的字节数为:%ld\n", sizeof(si));
- printf("long int 型所占的字节数为:%ld\n", sizeof(li));
- printf("unsigned int 型所占的字节数为:%ld\n", sizeof(ui));
- printf("unsigned short int 型所占的字节数为:%ld\n", sizeof(usi));
- printf("unsigned long int 型所占的字节数为:%ld\n", sizeof(uli));
- printf("float 型所占的字节数为:%ld\n", sizeof(f));
- printf("double 型所占的字节数为:%ld\n", sizeof(d));
- printf("long double 型所占的字节数为:%ld\n", sizeof(ld));
- printf("char 型所占的字节数为:%ld\n", sizeof(c));
- printf("unsigned char 型所占的字节数为:%ld\n", sizeof(uc));
- return 0;
- }
8 键盘输入一个秒数,输出XX小时XX分钟XX秒
8.1 问题
在本案例需要使用交互的方式将用户输入的秒数转换成时分秒:用户从控制台输入秒数,由程序计算这个数转换成时分秒的表示形式。程序交互过程如图-2所示:
图-2
8.2 方案
首先,计算小时数,将一个秒数转换成小时可使用 秒数 / 3600 = 小时数,因为1小时等于60分,1分钟等于60秒,所以,1小时等于60 * 60 = 3600秒。
然后,计算分钟数,第一步先将前面计算出的小时数所含的秒数从总秒数中减掉,第二步可使用 剩余的秒数 / 60 = 分钟数。
最后,计算秒数,秒数 = 总秒数 - 小时数 * 3600 - 分钟数 * 60。
8.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:定义变量
用变量secondNumber保存总秒数。
用变量hour保存转换后的小时数。
用变量minute保存转换后的分钟数。
用变量second保存转换后的秒数。
代码如下:
- #include <stdio.h>
- int main()
- {
- return 0;
- }
步骤二:从控制台输入总秒数
- #include <stdio.h>
- int main()
- {
- int secondNumber;//总秒数
- int hour;//小时数
- int minute;//分钟数
- int second;//秒数
- return 0;
- }
步骤三:转换并输出时分秒
转换公式为:
小时数 = 总秒数 / 3600。
分钟数 = (总秒数 - 小时数 * 3600) / 60。
秒数 = 总秒数 - 小时数 * 3600 - 分钟数 * 60。
- #include <stdio.h>
- int main()
- {
- int secondNumber;//总秒数
- int hour;//小时数
- int minute;//分钟数
- int second;//秒数
- printf("请输入一个秒数:");
- scanf("%d", &secondNumber);
- return 0;
- }
8.4 完整代码
本案例的完整代码如下所示:
- #include <stdio.h>
- int main()
- {
- int secondNumber;//总秒数
- int hour;//小时数
- int minute;//分钟数
- int second;//秒数
- printf("请输入一个秒数:");
- scanf("%d", &secondNumber);
- hour = secondNumber / 3600;
- minute = (secondNumber - hour * 3600) / 60;
- second = secondNumber - hour *3600 - minute * 60;
- printf("%02d:%02d:%02d\n", hour, minute, second);
- return 0;
- }