谭浩强C语言课后习题——第四章

一. 什么是算术运算?什么是关系运算?什么是逻辑运算?

答:

+、-、*、/等数学运算是算术运算;>、<、>=、<=、==、!=运算是关系运算;||、&&、!是逻辑运算。

附:

算术运算:

算术运算即“四则运算”,是加法、减法、乘法、除法、乘方、开方等几种运算的统称。

其中加减为一级运算,乘除为二级运算,乘方、开方为三级运算。在一道算式中,如果有多级运算存 在,则应先进行高级运算,再进行低一级的运算。

C语言中的算熟运算符包括: + 、 - 、 * 、 / 、 ++ 、 -- 、 % 等种类。

如果只存在同级运算;则从左至右的顺序进行;如果算式中有括号,则应先算括号里边,再按上述规则进行计算

示例: (1 + 1)^{2} * 4+5 * 3

解析:

1. 先进行括号内运算 1+1 ,然后进行乘方运算得到结果4.

2. 接下来与4相乘,得到结果16

3. 因为乘法优先级大于加法,因此先进行5*3,得到结果15

4. 最终相加得到结果31

结果:31

关系运算:

        关系的基本运算有两类:一类是传统的集合运算(并、差、交等),另一类是专门的关系运算(选择、 投影、连接、除法、外连接等),而在C语言中,关系运算通常被认为是比较运算,将两个数值进行比较,判断比较结果是否符合给定的条件。

常见的关系运算符包括: > 、  < 、 >= 、<=、 == 、 != 等种类。

其中,前4种关系运算符(> 、  < 、 >= 、<=)的优先级别相同,后2种(==、!=)也相同。而前4种高于后2种。

例如, > 优先于 == 。而 > 与 <优先级相同。 并且,关系运算符的优先级低于算术运算符,关系运算符的优先级高于赋值运算符(=)。

逻辑运算:

        在逻辑代数中,有与、或、非三种基本逻辑运算。表示逻辑运算的方法有多种,如语句描述、逻辑代数 式、真值表、卡诺图等。而在C语言中,逻辑运算通常用于使用逻辑运算符将关系表达式或其它逻辑量连接起来组成逻辑表达式用来测试真假值。常见的逻辑运算符包括: && 、 || 、 ! 等种类。

&& : 与是双目运算符,要求有两个运算对象,表示两个运算对象都成立,则结果为真,否则结果为 假。 例如:(ay),表示(a和(x>y)同时成立则为真。

|| :是双目运算符,要求有两个运算对象,表示两个运算对象只要任意一个成立,则结果为真,否则 结果为假。 例如:(ay),表示(a和(x>y)两个对象中任意一个成立则结果为真。

! :是单目运算符,只要求有一个运算对象,表示取运算对象反义,运算对象为真则结果为假,运算对象结果为假则结果为真。

例如:!(a>b),表示(a>b)成立时结果为假,不成立时结果为真。 若在一个逻辑表达式中包含多个逻辑运算符,则优先次序为: ! > && > || 。当然若一个逻辑表达式 中包含括号括起来的子逻辑,则优先括号内的子逻辑判断

示例:

(1>2)||(2>3)&&(4>3) 结果为0 !(1>2)||(2>3)&&(4>3)结果为1

注:

&& 优先级大于 || ,((2>3)&&(4>3))无法同时成立,则结果为假,然后与(1>2)结果进行逻辑或运 算,两者都为假因此第一次结果为假。 而第二次 ! 优先级最高,先对(1>2)的结果取逻辑非,得到结果 为真,因此结果为真。

二. C语言中如何表示“真”和“假”?系统如何判断一个量的“真”和“假”?

答:

逻辑表达式,1表示真,0表示假。若是判断一个逻辑量的值,系统会以0表示为“假”,非0表示为“真”。

附:

在C语言中逻辑常量只有两个,即0和1,用来表示两个对立的逻辑状态,其中 0 表示假, 1 表示真。 逻辑变量与普通代数一样,也可以用字母、符号、数字及其组合成为的逻辑表达式表示。 对于系统来说,判断一个逻辑量的值时,系统会以 0 作为假,以非0作为真。例如 3&&5 的值为真,系统给出 3&&5 的值为 1 。

三. 写出下面各逻辑表达式的值。设a=3,b=4,c=5。

(1)a + b > c && b == c

(2)a || b + c && b - c

(3)!(a > b) && !c || 1

(4)!(x = a) && (y = b) && 0

(5)!(a + b) + c - 1 && b + c / 2

答:

(1)0

(2)1

(3)1

(4)0

(5)1

附:

1. 关系运算符的优先级高于赋值运算符,但是低于算术运算符

2. &&表示两边条件同为真则成立,||表示两边条件任意一个为真则成立,!取条件反义。

3. 逻辑运算符优先级: ! > && > ||

4. 有括号优先括号

(1)0

1. a + b > c        7 > 5为真

2. b == c            4 = 5        为假

3. a + b > c && b == c         1 && 0,结果为0

(2)1

1. b + c && b - c        1 && 1,结果为1

2.a || b + c && b - c      1  || 1,结果为1

(3)1

1. (a > b)        3 > 4,结果为0        因此,!(a > b)结果为1

2.!c        同理,!c结果为0

3.!(a > b) && !c        1 && 0,结果为0

4.!(a > b) && !c || 1         0 || 1,结果为1

(4)0

1. !(x = a)        结果为0

2.(y = b)        结果为0

3.!(x = a) && (y = b) && 0         0 && 0 && 0        结果为0

(5)1

1.c / 2        结果为1        //其准确结果取决于将 c 定义为什么类型(int = 2、float = 2.500000)

2. (a + b)        a + b = 7

3.c - 1        5 - 1 = 4

4. b + c / 2        4 + 1 =5

4. !(a + b)        结果为0

5.!(a + b) + c - 1         0 + c - 1 = 4        结果为4

6.!(a + b) + c - 1 && b + c / 2         1 && 1,结果为1

四. 有3个整数a, b, c,由键盘输入,输出其中最大的数。

4.1 if嵌套

#include <stdio.h>

int main()
{
	int a = 0;        
	int b = 0;
	int c = 0;
	int max = 0;

	printf("请输入三个整数:");
	scanf("%d%d%d", &a, &b, &c);

    max = a;        //设定最大值为a

    if (b > max)    //如果 b > a,最大值为b
    {
        max = b;
    
    if (c > max)    //如果 c > a,最大值为c
    {
        max = c;
    }

    printf("最大的数是:%d\n", max);

    return 0;

}

注:

这个程序首先假设a是最大的,并将其存储在变量max中。然后,它使用两个if语句来检查bc是否分别大于当前存储在max中的值。如果是,则更新max的值。最后,它输出max的值,即三个数中的最大值。

这种方法的好处是它只需要两次比较就可以找到最大值,这比使用嵌套的if-else语句更简洁、更高效。

4.2使用嵌套的if-else语句 

#include <stdio.h>  

int main() {
    int a, b, c, max;

    printf("请输入三个整数:");
    scanf("%d%d%d", &a, &b, &c);

    if (a > b) 
{
        if (a > c)
        {
            max = a; // a 是最大的  
        }
        else
        {
            max = c; // c 比 a 大,所以 c 是最大的  
        }
    }
    else
    {
        if (b > c) 
        {
            max = b; // b 比 a 大,且 b 比 c 大,所以 b 是最大的  
        }
        else
        {
            max = c; // c 是最大的(因为 b 不大于 c,且 a 也不大于 b)  
        }
    }

    // 注意:这里不需要再检查 a 和 max 的关系,因为上面的逻辑已经涵盖了所有情况  

    printf("最大的数是:%d\n", max);

    return 0;
}

4.3 用逻辑符号和逻辑表达式写

#include <stdio.h>

int main()
{
	int a, b, c, max;

	printf("请输入三个整数:");
	scanf("%d%d%d", &a, &b, &c);

	if (a > b && a > c)

	{
		max = a;
		printf("max = %d\n", max);
	}
	else if (b > a && b > c)
	{
		max = b;
		printf("max = %d\n", max);
	}
	else if (c > a && c > b) 
	{
		max = c;
		printf("max = %d\n", max);
	}
	else
	{
		max = a;
		printf("max = %d\n", max);
	}

	return 0;
}

五.从键盘输入一个小于1000的正数,要求输出它的平方根(如平方根不是整数,则输出其整数部分)。要求在输入数据后先对其进行检查是否为小于1000 的正数。若不是,则要求重新输入。

#include<stdio.h>
#include<math.h>

int main()
{
	double a = 0;

	printf("请输入一个小于1000的正数:\n");
	scanf("%lf", &a);

	if (a < 0 || a > 1000)    //检验a的大小是否在要求的范围内
	{
		printf("请重新输入一个小于1000的正数!\n");
	}
	else    //如果a符合要求,直接开方
	{
		a = sqrt(a);        
	}

	printf("该正数的平方根为:%2.lf\n", a);

	return 0;
}

六. 有一个函数,编写程序,输入x的值,输出y相应的值。

#include<stdio.h>

int main()
{
	int x = 0;
	int y = 0;

	scanf("%d", &x);

	if (x < 1)
	{
		y = x;
	}
	else if (1 <= x && x < 10)
	{
		y = (2 * x) - 1;
	}
	else		// x >= 10
	{
		y = (3 * x) - 11;
	}

	printf("y = %d\n", y);

	return 0;
}

注:

错误写法:else if (1 <=  x < 10)                // else if (1 <= x && x < 10)

直接像 1 <= x < 10 这样连续比较两个条件,因为这样的表达式会被解释为 (1 <= x) < 10,而 (1 <= x) 的结果是一个布尔值(在 C 中是 int 类型,01),然后再与 10 进行比较。

七.有一个函数,如下图有人编写了以下两个程序,请分析它们是否能实现题目要求。不要急于上机运行程序,先分析两个程序的逻辑,画出它们的流程图,分析它们的运行情况。然后,上机运行程序,观察和分析结果。

7.1

#include <stdio.h>

int main()
{
	int x, y;

	printf("enter x:");
	scanf("%d", &x);

	y = -1;

	if (x != 0)
		if (x > 0)
			y = 1;
		else
			y = 0;

	printf("x=%d,y=%d\n", x, y);

	return 0;
}

答:

这段代码不能实现题目的要求。当x等于0时,y的值为-1。当x小于0时,y的值为0。其中else子句与第9行的if语句相匹配。

注:

else语句使用过程中,else总是匹配距离自己最近的且没有配对的if

因此x!=0具有两种情况x>0和x<0;

因此x==0时y保持 -1;x!=0&&x>0时y=1;x!=0&&x时y=0。

运行结果:

流程图:

7.2

#include <stdio.h>

int main()
{
	int x, y;

	printf("enter x:");
	scanf("%d", &x);

	y = 0;

	if (x >= 0)
		if (x > 0)
			y = 1;
		else
			y = -1;

	printf("x=%d,y=%d\n", x, y);

	return 0;
}

运行结果:

流程图:

 修正后的代码:

#include <stdio.h>

int main()
{
	int x, y;

	printf("enter x:");
	scanf("%d", &x);

	y = 0;

	if (x != 0)
		if (x > 0)
			y = 1;
		else
			y = -1;

	printf("x=%d,y=%d\n", x, y);

	return 0;
}

 运行结果:

流程图:

八. 给出一百分制成绩,要求输出成绩等级'A'、'B'、'C'、'D'、'E'。 90分以上为'A',80~89分为'B',70~79分为'C' ,60~69分为'D' ,60分以下为'E'。

int main()
{
	int feat = 0;

	printf("请输入你的成绩:\n");
	scanf("%d", &feat);

	if (feat >= 90)
	{
		printf("A");
	}
	if (feat >= 80 && feat < 90)
	{
		printf("B");
	}
	if (feat >= 70 && feat < 80)
	{
		printf("C");
	}
	if (feat >= 60 && feat < 70)
	{
		printf("D");
	}
	if (feat < 60)
	{
		printf("E");
	}
	
	return 0;

}

九. 给一个不多于5位的正整数,要求:①求出它是几位数;②分别输出每一位数字;③按逆序输出各位数字,例如原数为321,应输出123。

1.求出它是几位数

#include <stdio.h>

int main()
{    
	int num;
	printf("enter num:");    
	scanf_s("%d", &num);   

	if (num > 99999 || num < 0)
	{       
		printf("请输入0~99999之间的正数\n");   

	return -1;   
	}    

	if (num >= 10000)
	{        
		printf("5\n");   
	}
	else if (num >= 1000) 
	{        
		printf("4\n");   
	}
	else if (num >= 100)
	{        
		printf("3\n");   
	}
	else if (num >= 10) 
	{        
		printf("2\n");   
	}
    else 
	{        
		printf("1\n");   
	}    

	return 0;
}

2.分别输出每一位数字

#include <stdio.h>

int main()
{   
	int num = 0; 
	printf("enter num:");
	scanf_s("%d", &num);   

	if (num > 99999 || num < 0)
	{        
		printf("请输入0~99999之间的数字\n");

		return -1;    
	}    

	if (num / 10000 > 0)		//取出万位数字
	{
		printf("%d ", num / 10000);
	}   
	if (num % 10000 >= 1000)	//取余10000则可以取出低四位的数据,除以1000则得到千位的数字
	{        
		printf("%d ", (num % 10000) / 1000);   
	}   
	if (num%1000 >= 100)		//取余1000则可以取出低三位的数据,除以100则得到百位的数字
	{
		        
		printf("%d ", (num % 1000) / 100);    
	}    
	if (num%100 >= 10)			//取余100则可以取出低两位的数据,除以10则得到十位的数字 
	{							      
		printf("%d ", (num % 100) / 10);   
	}   
	if (num%10 >= 0)			//取余10则取出个位数字 
	{       
		printf("%d ", num % 10);   
	}   

	printf("\n");   
	
	return 0;
}

3.按逆序输出各位数字

#include <stdio.h>

int main()
{   
	int num = 0; 

	printf("enter num:");
	scanf_s("%d", &num);   

	if (num > 99999 || num < 0)
	{        
		printf("请输入0~99999之间的数字\n");

		return -1;    
	}    

	if (num%10 >= 0)			//取余10则取出个位数字 
	{       
		printf("%d ", num % 10);   
	}   
	if (num % 100 >= 10)			//取余100则可以取出低两位的数据,除以10则得到十位的数字 
	{
		printf("%d ", (num % 100) / 10);
	}if (num % 100 >= 10)			//取余100则可以取出低两位的数据,除以10则得到十位的数字 
	{
		printf("%d ", (num % 100) / 10);
	}
	if (num % 1000 >= 100)		//取余1000则可以取出低三位的数据,除以100则得到百位的数字
	{

		printf("%d ", (num % 1000) / 100);
	}
	if (num % 10000 >= 1000)	//取余10000则可以取出低四位的数据,除以1000则得到千位的数字
	{
		printf("%d ", (num % 10000) / 1000);
	}
	if (num / 10000 > 0)		//取出万位数字
	{
		printf("%d ", num / 10000);
	}

	printf("\n");   
	
	return 0;
}

十.企业发放的奖金根据利润提成。利润I低于或等于100000元的,奖金可提成10%;利润高于100000元,低于200000元(100000时,低于100000元的部分按10%提成,高于100000元的部分,可提成7. 5%;200000时,低于200000元的部分仍按上述办法提成(下同)。高于200000元的部分按5%提成;400000元时,高于400000元的部分按3%提成;600000时,高于600000元的部分按1.5%提成;I>1000000时,超过1000000元的部分按1%提成。从键盘输入当月利润I,求应发奖金总数。

要求:

(1) 使用if语句编写程序

int main()
{
	double I = 0; 
	double J = 0;

	printf("enter I:");
	scanf("%lf", &I);   

	if (I <= 1e+5)
	{
		J = I * 0.1;
	}
	else if (I > 1e+5 && I <= 2e+5)
	{
		J = (100000 * 0.1) + (I - 100000) * 0.075;
	}
	else if (I > 2e+5 && I <= 4e+5)
	{
		J = (100000 * 0.1) + (100000 * 0.075) + (I - 200000) * 0.05;
	}
	else if (I > 4e+5 && I <= 6e+5)
	{
		J = (100000 * 0.1) + (100000 * 0.075) + ( I -200000 * 0.03) ;
	}
	else if (I > 6e+5 && I <= 1e+6)
	{
		J = (100000 * 0.1) + (100000 * 0.075) + (200000 * 0.05) + (200000 * 0.015);
	}
	else if (I > 1e+6)
	{
		J = (100000 * 0.1) + (100000 * 0.075) + (200000 * 0.05) + (200000 * 0.015) + (I - 1000000)*0.001;
	}

	printf("%lf", J);

	return 0;
}

(2)使用switch语句编写程序

int main()
{
	int I = 0; 
	double J = 0;

	printf("enter I:");
	scanf("%d", &I);   

	switch (I)
	{
	case 0:
		J = I * 0.1;
		break;
	case 1:
		J = (100000 * 0.1) + (I - 100000) * 0.075;
		break;
	case 2:
	case 3:
		J = (100000 * 0.1) + (100000 * 0.075) + (I - 200000) * 0.05;
		break;
	case 4:
	case 5:
		J = (100000 * 0.1) + (100000 * 0.075) + (I - 200000 * 0.03);
		break;
	case 6:
	case 7:
	case 8:
	case 9:
		J = (100000 * 0.1) + (100000 * 0.075) + (200000 * 0.05) + (200000 * 0.015);
		break;
	default:
		J = (100000 * 0.1) + (100000 * 0.075) + (200000 * 0.05) + (200000 * 0.015) + (I - 1000000) * 0.001;
		break;
	}

	printf("%lf", J);

	return 0;
}

十一. 输入4个整数,要求按由小到大的顺序输出。

11.1 if 语句循环

#include <stdio.h>  

int main()
{
    int a, b, c, d, temp;

    printf("请输入四个整数:");
    scanf("%d%d%d%d", &a, &b, &c, &d);

    if (a > b) 
    {
        tmp = a;
        a = b;
        b = tmp;
    }
    if (a > c) 
    {
        tmp = a;
        a = c;
        c = tmp;
    }
    if (a > d) 
    {
        tmp = a;
        a = d;
        d = tmp;
    }
    if (b > c)
    {
        tmp = b;
        b = c;
        c = tmp;
    }
    if (b > d)
    {
        tmp = b;
        b = d;
        d = tmp;
    }
    if (c > d)
    {
        tmp = c;
        c = d;
        d = tmp;
    }

    printf("%d %d %d %d\n", a, b, c, d);

    return 0;
}

注:

文心一言在检查代码时发现了问题,但在我的各种检验下,代码依旧正确运行了。这个逻辑问题我还没能处理,将文心一言给我的修改建议放在下面,以供参考。

在比较和交换 bd 之后,如果 b(现在可能包含原来的 d 的值)大于 c,那么 bc 的位置也需要被交换以确保排序的正确性。

然而,为了更清楚地说明问题,我们可以构造一个稍微不同的场景,其中确实需要交换 bd,并且之后需要重新检查 cb 的关系:

假设用户输入的四个整数是:4, 7, 6, 3

执行过程(假设代码在比较 bd 后错误地停止了进一步的比较):

  1. 初始状态:a=4, b=7, c=6, d=3
  2. 比较 ab,不需要交换。
  3. 比较 ac4 < 6,不需要交换。
  4. 比较 ad4 > 3,交换 ada=3, b=7, c=6, d=4
  5. 比较 bc7 > 6,不需要交换。
  6. 关键步骤:比较 bd7 > 4,交换 bda=3, b=4, c=6, d=7
  7. 问题显现:此时没有重新检查 cb 的关系。按照排序要求,c6)应该大于 b(现在是 4),但由于我们没有重新检查,所以这一步被遗漏了。正确的状态应该是通过某种方式(可能是另一个比较和交换步骤)得到 a=3, b=4, c=7, d=6 或其他任何 c 大于 b 的排序。

2. 使用冒泡排序的思想进行排序 

#include <stdio.h>  

int main()
{
    int a , b, c , d, temp; 

    printf("请输入四个整数:");
    scanf("%d%d%d%d", &a, &b, &c, &d);

    if (a > b)
    {
        temp = a;
        a = b;
        b = temp;
    }
    if (a > c)
    {
        temp = a;
        a = c;
        c = temp;
        if (b > c)
        {
            temp = b;
            b = c;
            c = temp;
        }
    }
    if (a > d)
    {
        temp = a;
        a = d;
        d = temp;
        if (b > d)
        {
            temp = b;
            b = d;
            d = temp;
        }
        if (c > d)
        {
            temp = c;
            c = d;
            d = temp;
        }
    }
    if (b > c)
    {
        temp = b;
        b = c;
        c = temp;
    }
    if (b > d)
    {
        temp = b;
        b = d;
        d = temp;
        if (c > d)
        {
            temp = c;
            c = d;
            d = temp;
        }
    }
    if (c > d)
    {
        temp = c;
        c = d;
        d = temp;
    }

    printf("%d %d %d %d", a, b, c, d);

    return 0;
}

十二. 有4个圆塔,圆心分别为(2,2)、(-2,2)、(-2,-2)、(2,-2),圆半径为1,见图。这4个塔的高度为10m,塔以外无建筑物。今输入任一点的坐标,求该点的建筑高度(塔外的高度为零)。

#include <stdio.h>  
#include <math.h>  
  
int main()  
{      
    int h;      
    double x, y, m, n, r;      
  
    printf("请输入一个坐标点 (x,y):");      
    scanf("%lf %lf", &x, &y);      
  
    // 检查坐标点是否在边长为6的正方形内(不包括边界)  
    if (fabs(x) > 3 || fabs(y) > 3)   
    {          
        h = 0;          
        printf("该点位于区域外,建筑高度:h=%d\n", h);  
        return 0;      
    }      
  
    // 计算点到原点(0,0)的距离,然后减去2(因为中心区域半径为1)  
    m = fabs(x) - 2;   
    n = fabs(y) - 2;      
    r = sqrt(m * m + n * n);      
  
    // 如果点到中心的距离大于1,则高度为0;否则高度为10  
    if (r > 1)         
        h = 0;      
    else          
        h = 10;      
  
    // 输出建筑高度  
    printf("该点的建筑高度:h=%d\n", h);    
  
    return 0;  
}
 未完待续......
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值