- 1、什么是算术运算?什么是关系运算?什么是逻辑运算?
- 2、C语言中如何表示“真”和“假”?系统如何判断一个量的“真”和“假”?
- 3、写出下面各逻辑表达式的值。设
a=3,b=4,c=5 - 4、有 3 个整数a,b,c,由键盘输入,输出其中最大的数
- 11、输入4个整数,要求按由小到大的顺序输出
- 5、从键盘输入一个小于 1000 的正数,要求输出它的平方根(如平方根不是整数,则输出其整数部分)。要求在输入数据后先对其进行检查是否为小于 1000 的正数。若不是,则要求重新输入
- 6、有一个分段函数如下,写程序,输入
x的值,输出相应y得值。 - 7、有一函数如下:有人分别编写了以下两个程序,请分析它们是否能实现题目要求。不要急于上机运行程序,先分析上面两个程序的逻辑,画出它们的流程图,分析它们的运行情况。然后上机运行程序,观察并分析结果。
- 8、给出一百分制成绩,要求输出成绩等级’A’、’B’、’C’、’D’、’E’。90分以上为’A’,80~89分为B’,70~70分为’C’,60~69分为’D’,60分以下为’E’。
- 9、给一个不多于5位的正整数,要求:
- 10、企业发放的奖金根据利润提成
- 12、有4个圆塔,圆心分别为(2,2),(-2,2),(-2,-2),(2,-2),圆半径为1
1、什么是算术运算?什么是关系运算?什么是逻辑运算?
解:略。
2、C语言中如何表示“真”和“假”?系统如何判断一个量的“真”和“假”?
- 对于逻辑表达式,若其值为“真”,则以
1表示,若其值为“假”,则以0表示。 - 但是在判断一个逻辑量的值时,系统会以
0作为“假”,以非0作为“真”。例如3 && 5的值为“真”,系统给出3 && 5的值为1。3、写出下面各逻辑表达式的值。设
a=3,b=4,c=5
a + b > c && b == c:0- 设
k = a + b = 7则表达式为k > 5 && b == c可知左侧关系表达式7 > 5成立,则表达式为1 && b == c - 由于
b != c,因此右侧关系表达式返回值为0,则整个表达式1 && 0 = 0
- 设
a || b + c && b - c:1- 最先看到
||,由于逻辑量a = 3是真,因此||短路运算直接返回1
- 最先看到
!(a > b) && !c || 1:1!是右结合性继续向后看,但是遇到第二个操作符(优先级比!则先计算括号内的内容,即(a > b)返回值为0。!0返回1,因此整个表达式为1 && !c || 1- 遇到
!c返回0,由于&&优先级高于||,因此先计算&&部分即(1 && 0) || 1得0 || 1返回1
!(x = a) && (y = b) && 0:0!是右结合性继续向后看,但是遇到第二个操作符(优先级比!则先计算括号内的内容,即(x = a)赋值表达式给x = 3赋值成功并返回3。- 此时表达式为
!3 && (y = b) && 0,则!3返回0,则有0 && (y = b) && 0直接短路&&后面表达式内容而返回0
!(a + b) + c - 1 && b + c / 2:1!是右结合性继续向后看,但是遇到第二个操作符(优先级比!则先计算括号内的内容,即(a + b)返回值为7,此时表达式为!7 + c - 1 && b + c / 2→0 + 5 - 1 && b + c / 2- 算数运算表达式高于逻辑表达式:先计算
&&左侧算术表达式结果即4 && b + c / 2,左侧算术表达式返回4逻辑量为真 - 继续右侧算术表达式
4 && b + c / 2:由于+二元运算符遇到/,先计算c / 2 = 2再进行b + 2返回7。因此整个表达式为1 && 7返回1
4、有 3 个整数a,b,c,由键盘输入,输出其中最大的数
解题思路:3 个中挑出最大的一共需要比较 2 次,即在 n 名选手中挑出最牛逼的需要进行 n-1 轮 PK。原理就是打擂台,首先自告奋勇第一轮两个人上台,然后胜者留下继续打剩下 n - 2 ,以此类推。
- 流程图:
- N-S 图见图:

- C语言:
编译运行: :::success b12@PC:~/chapter4$ gcc -Wall ./src/threeMax.c -o ./bin/threeMax#include <stdio.h>int main () {int a, b, c;printf("Please input three digits: ");scanf("%d %d %d", &a, &b, &c);if (a > b) { // a 和 b 比较大小,如果 a 大if (a > c) { // 如果还是 a 大printf("Max: %d\n", a);} else { // 否则 c 最大printf("Max: %d\n", c);}} else { // a 和 b 比较大小,如果 b 大if (b > c) { // 如果还是 b 大printf("Max: %d\n", b);} else { // 否则 c 最大printf("Max: %d\n", c);}}return 0;}// 2.使用第三方变量(看起来了简洁很多)#include <stdio.h>int main () {int a, b, c;printf("Please input three digits: ");scanf("%d %d %d", &a, &b, &c);int tmp = a > b ? a : b; // a,b最大者放入 tmptmp = tmp > c ? tmp : c; // tmp,c最大者放入 tmpprintf("Max: %d\n", tmp);return 0;}
b12@PC:~/chapter4$ ./bin/threeMax
Please input three digits: 12 34 9
Max: 34 :::11、输入4个整数,要求按由小到大的顺序输出
解题思路:本题可以转换为上面的形式。即先在4个中找到最大的,然后剔除最大者就变成上一个问题。
- 先在
4人中找出最大者,即4人 PK 找到一直站台舞台的上人就是最大的。其它3人进入待命区。 - 然后再在待命区中选一个复活:即
3人 PK 找到一直站台舞台的上人就是次大的。其它2人进入待命区。 - 然后再在待命区中选一个复活:即
3人 PK 找到一直站台舞台的上人就是次次大的。其它1人进入待命区。 - 最后这个在待命区就是最小的了。
综上一共需要 3 趟比较,但是一趟要进行 PK x-1 轮选出此趟最大者,其中 x 就是参入 PK 的总人数。
#include <stdio.h>int main () {int tmp, a, b, c, d;printf("Please input four numbers:");scanf ("%d,%d,%d,%d", &a, &b, &c, &d);// 1.在 a,b,c,d 中找最大值并放到 a 中if (a < b) { // a是a,b 中最大tmp = a;a = b;b = tmp;}if (a < c) { // a是a,b,c 中最大tmp = a;a = c;c = tmp;}if (a < d) { // a是a,b,c,d 中最大tmp = a;a = d;d = tmp;}// 2.在 b,c,d 中找到最大并放在 bif (b < c) { // b是 b,c 中最大tmp = b;b = c;c = tmp;}if (b < d) { // b是 b,c,d 中最大tmp = b;b = d;d = tmp;}// 3.在 c,d 中找到最大并放在 cif (c < d) { // b是 b,c,d 中最大tmp = c;c = d;d = tmp;}printf("Decending order: %d %d %d %d\n", a, b, c, d);return 0;}
编译运行:
:::success
b12@PC:~/chapter4$ gcc -Wall ./src/fourSort.c -o ./bin/fourSort
b12@PC:~/chapter4$ ./bin/fourSort
Please input four numbers:6,8,1,4
Decending order: 8 6 4 1
b12@PC:~/chapter4$ ./bin/fourSort
Please input four numbers:6,0,99,-7
Decending order: 99 6 0 -7
:::
相比而已,这就是选择排序的 for 循环展开形式,只要知道本质是什么即可。即对 n 个人进行“打擂台”依次挑出最大者的过程。
5、从键盘输入一个小于 1000 的正数,要求输出它的平方根(如平方根不是整数,则输出其整数部分)。要求在输入数据后先对其进行检查是否为小于 1000 的正数。若不是,则要求重新输入
解题思路:要求重新输入,则就是判断输入合法,如果一直不合法就让它一直输入(无退出选择),那么就要进行 while 检测。虽然一定要获取第一个输入,但不能使用 do-while 进行运算后再判断合法性。
#include <stdio.h>#include <math.h>#define M 1000int main () {int number;printf("Please input a number(<= %d):", M);scanf("%d", &number);while (number > M) {printf("Invalid input, please input again(<= %d):", M);scanf("%d", &number);}printf("The sqrt root is %d\n", (int)sqrt(number));return 0;}
编译运行:
:::success
b12@PC:~/chapter4$ gcc ./src/thousandSqrt.c -o ./bin/thousandSqrt -lm
b12@PC:~/chapter4$ ./bin/thousandSqrt
Please input a number(<= 1000):345
The sqrt root is 18
b12@PC:~/chapter4$ ./bin/thousandSqrt
Please input a number(<= 1000):1001
Invalid input, please input again(<= 1000):1000
The sqrt root is 31
:::
6、有一个分段函数如下,写程序,输入 x 的值,输出相应 y 得值。
解题思路:典型 if-else 判断,由于范围太大,用 switch-case 实现起来太麻烦。
#include <stdio.h>int main () {int x, y;printf("Please input x:");scanf("%d", &x);if (x < 1) {y = x;} else if (1 <= x && x < 10) {y = 2 * x - 1;} else {y = 3 * x - 11;}printf("x = %d, y = %d\n", x, y);return 0;}
运行结果:
:::success
b12@PC:~/chapter4$ gcc -Wall ./src/PiecewiseFunction.c -o ./bin/PiecewiseFunction
b12@PC:~/chapter4$ ./bin/PiecewiseFunction
Please input x:4
x = 4, y = 7
b12@PC:~/chapter4$ ./bin/PiecewiseFunction
Please input x:-1
x = -1, y = -1
b12@PC:~/chapter4$ ./bin/PiecewiseFunction
Please input x:20
x = 20, y = 49
:::
7、有一函数如下:有人分别编写了以下两个程序,请分析它们是否能实现题目要求。不要急于上机运行程序,先分析上面两个程序的逻辑,画出它们的流程图,分析它们的运行情况。然后上机运行程序,观察并分析结果。
程序1:
#include <stdio.h>int main () {int x, y;printf("Enter x:");scanf("%d", &x);y = -1;if (0 != x) // 1if (x > 0) // 2y = 1;else // 3y = 0;printf("x = %d, y = %d\n", x, y);return 0;}
其流程图如下:
出错原因在于第 10 行 else (3处)是和第 8 行 if (2处)匹配,而不是和第 7 行 if (1处)匹配。
编译运行:(发出警告,不仅仅是编码规范,而是易错)
:::warning
b12@PC:~/chapter4$ gcc -Wall ./src/if_else1.c -o ./bin/if_else1
./src/if_else1.c: In function ‘main’:
./src/if_else1.c:7:5: warning: suggest explicit braces to avoid ambiguous ‘else’ [-Wdangling-else]
7 | if (0 != x)
| ^
b12@PC:~/chapter4$ ./bin/if_else1
Enter x:-6
x = -6, y = 0
:::
程序2:
#include <stdio.h>int main () {int x, y;printf("Enter x:");scanf("%d", &x);y = 0;if(x >= 0) // 1if (x > 0) // 2y = 1;else // 3y = -1;printf("x = %d, y = %d\n", x, y);return 0;}
其流程图如下:
出错原因在于第 10 行 else (3处)是和第 8 行 if (2处)匹配,而不是和第 7 行 if (1处)匹配。即函数为
编译运行:(发出警告,不仅仅是编码规范,而是易错)
:::warning
b12@PC:~/chapter4$ gcc -Wall ./src/if_else2.c -o ./bin/if_else2
./src/if_else2.c: In function ‘main’:
./src/if_else2.c:7:4: warning: suggest explicit braces to avoid ambiguous ‘else’ [-Wdangling-else]
7 | if(x >= 0) // 1
| ^
b12@PC:~/chapter4$ ./bin/if_else2
Enter x:-4
x = -4, y = 0
:::
总之,即使 if-else 内只有一行代码也不要偷懒不写 {} ,代码不是要求简洁,而是要求可读性好。千万别学书上没格式地乱缩进等。。
正确代码:
#include <stdio.h>int main() {int x, y;printf("Enter x:");scanf("%d", &x);if (x > 0) {y = 1;} else if (0 == x) {y = 0;} else {y = -1;}printf("x = %d, y = %d\n", x, y);return 0;}
编译运行:
:::success
b12@PC:~/chapter4$ gcc ./src/if_else.c -o ./bin/if_else
b12@PC:~/chapter4$ ./bin/if_else
Enter x:3
x = 3, y = 1
b12@PC:~/chapter4$ ./bin/if_else
Enter x:0
x = 0, y = 0
b12@PC:~/chapter4$ ./bin/if_else
Enter x:-1
x = -1, y = -1
:::
8、给出一百分制成绩,要求输出成绩等级’A’、’B’、’C’、’D’、’E’。90分以上为’A’,80~89分为B’,70~70分为’C’,60~69分为’D’,60分以下为’E’。
解题思路:可以使用 switch-case 或者 if-else 解决。在使用switch-case 时找到每个 10 区间对应的值即可,但是需要注意 100 的特殊情况。由于分数可以 65.5 ,因此数据类型就是 float
// scoreGrade.c#include <stdio.h>int main () {float score;char grade;printf("Please input student score:");scanf("%f", &score);while (0 > score || score > 100) {printf("Invalid input, pelase input again:");scanf("%f", &score);}switch ((int)(score / 10)) {case 10:case 9:grade = 'A';break;case 8:grade = 'B';break;case 7:grade = 'C';break;case 6:grade = 'D';break;default:grade = 'E';}// if (score >= 90) {// grade = 'A';// } else if (score >= 80) {// grade = 'B';// } else if (score >= 70) {// grade = 'C';// } else if (score >= 60) {// grade = 'D';// } else {// grade = 'E';// }printf("score: %5.1f, grade: %c\n", score, grade);return 0;}
运行结果:
:::success
b12@PC:~/chapter4$ gcc -Wall ./src/scoreGrade.c -o ./bin/scoreGrade
b12@PC:~/chapter4$ ./bin/scoreGrade
Please input student score:101
Invalid input, pelase input again:-1
Invalid input, pelase input again:58
score: 58.0, grade: E
:::
9、给一个不多于5位的正整数,要求:
- 求出它是几位数
- 分别输出每一位数字
- 按逆序输出各位数字,例如原数为
321,应输出123。
解题思路:要求1和2可同步进行,使用函数递归,从高位到低位进行退栈的过程进行打印输出即可。同时逆序就是低位到高位,可以直接使用 do-while 取余整除迭代进行。
#include <stdio.h>void putDigit(int num, int cnt) {/* 函数进行递归正序输出,cnt参数计算长度 */if (0 == num / 10) { // 一位的时候单独处理printf("Total length:%d\n", cnt + 1);printf("Each digit:%d", num);} else {putDigit(num / 10, cnt + 1);printf(", %d", num % 10);}}int main () {int num;printf("Please input a number(0~99999):");scanf("%d", &num);putDigit(num, 0);// 迭代逆序输出printf("\nReversed:");do {printf("%d", num % 10);num /= 10;} while (num);return 0;}
:::success
b12@PC:~/chapter4$ gcc -Wall ./src/countNum.c -o ./bin/countNum
b12@PC:~/chapter4$ ./bin/countNum
Please input a number(0~99999):98423
Total length:5
Each digit:9, 8, 4, 2, 3
Reversed:32489
:::
10、企业发放的奖金根据利润提成
利润I低于或等于100000元的,奖金可提成10%;利润高于100000元,低于200000元(1000001000000时,超过1000000元的部分按1%提成。从键盘输入当月利润I,求应发奖金总数。
要求:
- 用if语句编程序。
- 用switch语句编程序。
解题思路:本题所表达是意思如下
由此可以清晰看出其间的递推关系:除了第一层的 单独计算外,其他都是在前者的基础上累加区间利润。
- 利润为100 000元时应得的奖金,即100000元×0.1。
- 100 000元以上部分应得的奖金,即(num-100 000)×0.075元。
- 200000~400000元这个区间的奖金也应由两部分组成:
- 利润为200 000元时应得的奖金,即100 000×0.1+100 000×0.075。
- 200 000元以上部分应得的奖金,即(num-200000)×0.05元。
程序中先把100 000元、200 000元、400 000元、600 000元、1 000 000元各关键点的奖金计算出来,即 bon1,bon2,bon4,bon6和bon10。然后再加上各区间附加部分的奖金即可。
流程图:
#include <stdio.h>int main () {int i;printf("Please input interests:");scanf("%d", &i);double bonus, bonus1, bonus2, bonus4, bonus6, bonus10;bonus1 = 100000 * 0.1;bonus2 = bonus1 + 100000 * 0.075;bonus4 = bonus2 + 100000 * 0.05;bonus6 = bonus4 + 100000 * 0.03;bonus10 = bonus6 + 100000 * 0.015;if (i <= 100000) {bonus = i * 0.1;} else if (i <= 200000) {bonus = bonus1 + (i - 100000) * 0.075;} else if (i <= 400000) {bonus = bonus2 + (i - 200000) * 0.05;} else if (i <= 600000) {bonus = bonus4 + (i - 400000) * 0.03;} else if (i <= 1000000) {bonus = bonus6 + (i - 600000) * 0.015;} else {bonus = bonus10 + (i - 1000000) * 0.01;}printf("Bonus:%10.2f\n", bonus);return 0;}
编译运行:
:::success
b12@PC:~/chapter4$ gcc -Wall ./src/bonus.c -o ./bin/bonus
b12@PC:~/chapter4$ ./bin/bonus
Please input interests:234000
Bonus: 19200.00
:::
N-S流程图:
使用 switch-case 同上面成绩转换一样,注意最大区间的判断即可。
#include <stdio.h>int main () {int i;printf("Please input interests:");scanf("%d", &i);double bonus, bonus1, bonus2, bonus4, bonus6, bonus10;bonus1 = 100000 * 0.1;bonus2 = bonus1 + 100000 * 0.075;bonus4 = bonus2 + 100000 * 0.05;bonus6 = bonus4 + 100000 * 0.03;bonus10 = bonus6 + 100000 * 0.015;int branch = i / 100000;if (i >= 1000000) { // 最大区间的范围压缩branch = 10;}switch (branch) {case 0:bonus = i * 0.1; break;case 1:bonus = bonus1 + (i - 100000) * 0.075; break;case 2:case 3:bonus = bonus2 + (i - 200000) * 0.05; break;case 4:case 5:bonus = bonus4 + (i - 400000) * 0.03; break;case 6:case 7:case 8:case 9:bonus = bonus6 + (i - 600000) * 0.015; break;case 10:bonus = bonus10 + (i - 1000000) * 0.01; break;}printf("Bonus:%10.2f\n", bonus);return 0;}
编译运行:
可能会疑惑:明明题目给定时,利润是
,但是上面代码进行
后怎么没有判断右区间相等的情况?例如
是
case 0 ,那么 它不是等于
branch=1 吗?明显错了?其实不然,因为它跑到下一个 case 1 去了,此时 bonus = bonus1 + (i - 100000) * 0.075; 后面相加部分为 0 ,这也是 switch-case 使用的时候需要非常注意的地方,如果拿不准或找不到规律,直接使用 if-else 。
:::success
b12@PC:~/chapter4$ gcc -Wall ./src/bonus.c -o ./bin/bonus
b12@PC:~/chapter4$ ./bin/bonus
Please input interests:100000
Bonus: 10000.00
b12@PC:~/chapter4$ ./bin/bonus
Please input interests:200000
Bonus: 17500.00
:::
12、有4个圆塔,圆心分别为(2,2),(-2,2),(-2,-2),(2,-2),圆半径为1
这4个塔的高度为10m,塔以外无建筑物。今输入任一点的坐标,求该点的建筑高度(塔外的高度为零)。
解题思路:其实说半天就是一个立体图的俯视图,问你是不是在四个水塔上,是就是高度为 10 m,否则就是地上,高度为 0 m。
按书上对 4 个塔中心距离求解
N-S流程图:
因为对称性的发现,问题可以直接转换到求一个点是否在塔上,可以把其转换为都在第一象限上(),即对坐标取绝对值
流程图:
参考代码:
#include <stdio.h>#define X 2#define Y 2#define R 1int main () {int h = 10;float x, y;printf("Please input a point (x, y):");scanf ("%f,%f", &x, &y);x = x >= 0 ? x : -x; // fabs(x)y = y >= 0 ? y : -y; // fabs(y)if ((x - X) * (x - X) + (y - Y) * (y - Y) > R) {h = 0;}printf("The height of (%f, %f) is %d\n", x, y, h);return 0;}
编译运行:
:::success
b12@PC:~/chapter4$ gcc -Wall ./src/tower.c -o ./bin/tower
b12@PC:~/chapter4$ ./bin/tower
Please input a point (x, y):0.5,0.7
The height of (0.500000, 0.700000) is 0
b12@PC:~/chapter4$ ./bin/tower
Please input a point (x, y):2.1,-2.3
The height of (2.100000, 2.300000) is 10
:::
