- 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最大者放入 tmp
tmp = tmp > c ? tmp : c; // tmp,c最大者放入 tmp
printf("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 中找到最大并放在 b
if (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 中找到最大并放在 c
if (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 1000
int 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) // 1
if (x > 0) // 2
y = 1;
else // 3
y = 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) // 1
if (x > 0) // 2
y = 1;
else // 3
y = -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
个塔的高度为10
m,塔以外无建筑物。今输入任一点的坐标,求该点的建筑高度(塔外的高度为零)。
解题思路:其实说半天就是一个立体图的俯视图,问你是不是在四个水塔上,是就是高度为 10
m,否则就是地上,高度为 0
m。
按书上对 4 个塔中心距离求解
N-S流程图:
因为对称性的发现,问题可以直接转换到求一个点是否在塔上,可以把其转换为都在第一象限上(),即对坐标取绝对值
流程图:
参考代码:
#include <stdio.h>
#define X 2
#define Y 2
#define R 1
int 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
:::