C程序设计谭浩强第五版课后答案 第四章习题答案
scanf出问题请看:超简单的scanf错误修改
4. 有3个整数a, b, c,由键盘输入,输出其中最大的数。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
if (a == b && a == c) {
printf("Three numbers are equal\n");
}else if (a == b && a > c) {
printf("a and b are the largest number\n", a);
}else if (a == c && a > b) {
printf("a and c are the largest number\n", a);
}else if (b == c && b > a) {
printf("c and b are the largest number\n", a);
}else if (a > b && a > c) {
printf("a=%d is the largest number\n", a);
}else if (b > a && b > c) {
printf("b=%d is the largest number\n", b);
}else {
printf("c=%d is the largest number\n", c);
}
return 0;
}
5.从键盘输入一个小于1000的正数,要求输出它的平方根(如平方根不是整数,则输出其整数部分)。要求在输入数据后先对其进行检查是否为小于1000 的正数。若不是,则要求重新输入。
#include <stdio.h>
#include <math.h>
int main()
{
float a, b;
scanf_s("%f", &a);
if (a >= 1000 || a < 0) {
printf("请输入小于1000的正数\n");
scanf_s("%f", &a);
b = sqrt(a);
}
else {
b = sqrt(a);
}
printf("a=%4.0f, b=%4.0f\n", a, b);
system("pause");//这一句是为了让控制台不退出
return 0;
}
6. 有一个函数,编写程序,输入x的值,输出y相应的值。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
int x, y;
scanf("%d", &x);
if (x < 1)
{
y = x;
}
else if (x >= 1 && x < 10)
{
y = 2 * x - 1;
}
else
{
y = 3 * x - 11;
}
printf("y = %d\n", y);
//system("pause");//控制台没设置好的,加上这个或者设置控制台
return 0;
}
7. 有一个函数
有人编写了以下两个程序,请分析它们是否能实现题目要求。不要急于上机运行程序,先分析两个程序的逻辑,画出它们的流程图,分析它们的运行情况。然后,上机运行程序,观察和分析结果。
#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;
}
8. 给出一百分制成绩,要求输出成绩等级’A’、‘B’、‘C’、‘D’、‘E’。 90分以上为’A’,8089分为’B’,7079分为’C’ ,60~69分为’D’ ,60分以下为’E’。
#include <stdio.h>
int main()
{
int score;
printf("enter score:");
scanf_s("%d", &score);
if (score >= 90) {
printf("A\n");
}else if (score >= 80 && score < 90) {
printf("B\n");
}else if (score >= 70 && score < 80) {
printf("C\n");
}else if (score >= 60 && score < 70) {
printf("D\n");
}else {
printf("E\n");
}
system("pause");
return 0;
}
9. 给一个不多于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");
}
system("pause");
return 0;
}
解(2)
#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 > 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");
system("pause");
return 0;
}
解(3)
#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 % 10 >= 0) {
printf("%d ", num % 10);
}
if (num % 100 >= 10) {
printf("%d ", (num % 100) / 10);
}
if (num % 1000 >= 100) {
printf("%d ", (num % 1000) / 100);
}
if (num % 10000 >= 1000) {
printf("%d ", (num % 10000) / 1000);
}
if (num / 10000 > 0) {
printf("%d ", num / 10000);
}
printf("\n");
system("pause");
return 0;
}
10.企业发放的奖金根据利润提成。利润I低于或等于100000元的,奖金可提成10%;利润高于100000元,低于200000元(100000<I≤200000)时,低于100000元的部分按10%提成,高于100000元的部分,可提成7. 5%;200000<I≤400000时,低于200000元的部分仍按上述办法提成(下同)。高于200000元的部分按5%提成;400000<<I≤600000元时,高于400000元的部分按3%提成;600000<1≤1000000时,高于600000元的部分按1.5%提成;I>1000000时,超过1000000元的部分按1%提成。从键盘输入当月利润I,求应发奖金总数。要求:(1) 使用if语句编写程序。(2) 使用switch语句编写程序。
解(1)
#include <stdio.h>
int main()
{
double I, salary = 0;
printf("enter performance:");
scanf_s("%lf", &I);
if (I < 0) {
printf("请输入一个正数\n");
system("pause");
return -1;
}
double salary1 = 100000 * 0.1;//10万的奖金
double salary2 = (200000 - 100000) * 0.075 + salary1;//20万的奖金
double salary3 = (400000 - 200000) * 0.05 + salary2;//40万的奖金
double salary4 = (600000 - 400000) * 0.03 + salary3;//60万的奖金
double salary5 = (1000000 - 600000) * 0.015 + salary4;//100万的奖金
if (I <= 100000) {
salary = I * 0.1;//小于100000按10%提成
}else if (I > 100000 && I <= 200000) {
salary = salary1 + (I - 100000) * 0.075;//多出10万的按比例计算,加上10w的奖金
}else if (I > 200000 && I <= 400000) {
salary = salary2 + (I - 200000) * 0.05;//多出20万的按比例计算,加上20w的奖金
}else if (I > 400000 && I <= 600000) {
salary = salary3 + (I - 400000) * 0.03;//多出40万的按比例计算,加上40w的奖金
}else if (I > 600000 && I <= 1000000) {
salary = salary4 + (I - 600000) * 0.015;//多出60万的按比例计算,加上60w的奖金
}else if (I > 1000000){
salary = salary5 + (I - 1000000) * 0.01;//多出100万的按比例计算,加上100w的奖金
}
printf("salary:%f\n", salary);
system("pause");
return 0;
}
解(2)
#include <stdio.h>
int main()
{
double I, salary = 0;
printf("enter performance:");
scanf_s("%lf", &I);
if (I < 0) {
printf("请输入一个正数\n");
system("pause");
return -1;
}
double salary1 = 100000 * 0.1;//大于100000时0~100000的奖金
double salary2 = (200000 - 100000) * 0.075 + salary1;//大于200000时0~20万的奖金
double salary3 = (400000 - 200000) * 0.05 + salary2;//大于400000时0~40万的奖金
double salary4 = (600000 - 400000) * 0.03 + salary3;//大于600000时0~60万的奖金
double salary5 = (1000000 - 600000) * 0.015 + salary4;//大于1000000时0~100万的奖金
int grade = I / 100000;
switch(grade) {
case 0:
salary = I * 0.1; break;
case 1:
salary = salary1 + (I - 100000) * 0.075; break;
case 2://会顺序执行到下一个break处
case 3:
salary = salary2 + (I - 200000) * 0.05; break;
case 4:
case 5:
salary = salary3 + (I - 400000) * 0.03; break;
case 6:
case 7:
case 8:
case 9:
salary = salary4 + (I - 600000) * 0.015; break;
default:
salary = salary5 + (I - 1000000) * 0.01; break;
}
printf("salary:%f\n", salary);
system("pause");
return 0;
}
11. 输入4个整数,要求按由小到大的顺序输出。
#include <stdio.h>
int main()
{
int a, b, c, d;
int max_num;
scanf_s("%d %d %d %d", &a, &b, &c, &d);
int tmp;
//找到最小的数
if (a > b) {
tmp = a; a = b; b = tmp; // a>b两个数据交换,则给a存储小的b
}
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);
system("pause");
return 0;
}
12. 有4个圆塔,圆心分别为(2,2)、(-2,2)、(-2,-2)、(2,-2),圆半径为1。这4个塔的高度为10m,塔以外无建筑物。今输入任一点的坐标,求该点的建筑高度(塔外的高度为零)。
#include <stdio.h>
#include <math.h>
void main()
{
int h;
double x, y, m, n, r;
printf("Please input a coordinate (x,y):");
scanf_s("%lf,%lf", &x, &y);
if (fabs(x) > 3 || fabs(y) > 3) {
h = 0;
printf("The height of the coordinate(%f,%f):h=%d\n", x, y, h);
return 0;
}
m = fabs(x) - 2; n = fabs(y) - 2;
r = sqrt(m * m + n * n);
if (r > 1)
h = 0;
else
h = 10;
printf("The height of the coordinate(%f,%f):h=%d\n", x, y, h);
system("pause");
return 0;
}
数据结构
数据结构是计算机科学中的一个核心概念,它涉及到计算机中数据的存储、组织和管理方式。以下是关于数据结构的详细解释:
- 定义:
- 数据结构是计算机存储、组织数据的方式。具体地说,数据结构是相互之间存在一种或多种特定关系的数据元素的集合,它研究的是数据的逻辑结构和数据的物理结构以及它们之间的相互关系。
- 要素:
- 数据结构的两个基本要素是:数据元素的集合和关系的集合。数据元素是数据结构的基本单位,而关系则定义了这些元素如何相互关联。
- 分类:
- 数据结构可以按数据元素之间关系的不同进行分类,主要分为四类:
- 集合结构:数据元素属于同一个集合。
- 线性结构:数据元素之间存在着一对一的关系。常见的有链表、队列、栈等。
- 树形结构:数据元素之间存在着一对多的关系。常见的有二叉树、二叉查找树、平衡二叉查找树等。
- 图形结构:数据元素之间存在着多对多的关系。
- 按照存储方式的不同,数据结构可以分为顺序存储结构和链式存储结构:
- 顺序存储结构:数据元素在存储器中是连续存储的,可以用相对位转走来表示数据元素之间的逻辑结构,如顺序表、队列、栈等。
- 链式存储结构:每个数据元素里设置了一个指针用来指向另一个元素的存储地址,以此来表示数据元素之间的逻辑结构。
- 逻辑关系与存储关系:
- 数据的逻辑结构指的是数据元素之间的逻辑关系,而数据的存储结构则指的是数据元素在计算机中的表示和存储方式。这两者密切相关,是设计数据结构时需要考虑的重要因素。
- 应用:
- 数据结构在编程和软件开发中扮演着至关重要的角色。通过选择合适的数据结构,可以提高程序的运行效率、减少存储空间的使用,并使得代码更加清晰、易于维护。数据结构的选择和设计是程序设计的基础和关键。
- 常用数据结构:
- 在实际编程中,常用的数据结构包括数组、链表、栈、队列、树和图等。这些数据结构各有特点,适用于不同的应用场景。例如,数组适用于需要快速访问任意元素的情况,链表适用于需要动态调整元素数量的情况,树和图则适用于表示具有层次或网状关系的数据。
- 设计原则:
- 在设计数据结构时,需要考虑数据元素的特性、操作的需求以及存储空间的限制等因素。设计良好的数据结构应该具有高效性、稳定性和可扩展性等特点,能够满足实际应用的需求。
总之,数据结构是计算机科学中不可或缺的一部分,它涉及到计算机中数据的存储、组织和管理方式。通过学习和掌握数据结构的相关知识,可以更好地理解和应用计算机技术解决实际问题。
数组
数组(Array)是一种重要的数据结构,主要用于存储具有相同数据类型的多个元素的集合。下面我将从多个方面对数组进行详细介绍:
定义与性质
定义:数组是有序的元素序列,用于存储多个相同类型的数据。这些有序排列的同类数据元素的集合称为数组。
性质:
- 定长性:当数组被声明后,空间所能存放的元素个数就是确定的。虽然可以对数组进行扩容操作,但原始数组的大小在声明时就已经确定。
- 连续性:数组在存放时必须在该空间的最前面连续存放,这意味着数组中的元素在内存中是连续排列的。
- 边界检查:数组具有边界检查功能,当索引不在数组范围内时会抛出异常(如C#中的IndexOutOfRangeException或Java中的ArrayIndexOutOfBoundsException)。
分类
- 一维数组:由一组具有相同数据类型的数据按照一定顺序排列而成的线性表。
- 二维数组:由若干个一维数组组成的表格状数据结构,可以看作是一个行列都固定的矩阵。
- 稀疏数组:当数组中大部分元素为0或同一值时,采用压缩存储方式,只记录不同值的元素和其位置,以节省存储空间和提高运算效率。
- 动态数组:在插入或删除元素时可以自动改变大小的一维数组,具有灵活性和高效性。
- 布尔数组:由若干个布尔值组成的数组,可以用来表示某些问题的真值表或状态表。
应用与初始化
- 一维数组:通常用于存储一组具有相同属性的数据。例如,在C语言中可以使用int a[10];声明一个可以存储10个整数的数组。初始化时,可以逐个赋值,也可以一次性赋值(如int a[10] = {0, 1, 2, …};)。
- 二维数组:常用于表示表格或矩阵形式的数据。在C语言中,可以使用int a[3][4];声明一个3行4列的二维数组。初始化时,可以分行赋值(如int a[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};)。
注意事项
- 在使用数组时,要注意不要越界访问,即不要使用超出数组范围的索引。这可能会导致程序崩溃或产生不可预料的结果。
- 在声明数组时,要根据实际需要选择合适的大小。过大的数组可能会浪费内存空间,而过小的数组则可能无法满足存储需求。
- 在某些编程语言中(如C++和Java),数组的大小可以是动态的,即可以在运行时根据需要调整数组的大小。但在某些其他编程语言中(如C),数组的大小在声明时就必须确定,并且之后不能更改。
总结
数组是一种非常重要的数据结构,在编程中有着广泛的应用。通过合理地使用数组,可以高效地处理大量具有相同类型的数据,提高程序的运行效率。同时,也要注意在使用数组时遵守相关的规则和注意事项,以确保程序的正确性和稳定性。
链表
链表是一种物理存储单元上非连续、非顺序的存储结构,其特点是通过链表中的指针链接次序来实现数据元素的逻辑顺序。以下是关于链表的详细介绍:
链表的基本概念
链表由一系列结点(链表中每一个元素称为结点)组成,这些结点可以在运行时动态生成。
每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
链表的特点
动态分配:链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。结点可以在需要时动态生成,不需要预先知道数据的大小。
插入和删除效率高:由于链表在物理存储上不是连续的,因此在进行插入和删除操作时,不需要移动大量元素,从而达到较高的效率。特别是在链表头部进行插入和删除操作时,时间复杂度可以达到O(1)。
顺序访问:链表只能从头结点开始,顺序访问每个结点,直到找到目标数据或遍历完整个链表。因此,访问链表中的特定元素或查找某个元素可能需要O(n)的时间复杂度。
空间开销:由于每个结点都需要存储指向下一个结点的指针,因此链表的空间开销相对较大。
链表的类型
链表有多种类型,包括单向链表、双向链表和循环链表等。其中,单向链表是最简单的形式,每个结点只有一个指向下一个结点的指针;双向链表则每个结点有两个指针,分别指向前一个结点和后一个结点;循环链表则是尾结点的指针指向头结点,形成一个环状结构。
链表的应用场景
链表在计算机科学中被广泛应用于各种场景,如文件系统的目录结构、网页浏览器的历史记录、电话簿中的联系人列表、音乐播放器的播放列表以及操作系统的进程管理等。这些应用场景都充分利用了链表动态分配、插入和删除效率高的特点。
总结:链表作为一种重要的数据结构,在实际应用中具有广泛的用途。它克服了数组需要预先知道数据大小的缺点,实现了灵活的内存动态管理。然而,链表也失去了数组随机读取的优点,并且在空间开销上相对较大。因此,在选择使用链表还是其他数据结构时,需要根据具体的应用场景和需求进行权衡。