C语言程序设计第五版谭浩强课后答案

目录

简答题

什么是程序?什么是程序设计?

为什么需要计算机语言?高级语言有哪些特点?

正确理解以下名词及其含义:

什么是算法?试从日常生活中找3个例子,描述它们的算法

什么叫结构化的算法?为什么要提倡结构化的算法?

试述3种基本结构的特点,请另外设计两种基本结构(要符合基类结构的特点)。

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

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

什么是文件型指针?通过文件指针访问文件有什么好处?

对文件的打开与关闭的含义是什么?为什么要打开和关闭文件?

代码题

编写一个C程序,运行时输出Hello World!

编写一个C程序,运行时输出以下图形:平行四边形*

编写一个C程序,运行时输人a,b,c三个值,输出其中值最大者。

有两个瓶子A和B,分别盛放醋和酱油,要求将他们互换(即A瓶原来盛醋,现在盛酱油,B瓶则相反)。

依次将10个数输入,要求输出其中最大的数。

有3个数a,b,c, 要求按大小顺序把他们输出。

求1 + 2 + 3 + … + 100。

判断一个数n能否同时被3和5整除。

求两个数m和n的最大公约数

求方程 ax^2 + bx + c = 0的根。分别考虑:有两个不相等的实根;有两个相等的实根;

假如我国国民生产总值的年增长率为7%, 计算10年后我国国民生产总值与现在相比增长多少百分比。计算公式为p = (1+r)^n,其中r为年增长率,n为年数,p为与现在相比的倍数。

存款利息的计算。有1000元,想存5年,可按以下5种办法存:

购房从银行贷了一笔款d,准备每月还款额为p,月利率为r,计算多少月能还清。设d为300 000元,p为6000元,r为1%。对求得的月份取小数点后一位,对第2位按四舍五人处理。

分析下面的程序:

用下面的scanf 函数输人数据,使a=3,b=7,x=8.5,y=71. 82,cl=‘A’,c2=‘a’。在键盘上应如何输入?

请编程序将“China"译成密码,密码规律是:用原来的字母后面第4个字母代替原来的字母。例如,字母“A”后面第4个字母是“E”,用“E”代替“A”。因此,“China"应译为“Glmre”。请编一程序,用赋初值的方法使cl,c2,c3,c4,c5这5个变量的值分别为’C’,‘h’,‘i’,‘n’,‘a’ ,经过运算,使c1,c2,c3,c4,c5 分别变为’G’,‘l’,‘m’,‘r’,‘e’。分别用putchar函数和printf函数输出这5个字符。

设圆半径r=1.5,圆柱高h=3,求圆周长、圆面积、圆球表面积、圆球体积、圆柱体积。用scanf输人数据,输出计算结果,输出时要求有文字说明,取小数点后2位数字。请编程序。

编程序,用getchar函数读人两个字符给c1和c2,然后分别用putchar函数和printf函数输出这两个字符。思考以下问题:

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

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

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

7. 有一个函数,

给出一百分制成绩,要求输出成绩等级’A’、‘B’、‘C’、‘D’、‘E’。 90分以上为’A’,8089分为’B’,7079分为’C’ ,60~69分为’D’ ,60分以下为’E’。

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

企业发放的奖金根据利润提成。利润I低于或等于100000元的,奖金可提成10%;利润高于100000元,低于200000元(1000001000000时,超过1000000元的部分按1%提成。从键盘输入当月利润I,求应发奖金总数。要求:(1) 使用if语句编写程序。(2) 使用switch语句编写程序。≤200000)时,低于100000元的部分按10%提成,高于100000元的部分,可提成7.>

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

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

输人两个正整数m和n,求其最大公约数和最小公倍数

输人一行字符,分别统计出其中英文字母、空格、数字和其他字符的个数。

求S n =a+aa+aaa+… (n 个 a )之值,其中a是一个数字,n表示a的位数,n由键盘输入。例如:2+22+222+2222+22222 (此时n=5)

求  20     ∑   n! (即求1!+2!+3!+4!+…+20!)。    n=1

7.​编辑

输出所有的“水仙花数”,所谓“水仙花数”是指一个3位数,其各位数字立方和等于该数本身。例如,153是水仙花数,因为153=1*+5*+3。

一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如,6的因子为1,2,3,而6=1+2+3,因此6是“完数”。编程序找出1000之内的所有完数,并按下面格式输出其因子:6 its factors are 1,2,3

有一个分数序列,求出这个数列的前20项之和。​编辑

一个球从100m高度自由落下,每次落地后反弹回原高度的一半,再落下,再反弹。求它在第10次落地时共经过多少米,第10次反弹多高。

猴子吃桃问题。猴子第1天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个。第2天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第10天早上想再吃时,就只剩一个桃子了。求第1天共摘多少个桃子。

用迭代法求x=sqrt{a} 

用牛顿迭代法求下面方程在1.5附近的根:

用二分法求下面方程在(-10,10)的根:​编辑

输出以下图案:

两个乒乓球队进行比赛,各出3人。甲队为A,B,C 3人,乙队为X,Y,Z 3人。已抽签决定比赛名单。有人向队员打听比赛的名单,A说他不和X比,C说他不和X,Z比,请编程序找出3对赛手的名单。

用筛选法求100之内的素数

用选择法对10个整数排序

求一个3 X 3的整形矩阵对角线元素之和

有一个已经排好序的数组,要求输入一个数后,按原来顺序的规律将它插入数组中

将一个数组中的值按逆序重新存放。例如:原来顺序为8,6,5,4,1。要求改为1,4,5,6,8。

输出一下的杨慧三角(要求输出10行)

输出"魔方阵"。所谓魔方阵是指这样的方阵,它的每一行、每一列和对角线之和均相等。例如:

找出一个二维数组中的鞍点,即该位置上的元素在该行上最大,在该列上最小,也可能没有鞍点。

有15个数按由大到小顺序存放在一个数组中,输入一个数,要求用折半查找法找出该数是数组中第几个元素的值。如果该数不在数组中,则输出"无此数"。

有一篇文章,共有3行文字,每行有80个字符。要求分别统计出其中英文大写字母、小写字母、数字、空格以及其他字符的个数。

输出一下图案:

有一行电文,以按下面规律译成密码:

编一程序,将两个字符串连接起来,不要用strcat函数

编写一个程序,将连个字符串s1和s2比较,如果s1 > s2,输出一个整数;若s1 = s2,输出0;若s1 < s2,输出一个负数。不要用strcpy函数。两个字符串用gets函数读入。输出的正数或负数的绝对值应是相比较的两个字符串相对应字符的ASCII码的差值。例如,“A"和“C”相比,由于"A” < “C”,应输出负数,同时由于‘A’与‘C’的ASCII码差值为2,因此应输出"-2"。同理:“And”和"Aid"相比较,根据第2个字符比较结果,“n"比"i"大5,因此应输出"5”。

编写一个程序,将字符数组s2中的全部字符复制到字符数组s1中,不用strcpy函数。复制时,‘\0’也要赋值过去。’\0’之后的字符不复制。

写两个函数,分别求两个整数的最大公约数和最小公倍数,用主函数调用这两个函数,并输出结果。两个整数由键盘输人。

求方程 {ax}^2+bx+c=0的根,用3个函数分别求当:  b^2-4ac大于0、等于0和小于0时的根并输出结果。从主函数输入a,b,c的值。

写一个判素数的函数,在主函数输人一个整数,输出是否为素数的信息。

写一个函数,使给定的一个3X3的二维整型数组转置,即行列互换。

写一个函数,使输人的一个字符串按反序存放,在主函数中输入和输出字符串。

写一个函数,将两个字符串连接。

写一个函数,将一个字符串中的元音字母复制到另一字符串,然后输出。

写一个函数,输人一个4位数字,要求输出这4个数字字符,但每两个数字间空一个空格。如输人1990,应输出“1 9 9 0”。

编写一个函数,由实参传来一个字符串,统计此字符串中字母、数字、空格和其他字符的个数,在主函数中输人字符串以及输出上述的结果。

写一个函数,输人一行字符,将此字符串中最长的单词输出。

写一个函数,用“起泡法”对输人的10个字符按由小到大顺序排列。

用牛顿迭代法求根。方程为ax^3+bx^2 +cx+d=0,系数a,b,c,d的值依次为1,2,3,4,由主函数输人。求x在1附近的一个实根。求出根后由主函数输出。

用递归方法求n阶勒让德多项式的值,递归公式为

输人10个学生5门课的成绩,分别用函数实现下列功能:①计算每个学生的平均分;②计算每门课的平均分;③找出所有50个分数中最高的分数所对应的学生和课程;④计算平均分方差:

写几个函数:①输人10个职工的姓名和职工号;②按职工号由小到大顺序排序,姓名顺序也随之调整;③要求输人一个职工号,用折半查找法找出该职工的姓名,从主函数输人要查找的职工号,输出该职工姓名。

写一个函数,输人一个十六进制数,输出相应的十进制数。

用递归法将一个整数n转换成字符串。例如,输人483,应输出字符串”483”。n的位数不确定,可以是任意位数的整数。

给出年、月、日,计算该日是该年的第几天。

输入3个整数,要求按由小到大的顺序输出。

输入3个字符串,要求按由小到大的顺序输出。

输入10个整数,将其中最小的数与第一个数对换, 把最大的数与最后一个数对换。写3个函数:

有n个整数,使前面各数顺序向后移m个位置,最后m个数变成最前面m个数,见图8.43。 写一函数实现以上功能,在主函数中输人n个整数和输出调整后的n个数。

有n个人围成一圈,顺序排号。从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位。

写一函数,求一个字符串的长度。在main函数中输入字符串,并输出其长度。

有一字符串,包含n个字符。写一函数,将此字符串中从第m个字符开始的全部字符复制成为另一个字符串。

输入一行文字,找出其中大写字母、小写字母、空格、数字以及其他字符各有多少。

写一函数,将一个3x3的整型矩阵转置。

将一个5x5的矩阵中最大的元素放在中心,4个角分别放4个最小的元素(顺序为从左到右,从上到下依次从小到大存放),写一函数实现之。用main函数调用。

在主函数中输入10个等长的字符串。用另一函数对它们排序。然后在主函数输出这10个已排好序的字符串。

用指针数组处理上一题目,字符串不等长。

写一个用矩形法求定积分的通用函数,分别求

将n个数按输入时顺序的逆序排列,用函数实现。

有一个班4个学生,5门课程。①求第1门课程的平均分;②找出有两门以上课程不及格的学生,输出他们的学号和全部课程成绩及平均成绩;③找出平均成绩在90分以上或全部课程成绩在85分以上的学生。分别编3个函数实现以上3个要求。

输入一个字符串,内有数字和非数字字符,例如:A123x456 17960? ,302tab5876,将其中连续的数字作为一个整数,依次存放到一数组a中。例如,123放在a[0],456放在a1[1]…统计共有多少个整数,并输出这些数。

写一函数,实现两个字符串的比较。即自己写一个strcmp函数,函数原型为int strcmp(char * p1 ,char * p2); 设p1指向字符串s1, p2指向字符串s2。要求当s1=s2时,返回值为0;若s1≠s2,返回它们二者第1个不同字符的ASCII码差值(如"BOY"与"BAD" ,第2个字母不同,0与A之差为79- 65=14)。如果s1>s2,则输出正值;如果s1,则输出负值。<>

编一程序,输入月份号,输出该月的英文月名。例如,输人3,则输出"March" ,要求用指针数组处理。

1) 编写一个函数new,对n个字符开辟连续的存储空间,此函数应返回一个指针(地址),指向字符串开始的空间。new(n)表示分配n个字节的内存空间。(2)写一函数free,将前面用new函数占用的空间释放。free§表示将p(地址)指向的单元以后的内存段释放。

用指向指针的指针的方法对5个字符串排序并输出。

用指向指针的指针的方法对n个整数排序并输出。要求将排序单独写成一个函数。n个整数在主函数中输入,最后在主函数中输出。

定义一个结构体变量(包括年、月、日)。计算该日在本年中是第几天,注意闰年问题。

写一个函数days,实现第1 题的计算。由主函数将年、月、日传递给days函数,计算后将日子数传回主函数输出。

编写一个函数print,打印一个学生的成绩数组,该数组中有5个学生的数据记录,每个记录包括num,name,score[3],用主函数输人这些记录,用print函数输出这些记录。

在上题的基础上,编写一个函数input,用来输人5个学生的数据记录。

有10个学生,每个学生的数据包括学号、姓名、3门课程的成绩,从键盘输人10个学生数据,要求输出3门课程总平均成绩,以及最高分的学生的数据(包括学号、姓名、3门课程成绩、平均分数)。

13个人围成一圈,从第1个人开始顺序报号1,2,3。凡报到3者退出圈子。找出最后留在圈子中的人原来的序号。要求用链表实现。

在第9章例9.9和例9.10的基础上,写一个函数del,用来删除动态链表中指定的节点

写一个函数insert,用来向一个动态链表插入结点

综合本章例9.9(建立链表的函数creat)、例9.10(输出链表的函数print)和本章习题第7题(删除链表中结点的函数del)、第8题(插入结点的函数insert),再编写一个主函数,先后调用这些函数。用以上5个函数组成一个程序,实现链表的建立、输出、删除和插入,在主函数中指定需要删除和插人的结点的数据。

已有a,b两个链表,每个链表中的结点包括学号、成绩。要求把两个链表合并, 按学号升序排列。

有两个链表a和b,设结点中包含学号、姓名。从a链表中删去与b链表中有相同学号的那些结点。

建立一个链表,每个结点包括:学号、姓名、性别、年龄。输入一个年龄,如果链表中的结点所包含的年龄等于此年龄,则将此结点删去。

从键盘输入一个字符串,将其中的小写字母全部转换成大写字母,然后输出到一个磁盘文件test中保存,输入的字符串以“!”结束。

有两个磁盘文件A和B,各存放一行字母,今要求把这两个文件中的信息合并(按字母顺序排列),输出到一个新文件C中去。

有5个学生,每个学生有3门课程的成绩,从键盘输人学生数据(包括学号,姓名,3门课程成绩),计算出平均成绩,将原有数据和计算出的平均分数存放在磁盘文件stud中。

将上题stud文件中的学生数据,按平均分进行排序处理,将已排序的学生数据存入一个新文件stu_ sort 中。

将上题已排序的学生成绩文件进行插人处理。插人一个学生的3门课程成绩,程序先计算新插人学生的平均成绩,然后将它按成绩高低顺序插入,插入后建立一个新文件。

将上题结果仍存人原有的stu_sort 文件而不另建立新文件。

有一磁盘文件employee,内存放职工的数据。每个职工的数据包括职工姓名、职工号、性别、年龄、住址、工资、健康状况、文化程度。今要求将职工名、工资的信息单独抽出来另建一个简明的职工工资文件。

从上题的“职工工资文件”中删去一个职工的数据,再存回原文件。

从键盘输人若干行字符(每行长度不等),输人后把

它们存储到一磁盘文件中。再从该文件中读入这些数据,将其中小写字母转换成大写字母后在显示屏上输出。


简答题

什么是程序?什么是程序设计?

  • 程序:就是一组能识别和执行的指令,每一条指令使计算机执行特定的操作

  • 程序设计:是指从确定任务到得到结果、写出文档的全过程

为什么需要计算机语言?高级语言有哪些特点?

为什么需要计算机语言:计算机语言解决了人和计算机交流是的语言问题,使得计算机和人都能识别

高级语言有哪些特点:
2.1 高级语言的数据结构要比汇编和机器语言丰富;
2.2 高级语言与具体机器结构的关联没有汇编以及机器语言密切;
2.3 高级语言更接近自然语言更容易掌握;
2.4 高级语言编写的程序要经过编译或解释计算机才能执行;

正确理解以下名词及其含义:

(1)源程序,目标程序,可执行程序。
​源程序:指未编译的按照一定的程序设计语言规范书写的文本文件,是一系列人类可读的计算机语言指令

目标程序:为源程序经编译可直接被计算机运行的机器码集合,在计算机文件上以.obj作扩展名

可执行程序:将所有编译后得到的目标模块连接装配起来,在与函数库相连接成为一个整体,生成一个可供计算机执行的目标程序,成为可执行程序

(2)程序编辑,程序编译,程序连接。
程序编辑:上机输入或者编辑源程序。

程序编译:

先用C提供的“预处理器”,对程序中的预处理指令进行编译预处理
对源程序进行语法检查, 判断是否有语法错误,直到没有语法错误未知
编译程序自动把源程序转换为二进制形式的目标程序
程序连接:将所有编译后得到的目标模块连接装配起来,在与函数库相连接成为一个整体的过程称之为程序连接

(3)程序,程序模块,程序文件。
程序:一组计算机能识别和执行的指令,运行于电子计算机上,满足人们某种需求的信息化工具

程序模块:可由汇编程序、编译程序、装入程序或翻译程序作为一个整体来处理的一级独立的、可识别的程序指令

程序文件:程序的文件称为程序文件,程序文件存储的是程序,包括源程序和可执行程序

(4)函数,主函数,被调用函数,库函数。
函数:将一段经常需要使用的代码封装起来,在需要使用时可以直接调用,来完成一定功能

主函数:又称main函数,是程序执行的起点

被调用函数:由一个函数调用另一个函数,则称第二个函数为被调用函数

库函数:一般是指编译器提供的可在c源程序中调用的函数。可分为两类,一类是c语言标准规定的库函数,一类是

​ 编译器特定的库函数

(5)程序调试,程序测试。
程序调试:是将编制的程序投入实际运行前,用手工或编译程序等方法进行测试,修正语法错误和逻辑错误的过程

程序测试:是指对一个完成了全部或部分功能、模块的计算机程序在正式使用前的检测,以确保该程序能按预定的方式正确地运行

什么是算法?试从日常生活中找3个例子,描述它们的算法

算法:简而言之就是求解问题的步骤,对特定问题求解步骤的一种描述。

比如生活中的例子:

考大学:首先填报志愿表、交报名费、拿到准考证、按时参加考试、收到录取通知书、按照日期到指定学校报到。

去北京听演唱会:首先在网上购票、然后按时坐车到北京,坐车到演唱会会场。

把大象放进冰箱:先打开冰箱门,然后将大象放进冰箱,关冰箱。

什么叫结构化的算法?为什么要提倡结构化的算法?

结构化算法:由一些顺序、选择、循环等基本结构按照顺序组成,流程的转移只存在于一个基本的范围之内。

结构化算法便于编写,可读性高,修改和维护起来简单,可以减少程序出错的机会,提高了程序的可靠性,保证了程序的质量,因此提倡结构化的算法。

试述3种基本结构的特点,请另外设计两种基本结构(要符合基类结构的特点)。

结构化程序设计方法主要由以下三种基本结构组成:

顺序结构:顺序结构是一种线性、有序的结构,它依次执行各语句模块
选择结构:选择结构是根据条件成立与否选择程序执行的通路。
循环结构:循环结构是重复执行一个或几个模块,直到满足某一条件位置
重新设计基本结构要满足以下几点:

只有一个入口
只有一个出口
结构内的每一部分都有机会执行到
结构内不存在死循环

什么叫结构化程序设计?它的主要内容是什么?

结构化程序设计(structured programming,简称SP)是进行以模块功能和处理过程设计为主的详细设计的基本原则。其概念最早由E.W.Dijikstra在1965年提出的。结构化程序设计思想确实使程序执行效率提高 ,是软件发展的一个重要的里程碑,它的主要观点是采用自顶向下、逐步求精的程序设计方法;各个模块通过“顺序、选择、循环”的控制结构进行连接,并且只有一个入口、一个出口 。

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

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

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

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

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

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

解析:

先进行括号内运算1+1,然后进行乘方运算得到结果4.
接下来与4相乘,得到结果16
因为乘法优先级大于加法,因此先进行5*3,得到结果15
最终相加得到结果31
结果:31

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

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

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

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

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

常见的逻辑运算符包括:&&、||、! 等种类

&&: 与是双目运算符,要求有两个运算对象,表示两个运算对象都成立,则结果为真,否则结果为假。

例如:(ay),表示(ay)同时成立则为真。

||:是双目运算符,要求有两个运算对象,表示两个运算对象只要任意一个成立,则结果为真,否则结果为假。

例如:(ay),表示(ay)两个对象中任意一个成立则结果为真。

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

例如:!(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语言中如何表示“真”和“假”?系统如何判断一个量的“真”和“假”?

在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)a + b > c && b == c -> 3+4>5&&4==5,解析: 3+4>5 优先3+4得到结果7,因此7>5结果为真; 4==5为假,一真一假逻辑与最终结果为假。答案: 0

(2)a || b + c && b - c -> 3||4 + 5 && 4-5,解析: 优先算术运算4+5得到7,非0则为真,4-5得到-1,非0则为真,接下来逻辑与判断,最终逻辑或判断。答案: 1

(3)!(a > b) && !c || 1 -> !(3>4) && !5 || 1  ,解析 : !优先级最高,!(3>4)最终结果为真,!5为假; 其次 &&,真&&假得到假,最终||,1为真,假或真为真。答案: 1

(4)!(x = a) && (y = b) && 0 -> !(x=3) && (y=4)&&0  解析: 这里&&优先级最低是最后一个逻辑运算,因此不管如何,最终&&0,则肯定为假。答案: 假-0

(5)!(a + b) + c - 1 && b + c / 2 -> !(3+4)+5-1 && 4+5/2   解析: 在vs中优先对(a+b)取非得到0,0+5-1结果为4,因此最终为真(此题涉及不同平台结果不同的问题,因为在有的平台下编译器会优先算术运算,则最终取非得到结果为假)。答案: ** 1

什么是文件型指针?通过文件指针访问文件有什么好处?

答:缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针”。每个被使用的文件都在内存中开辟一个相应的文件信息区,用来存放文件的有关信息(如文件的名字、文件状态及文件当前位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是由系统声明的,取名为FILE。

通过文件指针访问文件的好处是:可以随机访问文件,有效表示数据结构,动态分配内存,方便使用字符串,有效使用数组。

对文件的打开与关闭的含义是什么?为什么要打开和关闭文件?

答:”打开“是指为文件建立相应的信息区(用来存放有关文件的信息)和文件缓冲区(用来暂时存放输人输出的数据)。

”关闭“是指撤销文件信息区和文件缓冲区,使文件指针变量不再指向该文件,显然就无法进行对文件的读写了。

代码题

编写一个C程序,运行时输出Hello World!

代码示例:
#include

int main()
{
    printf("%s\n", "Hello World!");
    return 0;
}
 


编写一个C程序,运行时输出以下图形:平行四边形*

****

 ****

 ​ ****

  ​ ****

代码示例:
#include

int main()
{
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < i; j++)
        {
            printf("%s", "  ");
        }
        printf("%s\n", "*****");
    }
    return 0;
}

编写一个C程序,运行时输人a,b,c三个值,输出其中值最大者。

代码示例:
#include

int main()
{
    int a, b, c, max;
    printf("请输入三个数:\n");

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

    if (c > max)
    {
        max = c;
    }
    printf("三个数中最大的数为:%d", max);
    return 0;

}

有两个瓶子A和B,分别盛放醋和酱油,要求将他们互换(即A瓶原来盛醋,现在盛酱油,B瓶则相反)。

begin
    醋 => A
    酱油 => B
    A => C
    B => A
    C => B
end

依次将10个数输入,要求输出其中最大的数。

begin
    1 => i
    0 => max
    while i < 10
    {
        输入一个整数data
        if data > max
        {
            data => max
        }
    }

    print max
end

有3个数a,b,c, 要求按大小顺序把他们输出。

begin
    input a
    input b
    input c
    
    if a > b
    {
        a => t
        b => a
        t => b
    }
    
    if c > a
    {
        c => t
        a => c
        t => a
    }
    
    if c > b
    {
        c => t
        b => c
        t => b
    }
    
    print a
    print b
    print c
end


求1 + 2 + 3 + … + 100。

begin
    1 => i
    0 => sum
    while i <= 100
    {
        sum + i => sum
        i + 1 => i
    }

    print sum
end

判断一个数n能否同时被3和5整除。

begin
    input n
    if n % 3 == 0
    {
        if n % 5 == 0
        {
            print n能被3和5整除
        }
        else
        {
            print n不能被3和5整除
        }
    }
    else
    {
            print n不能被3和5整除
    }
end


求两个数m和n的最大公约数

begin
    input m
    input n
    
    if m > n
    {
        m => t
        n => m
        t => n
    }
    
    while n != 0
    {
        m % n => r
        m => n
        r => n
    }
    
    print m
end


求方程 ax^2 + bx + c = 0的根。分别考虑:有两个不相等的实根;有两个相等的实根;

begin
    input a
    input b
    input c
    
    b*b - 4*a*c => p
    if p < 0
    {
        print 方程没有实根
    }
    
    if p == 0
    {
        print 方程有一个实根 -b/2a
    }
    
    if p > 0
    {
        print 方程有两个实根:
        print x1 = {-b + sqrt(b^2 - 4ac)}/2a
        print x1 = {-b - sqrt(b^2 - 4ac)}/2a
    }
end

假如我国国民生产总值的年增长率为7%, 计算10年后我国国民生产总值与现在相比增长多少百分比。计算公式为p = (1+r)^n,其中r为年增长率,n为年数,p为与现在相比的倍数。

题目解析:
此题的关键主要是利用数学库math中pow函数进行计算,若不熟悉可以查阅帮助文档,查看pow函数的用法。
代码示例:
#include
#include
int main()
{
    float p, r, n;
    r = 0.07;
    n = 10;
    p = pow(1 + r, n);
    printf("p=%f\n", p);
    return 0;
}
 

存款利息的计算。有1000元,想存5年,可按以下5种办法存:

(1)一次存5年期

(2)先存2年期,到期后将本息再存3年期

(3)先存3年期,到期后将本息再存2年期

(4)存1年期,到期后将本息再存1年期,连续存5次

(5)存活期存款,活期利息每一季度结算一次

2017年银行存款利息如下:

1年期定期存款利息为1.5%;

2年期定期存款利息为2.1%;

3年期定期存款利息为2.75%;

5年期定期存款利息为3%;

活期存款利息为0.35%(活期存款每一-季度结算一-次利息)

如果r为年利率,n为存款年数,则计算本息的公式如下:

1年期本息和: P= 1000* (1+r);

n年期本息和: P= 1000* (1+n* r);

存n次1年期的本息和: P=1000* (1+r)^n

活期存款本息和: P= 1000 *(1+r /4 ^4 

说明: 1000 *(1+r /4 ^4 是一个季度的本息和。

题目解析:
理解题意很关键,其次就是利用数学库math中pow函数进行幂次方计算

代码示例:
#include
#include

int main()
{
    float r5, r3, r2, r1, r0, p, p1, p2, p3, p4, p5;
    p = 1000;
    r5 = 0.0585;
    r3 = 0.054;
    r2 = 0.0468;
    r1 = 0.0414;
    r0 = 0.0072;

    p1 = p*((1 + r5) * 5);                // 一次存5年期  
    p2 = p*(1 + 2 * r2)*(1 + 3 * r3);     // 先存2年期,到期后将本息再存3年期  
    p3 = p*(1 + 3 * r3)*(1 + 2 * r2);     // 先存3年期,到期后将本息再存2年期  
    p4 = p*pow(1 + r1, 5);                // 存1年期,到期后将本息存再存1年期,连续存5次  
    p5 = p*pow(1 + r0 / 4, 4 * 5);        // 存活期存款。活期利息每一季度结算一次  
    printf("p1=%f\n", p1);       // 输出按第1方案得到的本息和  
    printf("p2=%f\n", p2);       // 输出按第2方案得到的本息和  
    printf("p3=%f\n", p3);       // 输出按第3方案得到的本息和  
    printf("p4=%f\n", p4);       // 输出按第4方案得到的本息和  
    printf("p5=%f\n", p5);       // 输出按第5方案得到的本息和  
    return 0;
}

购房从银行贷了一笔款d,准备每月还款额为p,月利率为r,计算多少月能还清。设d为300 000元,p为6000元,r为1%。对求得的月份取小数点后一位,对第2位按四舍五人处理。

提示:计算还清月数m的公式如下:C语言程序设计第五版谭浩强课后答案_第1张图片

可以将公式改写为:C语言程序设计第五版谭浩强课后答案_第2张图片

C的库函数中有求对数的函数log10,是求以10为底的对数,log( p )表示log p。

题目解析:
该题的关键主要是利用数学函数库中的log函数进行求解,然后月份要求按照小数点后一位进行四舍五入进行处理,只需要在输出时进行格式控制即可。

代码示例:
#include
#include

int main()
{
    float d = 300000, p = 6000, r = 0.01, m;
    m = log10(p / (p - d*r)) / log10(1 + r);
    printf("m = %3.1f\n", m);
    return 0;
}

分析下面的程序:

#include
int main()
{
    char c1, c2;
    c1 = 97;
    c2 = 98;
    printf("c1=%c, c2=%c\n", c1, c2);
    printf("c1=%d, c2=%d\n", c1, c2);
    return 0;
}

(1)运行时会输出什么信息?为什么?

​ 答:c1=97, c2=98

因为第一行十一字符形式输出,所以会吧97和98当作相依字符的ascii值,输出的时候按照字符显示,第二行由于是以整形输出,所以输出对应整数值

(2)如果将程序第4,5行改为c1 = 197;c2 = 198;运行时会输出什么信息?为什么?

​ 答: 会输出:

C语言程序设计第五版谭浩强课后答案_第3张图片

因为c1和c2为char类型,其保存的数据范围为-128~127,当c1=197,c2=198时,已经超出了char类型所能够保存的数据范围,此时会进行相应的转换为c1=-59,c2=-58,只是第一行以字符输出时,c1=-59,c2=-58为不可显示字符,所以输出了?,而第二行以整数输出时就进行了相应的整数显示。
(3)如果将程序第3行改为int c1, c2;运行时会输出什么信息?为什么?

​ 答: 会输出

C语言程序设计第五版谭浩强课后答案_第4张图片

因为c1和c2为int时,第二行以整形输出自然能够保存的下,但第一行以字符输出时,虽然数据int能够储存,但是在输出时需要准换为字符,转换后数据就超出了范围,此时c1=-59,c2=-58,两者都为不可显示字符,所以就显示了

用下面的scanf 函数输人数据,使a=3,b=7,x=8.5,y=71. 82,cl=‘A’,c2=‘a’。在键盘上应如何输入?

#include
int main()
{
    int a, b;
    float x, y;
    char c1, c2;
    scanf("a=%db=%d", &a, &b);
    scanf("%f%e",&x, &y);
    scanf("%c%c",&c1, &c2);
    return 0;
}
题目解析:
此题主要考察格式化输入,整形输入a和b时,必须按照a=3b=7的格式输入,浮点数输入时,%e代表科学记数法输入,字符输入c1和c2时,中间不能有任何空格
运行结果:


请编程序将“China"译成密码,密码规律是:用原来的字母后面第4个字母代替原来的字母。例如,字母“A”后面第4个字母是“E”,用“E”代替“A”。因此,“China"应译为“Glmre”。请编一程序,用赋初值的方法使cl,c2,c3,c4,c5这5个变量的值分别为’C’,‘h’,‘i’,‘n’,‘a’ ,经过运算,使c1,c2,c3,c4,c5 分别变为’G’,‘l’,‘m’,‘r’,‘e’。分别用putchar函数和printf函数输出这5个字符。

题目解析:
密码转换的关键在于相应字符的ascii加4进行赋值修改原来的字符即可,修改完成后即为相应的密码,在使用putchar和printf进行相应输出即可。
代码示例:
#include

int main()
{
    char c1 = 'C', c2 = 'h', c3 = 'i', c4 = 'n', c5 = 'a';
    c1 = c1 + 4;
    c2 = c2 + 4;
    c3 = c3 + 4;
    c4 = c4 + 4;
    c5 = c5 + 4;
    
    //使用putchar输出
    printf("使用putchar输出: ");
    putchar(c1);
    putchar(c2);
    putchar(c3);
    putchar(c4);
    putchar(c5);
    printf("\n");

    //使用printf输出
    printf("使用putchar输出: %c%c%c%c%c\n", c1, c2, c3, c4, c5);
    return 0;
}

设圆半径r=1.5,圆柱高h=3,求圆周长、圆面积、圆球表面积、圆球体积、圆柱体积。用scanf输人数据,输出计算结果,输出时要求有文字说明,取小数点后2位数字。请编程序。

题目解析:
此题主要理解圆柱的各种求法,其次要求取小数点后两位,只需在打印时进行格式控制即可。

代码示例:
#include

int main()
{
    float h, r, l, s, sq, vq, vz;
    float pi = 3.141526;
    printf("请输入圆半径r,圆柱高h∶");
    scanf("%f %f", &r, &h);               //要求输入圆半径r和圆柱高h 
    l = 2 * pi*r;                          //计算圆周长l
    s = r*r*pi;                          //计算圆面积s
    sq = 4 * pi*r*r;                       //计算圆球表面积sq
    vq = 3.0 / 4.0*pi*r*r*r;               //计算圆球体积vq
    vz = pi*r*r*h;                       //计算圆柱体积vz
    printf("圆周长为:       l=%6.2f\n", l);
    printf("圆面积为:       s=%6.2f\n", s);
    printf("圆球表面积为:   sq=%6.2f\n", sq);
    printf("圆球体积为:     v=%6.2f\n", vq);
    printf("圆柱体积为:     vz=%6.2f\n", vz);
    return 0;
}

编程序,用getchar函数读人两个字符给c1和c2,然后分别用putchar函数和printf函数输出这两个字符。思考以下问题:

(1) 变量cl和c2应定义为字符型、整型还是二者皆可?

(2) 要求输出cl和c2值的ASCII码,应如何处理?用putchar函数还是printf函数?

(3) 整型变量与字符变量是否在任何情况下都可以互相代替?如:char c1,c2;与int cl,c2;是否无条件地等价?

题目解析:
(1) 变量cl和c2应定义为字符型、整型还是二者皆可?

答:c1和c2 应定义为整形,因为定义为字符有可能返回的整数会超出字符的存储范围
(2) 要求输出cl和c2值的ASCII码,应如何处理?用putchar函数还是printf函数?

答:需要使用printf函数,打印是以整形形式打印
(3) 整型变量与字符变量是否在任何情况下都可以互相代替

答:不是,因为两者的存储范围不同,如果整数超出了字符的存储范围,则不能相互替换
代码示例:
int main()
{
    int c1, c2;
    printf("请输入两个字符c1,c2:");
    c1 = getchar();
    c2 = getchar();
    printf("用putchar语句输出结果为:");
    putchar(c1);
    putchar(c2);
    printf("\n");
    printf("用printf语句输出结果为:");
    printf("%c %c\n", c1, c2);
    return 0;
}

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

解题思路: 每个数字两两与剩余两个数字进行比较,若比剩下的两个数大则最大,例如:a>b && a>c则a是最大的

答案:

#include
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;
}

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

解题思路: 首先判断输入的数字是否大于1000且是正数,然后使用sqrt函数对数据进行取平方根,最主要的是最终在输出是调整输出格式,小数部分为0位,只需要正数部分,且整数部分不会超过4位,

答案:

#include
#include
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;
}

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

y = { x     ( x < 1 )

        2 x − 1    ( 1 < = x < 10 )

        3 x − 11 ( x > = 10 ) 

解题思路: 根据输入的不同x值进行条件判断,不同的条件采用不同的表达式进行计算即可

答案:

#include
int main()
{
    int x, y;
    scanf_s("%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. 有一个函数,

y = { − 1 ( x < 0 )

        0     ( x = 0 )

        1     ( x > 0 ) 

#include

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;
}


#include

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’,8089分为’B’,7079分为’C’ ,60~69分为’D’ ,60分以下为’E’。

解题思路: 根据不同的阶段成绩区间作为成绩的判断条件,属于哪个区间则输出对应等级即可

#include
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;
}

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

①求出它是几位数;
解题思路: 大于10000就是5位,否则大于1000就是四位,否则大于100是三位…

答案:

#include
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;
}
②分别输出每一位数字;
解题思路: 99999除以10000则输出9;9999除以1000则输出9,…

答案:

#include
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;
}
③按逆序输出各位数字,例如原数为321,应输出123。
解题思路: 思路与第二题相同,只不过将整个过程逆序即可

答案:

#include
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;
}

企业发放的奖金根据利润提成。利润I低于或等于100000元的,奖金可提成10%;利润高于100000元,低于200000元(1000001000000时,超过1000000元的部分按1%提成。从键盘输入当月利润I,求应发奖金总数。要求:(1) 使用if语句编写程序。(2) 使用switch语句编写程序。

(1) 使用if语句编写程序。
解题思路: 先将每一档的最大奖金算出来,在某一个区间时,则那小于这一档的奖金加上多出部分的奖金即可,例如:

先列出100000档的奖金是10000,则180000就是10000 + (180000-100000) * 0.075;

列出200000档的奖金是第一档加上多出100000部分的7.5%得到17500,则300000就是17500 + (300000-200000)*0.05;

答案:

#include
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) 使用switch语句编写程序。
解题思路: 与第一题思路没有太大差别,区别在于switch语句的case子句中需要是一个常量整数,并且switch中若子句中没有break将循序向下执行,直到遇到break才会跳出switch语句,如果这时候将利润除以10w,则得到09的数字,其中0表示小于10w,1表示介于1020w,2、3表示介于2040w,4、5表示介于4060w,6、7、8、9表示介于60~100w,否则就是大于100w

答案:

#include
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;
}

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

解题思路: 四个数中先找到最小的,剩下的三个数中找到第二小的,剩下的两个数中找到第三小的。

答案:

#include
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;
}

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

解题思路: 塔的半径为1m,则x坐标小于-3或者大于3,以及y坐标大于3或者小于-3则都是0m的建筑;其余则判断输入的坐标是否在各个圆塔的圆形范围内。该点到各个圆心的距离是否大于1,小于则是10m建筑,否则为0m建筑。

math.h中提供了fabs(double)求一个浮点数的绝对值,输入x,y坐标

fabs(fabs(x) - 2)得到输入坐标距离圆心的横轴距离;

fabs(fabs(y) - 2)得到舒服坐标距离圆心的纵轴距离;

三角形两个直角边长平方相加,然后开平方根得到第三边长,若大于1,则不再圆塔范围内。

答案:

#include
#include
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;
}

输人两个正整数m和n,求其最大公约数和最小公倍数

解析:该题题目直接使用“辗转相除法”来求解最大公约数,以除数和余数反复做除法运算,当余数为 0 时,就取得当前算式除数为最大公约数。

最大公约数和最小公倍数之间的性质:两个自然数的乘积等于这两个自然数的最大公约数和最小公倍数的乘积。所以,当我们求出最大公约数,就可以很轻松的求出最小公倍数。

代码示例:
#include
int main()
{
    int  p, r, n, m, temp;
    printf("请输入两个正整数n,m:");
    scanf("%d%d,", &n, &m);
    //调整n保存较大的值
    if (n < m)
    {
        temp = n;
        n = m;
        m = temp;
    }

    p = n * m;
    while (m != 0)
    {
        r = n % m;
        n = m;
        m = r;
    }
    printf("它们的最大公约数为:%d\n", n);
    printf("它们的最小公倍数为:%d\n", p / n);
    return 0;
}

输人一行字符,分别统计出其中英文字母、空格、数字和其他字符的个数。

解析:该题可以调用getchar函数,从stdin流中读入一个字符,当输入多个字符时,getchar()再执行时就会直接从缓冲区中读取了。等同于getc(stdin)。所以,我们循环调用getchar,直到将标准输入的内容读到换行符\n为止。同时判断,读取到的字符是英文字母、空格、数字或者其他字符,并计数;

代码示例:
#include

int main()
{
    char c;
    //定义eng_char为英文字母的个数,初始值为0
    //定义space_char为空格字符的个数,初始值为0
    //定义digit_char为数字字符的个数,初始值为0
    //定义other_char为其他字符的个数,初始值为0
    int eng_char = 0, space_char = 0, digit_char = 0, other_char = 0;
    printf("请输入一行字符:");
    while ((c = getchar()) != '\n')
    {
        if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')
        {
            eng_char++;
        }
        else if (c == ' ')
        {
            space_char++;
        }
        else if (c >= '0' && c <= '9')
        {
            digit_char++;
        }
        else
        {
            other_char++;
        }
    }

    printf("英文字母数量:%d\n空格数量:%d\n数字数量:%d\n其他字符数量:%d\n", eng_char, space_char, digit_char, other_char);
    return 0;
}

求S n =a+aa+aaa+… (n 个 a )之值,其中a是一个数字,n表示a的位数,n由键盘输入。例如:
2+22+222+2222+22222 (此时n=5)

解析:该题目可以将数字拆分为 a * 10^n + 前一个数字,例如:

2 = 2 * 10^0 + 0 : 默认2的前一个数字为0,也就是没有任何值

22 = 2 * 10^1 + 2 : 22的前一个数字为2

222 = 2*10^2 + 22 :222的前一个数字为22

以此类推…

所以,在每次循环的时候,需要保存下,上一次结果的值,方便下一次计算

还需要使用到C库当中使用的pow函数,来计算某个数的n次方,我们在该题目当中使用的是10的n次方,n随着循环的次数,以此递增。

代码示例:
#include
#include

int main()
{
    //n为a的个数
    int n;
    double a, prev_sum = 0.0, total_sum = 0.0;
    printf("请输入a的值以及n的值: ");
    scanf("%lf %d", &a, &n);
    //循环n次求总和
    for (int i = 0; i < n; i++)
    {
        prev_sum += a * pow(10, i); 
        total_sum += prev_sum;
    }
    printf("总和为:%lf\n", total_sum);
    return 0;
}

求  20
     ∑   n! (即求1!+2!+3!+4!+…+20!)。
    n=1

解析:该题需要从1循环到20,依次求出每一个数字阶乘的结果。所以在代码当中需要有两个循环,大循环从1到20,保证1到20个数字都被循环到,小循环里计算N阶乘,累加求和。注意:对于20的阶乘已经超出了int类型能过表示的数字范围,所以在代码当中使用double类型

代码示例:
#include

int main()
{
    double total_sum = 0;
    for(int i = 1; i <= 20; i++) 
    {
        double single_sum = 1;
        for (int j = i; j > 0; j--)
        {
            single_sum *= j;
        }
        total_sum += single_sum;
    }
    printf("1~20每个数字阶乘总和为:%lf\n",total_sum);
    return 0;
}


7.

#include

int main()
{
    double total_sum = 0, sum1 = 0, sum2 = 0, sum3 = 0.0;
    for (int k = 1; k <= 100; k++)
    {
        sum1 += k;
        //遍历50次就不在执行情况2
        if (k <= 50)
        {
            sum2 += k * k;
        }
        //遍历10次就不在执行情况3
        if (k <= 10)
        {
            sum3 += 1.0 / k;
        }
    }
    total_sum = sum1 + sum2 + sum3;
    printf("三种情况求和结果为:%lf\n", total_sum);
    return 0;
}

输出所有的“水仙花数”,所谓“水仙花数”是指一个3位数,其各位数字立方和等于该数本身。例如,153是水仙花数,因为153=1*+5*+3。

解析:从题目当中得到”水仙花数“为一个3位数,则范围确定为[100, 999]。另外需要获取该数字的百位数字,十位数字,个位数字相加起来等于该数本身,则我们需要使用到%除的方式,来获取每一个位权的数字。

代码示例:
#include

int main()
{
     //a表示百位数字,b表示十位数字,c表示各位数字
    int a, b, c;
    for (int i = 100; i <= 999; i++)
    {
        a = i / 100;
        b = (i / 10) % 10;
        c = i % 10;
        if (a * a * a + b * b * b + c * c * c == i)
        {
            printf("%d\n", i);
        }
    }
    return 0;
}

一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如,6的因子为1,2,3,而6=1+2+3,因此6是“完数”。编程序找出1000之内的所有完数,并按下面格式输出其因子:
6 its factors are 1,2,3

解析:因子:整数a除以整数b(b≠0) 的商正好是整数而没有余数,我们就说b是a的因子。整数n除以m,结果是无余数的整数,那么我们称m就是n的因子。 需要注意的是,唯有被除数,除数,商皆为整数,余数为零时,此关系才成立。因子是不包括自身的。举一个例子:20 = 4 * 5,则4和5就是20的因子,也被称之为因子

代码示例:
#include

int main()
{
    int data, fator, sum;      /* data表示要判断的数,fator表示因子,sum表示因子之和*/

    for (data = 2; data <= 1000; data++)
    {
        //1是所有整数的因子,所以因子之和从1开始
        sum = 1;
        for (fator = 2; fator <= data / 2; fator++)
        {
            /* 判断data能否被fator整除,能的话fator即为因子  因子不包括自身 */
            if (data % fator == 0)
            {
                sum += fator;
            }
        }
        // 判断此数是否等于因子之和 */
        if (sum == data)    
        {
            printf("%d its factors are 1, ", data);
            for (fator = 2; fator <= data / 2; fator++)
            {
                if (data % fator == 0)
                {
                    printf("%d, ", fator);
                }
            }
            printf("\n");
        }
    }
    return 0;
}

有一个分数序列,求出这个数列的前20项之和。

解析:从题目当中可以看出来,下一个分式当中的分子为上一个分式中分子和分母的和,分母为上一个分式的分子。通过这个规律不难推出下一个分式的分子和分母,需要注意的是,保存分式的结果不能使用到整数,因为有可能会有小数的存在,所以我们需要选用浮点数double

代码示例:
#include  
//定义循环次数
#define COUNT 20

int main()
{
    //定义第一个分式的分子为a, 值为2; 定义分母为b,值为1
    //定义相加的和为sum,初始值为0
    double a = 2, b = 1, sum = 0;
    double temp;

    for (int i = 0; i < COUNT; i++)
    {
        sum += a / b;
        //记录前一项分子
        temp = a;
        //前一项分子与分母之和为后一项分子
        a = a + b;
        //前一项分子为后一项分母
        b = temp;
    }
    printf("前%d项之和为:sum=%9.7f\n", COUNT, sum);
    return 0;
}

一个球从100m高度自由落下,每次落地后反弹回原高度的一半,再落下,再反弹。求它在第10次落地时共经过多少米,第10次反弹多高。

解析:该题目需要循环10次,在每一循环的时候,需要将下落的高度和回弹的高度加起来。需要注意的点,第10次下落不需要在计算回弹的距离了,所以需要特殊处理下。在计算每次高度的时候,会有小数存在,所以需要选用浮点数

代码示例:
#include

int main()
{
    //总高度
    double total_m = 100.0;
    //小球经历的米数
    double total_sum = 0.0;
    for (int i = 0; i < 10; i++)
    {
        total_sum += total_m;
        total_m /= 2;
        total_sum += total_m;
    }
    //不需要计算第10次的反弹高度,所以减去
    total_sum -= total_m;
    printf("小球总共经历%lf米, 第10次反弹%lf米\n", total_sum, total_m);
    return 0;
}

猴子吃桃问题。猴子第1天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个。第2天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第10天早上想再吃时,就只剩一个桃子了。求第1天共摘多少个桃子。

解析:从题面上来看,可以推出,后一天的桃子数量 = 前一天桃子数量 / 2 - 1。所以,该公式也可以写成前一天的桃子数量 = (后一天桃子数量+1) * 2。所以我们知道了第10天剩余桃子的数量,则可以依次推算出桃子的前一天桃子的总数。需要注意的点,猴子只是吃了9天,所以,我们只需要遍历9次就可以了。

代码示例:
#include

int main()
{
    int day = 9;
    int prev_day_count;
    int cur_day_count = 1;
    while (day > 0)
    {
        prev_day_count = (cur_day_count + 1) * 2;
        cur_day_count = prev_day_count;
        day--;
    }
    printf("total count : %d\n", cur_day_count);
    return 0;
}

用迭代法求x=sqrt{a} 

求平方根的迭代公式为

要求前后两次求出的x的差的绝对值小于10^{-5}


#include
#include

int main()
{
    float a, x0, x1;
    printf("请输入一个正数: ");
    scanf("%f", &a);
    x0 = a / 2;
    x1 = (x0 + a / x0) / 2;
    do
    {
        x0 = x1;
        x1 = (x0 + a / x0) / 2;
    } while (fabs(x0 - x1) >= 1e-5);
    printf("[%f] 的平方根为 [%f]\n", a, x1);
    return 0;
}

用牛顿迭代法求下面方程在1.5附近的根:

代码示例:
#include
#include

int  main()
{
    double x1, x0, f, f1;
    x1 = 1.5;
    do
    {
        x0 = x1;
        f = ((2 * x0 - 4) * x0 + 3) * x0 - 6;
        f1 = (6 * x0 - 8) * x0 + 3;
        x1 = x0 - f / f1;
    } while (fabs(x1 - x0) >= 1e-5);
    printf("方程在1.5附近的根为:%lf\n", x1);
    return 0;
}

用二分法求下面方程在(-10,10)的根:C语言程序设计第五版谭浩强课后答案_第5张图片

代码示例:
#include
#include

int main()
{
    double left = -10, right = 10, mid;
    double temp = 10;
    while (fabs(temp) > 1e-5)
    {
        mid = (left + right) / 2;
        //((2x - 4)*x + 3) * x - 6 ==> 2x^3 - 4x^2 + 3x -6
        temp = ((2 * mid - 4) * mid + 3) * mid - 6;

        if (temp > 0)
        {
            right = mid;
        }
        else if (temp < 0)
        {
            left = mid;
        }
    }
    printf("在(-10,10)的根为:%lf", mid);
    return 0;
}

输出以下图案:

​ *

​ ***

*****

*******

*****

​ ***

​ *

答案解析:
该题目需要关心当前行对应的从最左边到第一颗*的空格数量以及星星数量。将该题分为两个部分,前面4行和后面3行来进行拆分。

前4行中:

第一行:行号为0, 空格数为3,星星数量为1;

第二行:行号为1, 空格数为2, 星星数量为3;

第三行:行号为2, 空格数为1, 星星数量为5;

第四行:行号为3, 空格数为0,星星数量为7;

则我们可以推出两组关系,即行号和空格数量关系为:空格数 = 3 - 行号 。行号与星星的关系为:星星数 = 2 * 行号 + 1

后三行中:

第一行:行号为0,空格数为1,星星数量为5;

第二行:行号为1, 空格数为2, 星星数量为3;

第三行:行号为2, 空格数为3,星星数量为1;

则我们推出两组关系,即行号与数量的关系:空格数 = 行号 + 1。行号与星星的关系:星星数 = 7 - 2 * (行号+1)

基于上面的关系,我们写出如下代码:

代码示例:
#include

int main()
{
    int cur_row, space_count, start_count;
    //输出前4行内容
    for (cur_row = 0; cur_row < 4; cur_row++)
    {
        //计算当前行空格数量,并且进行打印
        for (space_count = 3 - cur_row; space_count > 0; space_count--)
        {
            printf(" ");
        }
        //计算当前行*数量,并且进行打印
        for (start_count = 2 * cur_row + 1; start_count > 0; start_count--)
        {
            printf("*");
        }
        printf("\n") ;
    }
    //输出后三行
    for (cur_row = 0; cur_row < 3; cur_row++)
    {
        for (space_count = cur_row + 1; space_count > 0; space_count--)
        {
            printf(" ");
        }

        for (start_count = 7 - 2 * (cur_row + 1); start_count > 0; start_count--)
        {
            printf("*");
        }
        printf("\n");
    }
    return 0;
}

两个乒乓球队进行比赛,各出3人。甲队为A,B,C 3人,乙队为X,Y,Z 3人。已抽签决定比赛名单。有人向队员打听比赛的名单,A说他不和X比,C说他不和X,Z比,请编程序找出3对赛手的名单。

解析:从题面上得知,每队为3人,则隐含条件为队内三人是不能比赛的,并且A一定不会和X比,C一定不会X和Z比;则我们不难写出判断条件:

如果A和X比 或者 C和X比 或者 C和Z比 或者 A和B比 或者 A和C比 或者 B和C比,都是不可以的;所以我们只要穷举A比赛对象,B比赛对象,C比赛对象,判断上述条件就可以了;

代码示例:
#include

int main()
{
    int A_battle, B_battle, C_battle;
    //如果A对战的对象从“X”到“Z”
    for (A_battle = 'X'; A_battle <= 'Z'; A_battle++)
    {
        //如果B对战的对象从“X”到“Z”
        for (B_battle = 'X'; B_battle <= 'Z'; B_battle++)
        {
            //如果C对战的对象从“X”到“Z”
            for (C_battle = 'X'; C_battle <= 'Z'; C_battle++)
            {
                //去除限制条件
                if (A_battle == 'X' || C_battle == 'X' || C_battle == 'Z' || B_battle == A_battle || B_battle == C_battle || A_battle == C_battle)
                {
                    continue;
                }
                printf("A对%c,B对%c,C对%c", A_battle, B_battle, C_battle);
            }
        }
    }
    return 0;
}

用筛选法求100之内的素数

【答案解析】素数:约数为1和该数本身的数字称为素数,即质数

筛选法:又称为筛法。先把N个自然数按次序排列起来。1不是质数,也不是合数,要划去。第二个数2是质数留下来,而把2后面所有能被2整除的数都划去。2后面第一个没划去的数是3,把3留下,再把3后面所有能被3整除的数都划去。3后面第一个没划去的数是5,把5留下,再把5后面所有能被5整除的数都划去。这样一直做下去,就会把不超过N的全部合数都筛掉,留下的就是不超过N的全部质数。因为希腊人是把数写在涂腊的板上,每要划去一个数,就在上面记以小点,寻求质数的工作完毕后,这许多小点就像一个筛子,所以就把埃拉托斯特尼的方法叫做“埃拉托斯特尼筛”,简称“筛法”。(另一种解释是当时的数写在纸草上,每要划去一个数,就把这个数挖去,寻求质数的工作完毕后,这许多小洞就像一个筛子。)

【代码实现】

//用筛选法求100以内的素数
#include
int main()
{
    int i, j, k = 0;

    // 将数组汇总每个元素设置为:1~100
    int    a[100];
    for (i = 0; i < 100; i++)
        a[i] = i+1;

    // 因为1不是素数,把a[0]用0标记
    // 最后一个位置数字是100,100不是素数,因此循环可以少循环一次
    a[0] = 0;
    for (i = 0; i < 99; i++)
    {
        // 用a[i]位置的数字去模i位置之后的所有数据
        // 如果能够整除则一定不是素数,该位置数据用0填充
        for (j = i + 1; j < 100; j++)
        {
            if (a[i] != 0 && a[j] != 0)
            {
                //把不是素数的都赋值为0
                if (a[j] % a[i] == 0)
                    a[j] = 0;
            }
        }
    }

    printf(" 筛选法求出100以内的素数为:\n");
    for (i = 0; i < 100; i++)
    {
        //数组中不为0的数即为素数
        if (a[i] != 0)
            printf("%3d", a[i]);
    }

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

用选择法对10个整数排序

【答案解析】

选择排序原理:

总共两个循环,外循环控制选择的趟数,内循环控制具体选择的方式。

用maxPos标记区间中首元素位置,然后用后序元素依次与maxPos标记的元素进行比较,如果有元素大于maxPos位置的元素,用maxPos标记该元素的位置,直到区间的末尾。

该趟选择完成后,即找到该区间中最大元素,如果maxPos标记的最大元素不在区间末尾,用maxPos位置元素与区间末尾的元素进行交换。

继续新一趟选择,直到区间中剩余一个元素


【代码实现】

#include
int main()
{
    int array[] = {2,8,3,9,5,7,1,4,0,6};
    int size = sizeof(array) / sizeof(array[0]);
    // 输出原数组
    printf("排序前数组中数据为:");
    for (int i = 0; i < size; ++i)
        printf("%d ", array[i]);
    printf("\n");

    // 选择排序过程:
    // 外循环控制选择的趟数,总共选择size-1趟,
    // 减1是因为最后一趟选择区间中剩余一个元素,该趟选择可以忽略
    for (int i = 0; i < size-1; ++i)
    {
        // 用maxPos标记[0, size-i)区间中最大元素
        // 在该趟选择没有开始前,默认认为0号位置就是最大元素
        int maxPos = 0;
        for (int j = 1; j < size - i; ++j)
        {
            // 遍历区间[0, size-i)中元素,如果有元素比maxPos位置元素大,maxPos记录该元素位置
            if (array[j] > array[maxPos])
                maxPos = j;
        }

        // 如果最大元素不在区间末尾时,将最大元素与区间末尾元素交换
        if (maxPos != size - i - 1)
        {
            int temp = array[maxPos];
            array[maxPos] = array[size - i - 1];
            array[size - i - 1] = temp;
        }
    }

    // 输出原数组
    printf("选择排序后数组中数据为:");
    for (int i = 0; i < size; ++i)
        printf("%d ", array[i]);
    printf("\n");
    return 0;
}

优化:既然一趟选择能找到最大的元素,那么也可以找到最小的元素,因此在一趟中可以找到最小和最大两个元素,最小元素放在区间左侧,最大元素放在区间右侧,可以减少选择的趟数。

#include
int main()
{
    int array[] = {2,8,3,9,5,7,1,4,0,6};
    int size = sizeof(array) / sizeof(array[0]);
    // 输出原数组
    printf("排序前数组中数据为:");
    for (int i = 0; i < size; ++i)
        printf("%d ", array[i]);
    printf("\n");

    
    int begin = 0, end = size - 1;
    // [begin, end]区间中进行选择
    while (begin < end)
    {
        int maxPos = begin;  // 标记区间中最大元素的位置
        int minPos = begin;  // 标记区间中最小元素的位置
        int index = begin + 1;
        while (index <= end)
        {
            if (array[index] > array[maxPos])
                maxPos = index;

            if (array[index] < array[minPos])
                minPos = index;
            ++index;
        }

        // 如果最大元素不在区间末尾,则交换
        if (maxPos != end)
        {
            int temp = array[maxPos];
            array[maxPos] = array[end];
            array[end] = temp;
        }

        // 如果在交换前区间末尾刚好存储的是最小的元素,则最小的元素被交换到maxPos位置
        // 此时需要更新minPos
        if (minPos == end)
            minPos = maxPos;

        // 如果最小元素不在区间起始位置,则交换
        if (minPos != begin)
        {
            int temp = array[minPos];
            array[minPos] = array[begin];
            array[begin] = temp;
        }

        // 最大与最小元素已经在区间的起始和末尾的位置,
        // 因此begin往后移动,end往前移动
        begin++;
        end--;
    }

    // 输出原数组
    printf("选择排序后数组中数据为:");
    for (int i = 0; i < size; ++i)
        printf("%d ", array[i]);
    printf("\n");
    return 0;
}

求一个3 X 3的整形矩阵对角线元素之和

【答案解析】

矩阵:即二维数组,矩阵行和列相等的二维数组称为方阵。

1 2 3

4 5 6

7 8 9

左上角到右下角对角线上数字:行下标和列下标相等

右上角到左下角对角线上数字:列下标减1 行下标加一

通过两个循环来取到对角线上的元素,并对其求和即可。

【代码实现】

#include
int main()
{
    int array[3][3];
    int sumLT2RB = 0;  // 标记左上角到右下角对角线元素之和
    int sumRT2LB = 0;  // 标记右上角到左下角对角线元素之和
    printf("请输入3行3列的矩阵:\n");
    for (int i = 0; i < 3; ++i)
    {
        for (int j = 0; j < 3; ++j)
            scanf("%d", &array[i][j]);
    }

    // 左上角到右下角对角线
    for (int i = 0; i < 3; ++i)
        sumLT2RB += array[i][i];

    for (int i = 0, j = 2; i < 3; ++i, j--)
        sumRT2LB += array[i][j];

    printf("左上角到右下角对角线元素之和: %d\n", sumLT2RB);
    printf("右上角到左下角对角线元素之和: %d\n", sumRT2LB);
    return 0;
}

有一个已经排好序的数组,要求输入一个数后,按原来顺序的规律将它插入数组中

【答案解析】

将数据插入到已排序的序列中,只需两步即可:

找待插入元素在数组中的插入位置
插入元素
具体如下:


注意:极端情况下,end可能会被减为-1,比如在上述序列中插入0

【代码实现】

#include
int main()
{
    int num = 0;
    int array[10] = {1,2,3,4,5,6,7,8,9};

    printf("请输入一个整数:");
    scanf("%d", &num);

    printf("原数组序列为:\n");
    for (int i = 0; i < 9; ++i)
        printf("%d ", array[i]);
    printf("\n");

    // 数组为升序
    // 在数组中找待插入元素的位置,具体找的方式为:
    // 从后往前依次与数组中元素进行比较,如果要插入元素num比end位置数据小,则num一定插在end位置之前
    // 因此将end位置数据往后搬移一个位置
    // 如果num大于end位置元素或者end已经在区间最左侧,则位置找到
    // 最后将新元素插入到end+1的位置
    int end = 8;
    while (end >= 0 && num < array[end])
    {
        array[end+1] = array[end];
        end--;
    }

    array[end + 1] = num;
    printf("插入元素%d之后的结果为:\n", num);
    for (int i = 0; i < 10; ++i)
        printf("%d ", array[i]);
    printf("\n");
    return 0;
}

将一个数组中的值按逆序重新存放。例如:原来顺序为8,6,5,4,1。要求改为1,4,5,6,8。

【答案解析】

该题为数组的逆置,具体处理方式如下:

如果begin < end时,则循环进行一下操作

给定两个下标begin和end,begin放在数组起始的位置,end放在数组最后一个元素的位置
交换begin和end位置的元素
begin往后移动,end往前移动
【代码实现】

#include
int main()
{
    int array[5] = {8,6,5,4,1};
    int begin = 0, end = 4;

    printf("逆序之前数组为:");
    for (int i = 0; i < 5; ++i)
        printf("%d ", array[i]);
    printf("\n");

    // 逆序:begin在数组最左侧,end在数组最右侧
    // 只要begin < end,将begin和end位置元素进行交换
    // 然后begin往后移动一步,end往前移动一步
    while (begin < end)
    {
        int temp = array[begin];
        array[begin] = array[end];
        array[end] = temp;
        begin++;
        end--;
    }

    printf("逆置之后数组为:");
    for (int i = 0; i < 5; ++i)
        printf("%d ", array[i]);
    printf("\n");
    return 0;
}

输出一下的杨慧三角(要求输出10行)

1   
1   1
1   2   1
1   3   3   1
1   4   6   4   1
1   5  10  10   5   1
……
1
2
3
4
5
6
7
【答案解析】

仔细观察杨慧三角可以看到:

第0列和对角线上的数据全部为1,其余位置上的数据为上一行正对数据与上一行正对前一个数据之和。

比如:a[4][2] = a[3][2] + a[3][1]

【代码实现】

#include
int main()
{
    int array[10][10];
    for (int i = 0; i < 10; ++i)
    {
        for (int j = 0; j <= i; ++j)
        {
            // 对角线和第0列上全部为1
            if (i == j || 0 == j)
                array[i][j] = 1;
            else
                array[i][j] = array[i - 1][j] + array[i - 1][j - 1];
        }
    }

    // 打印杨慧三角的前10行
    for (int i = 0; i < 10; ++i)
    {
        for (int j = 0; j <= i; ++j)
        {
            printf("%5d", array[i][j]);
        }

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

输出"魔方阵"。所谓魔方阵是指这样的方阵,它的每一行、每一列和对角线之和均相等。例如:

8   1   6
3   5   7
4   9   2
要求输出1~n ^2的自然数构成的魔方阵。

【答案解析】

| 17 | 24 |  1 |  8 | 15 |
--------------------------
| 23 |  5 |  7 | 14 | 16 |
--------------------------
|  4 |  6 | 13 | 20 | 22 |
--------------------------
| 10 | 12 | 19 | 21 |  3 |
--------------------------
| 11 | 18 | 25 |  2 |  9 |

仔细观察上述矩阵,可以看到以下规律:

魔方阵的生成方法为:在第0行中间置1,对从2开始的其余n 2 − 1 n^2-1n 
2
 −1个数依次按下列规则存放:

将1放在第1行的中间一列。
从2开始直到n*n止,各数依次按此规律存放:每一个数存放的行比前一个数的行数减1,列数加1。
如果上一行的行数为1,则下一个数的行数为n(指最下一行)。
当上一个数的列数为n时,下一个数的列数应该为1。
如果按上面规律确定的位置有数,或者上一个数是第1行第n列时,则把下一个数放在上一个数的下面。
【代码实现】

#include
int main()
{
    int a[15][15], n, i, j, k;
    while (1)
    {
        printf("请输入n(1~15):");
        scanf("%d", &n);
        if (n != 0 && n <= 15 && n % 2 != 0)
            break;
        else
        {
            printf("请输入奇数\n");
        }
    }

    for (i = 1; i <= n; i++)
    {
        for (j = 1; j <= n; j++)
            a[i][j] = 0;
    }

    j = n / 2 + 1;
    a[1][j] = 1;
    i = 1;
    for (k = 2; k <= n*n; k++)
    {
        i -= 1;
        j += 1;

        if (i<1 && j>n)
        {
            i += 2;
            j -= 1;
        }
        else if (i<1)
        {
            i = n;
        }
        else if (j>n)
        {
            j = 1;
        }

        if (a[i][j] == 0)
        {
            a[i][j] = k;
        }
        else
        {
            i += 2;
            j -= 1;

            a[i][j] = k;
        }
    }

    for (i = 1; i <= n; i++)
    {
        for (j = 1; j <= n; j++)
            printf("%5d", a[i][j]);

        printf("\n");
    }

    return 0;
}

找出一个二维数组中的鞍点,即该位置上的元素在该行上最大,在该列上最小,也可能没有鞍点。

【答案解析】

鞍点是行上最大,列上最小的元素,因此对数组的第i元素进行如下操作:

找到该行上最大元素,用max标记,并标记该元素所在列colindex
找colindex列上最小的元素,用min标记,并标记该元素所在行号rowindex
如果max和min相等,并且最小的元素刚好是在第i行,则为鞍点
如果所有行找完了,没有输出则没有鞍点

【代码实现】

#include
#define M 3
#define N 4

int main()
{
    int max, min, rowindex, colindex, flag = 0;
    int array[M][N];
    printf("请输入%d行%d列的数组:\n", M, N);
    for (int i = 0; i < M; i++)
    {
        for (int j = 0; j < N; j++)
            scanf("%d", &array[i][j]);
    }

    for (int i = 0; i < M; ++i)
    {
        // 找到i行上最大的元素,记录该元素在列号colindex
        max = array[i][0];
        for (int j = 0; j < N; ++j)
        {
            if (array[i][j] > max)
            {
                max = array[i][j];
                colindex = j;
            }
        }

        // 找max所在列colindex上最小的元素,并记录其所在的行
        min = array[0][colindex];
        for (int j = 0; j < M; ++j)
        {
            if (array[j][colindex] < min)
            {
                min = array[j][colindex];
                rowindex = j;
            }
        }

        // 如果最小元素与最小元素相同,并且最小元素也在第i行,则为鞍点
        if (max == min && i == rowindex)
        {
            flag = 1;
            printf("鞍点为:%d行%d列的元素%d", rowindex, colindex, max);
            break;
        }
    }

    if (0 == flag)
        printf("没有鞍点");
    return 0;
}

有15个数按由大到小顺序存放在一个数组中,输入一个数,要求用折半查找法找出该数是数组中第几个元素的值。如果该数不在数组中,则输出"无此数"。

【答案解析】

二分查找是一个非常高效简单的查找算法,笔试和面试中非常喜欢考察。

折半查找又叫二分查找,查找的前提是序列中元素必须有序,假设区间使用[left, right)标记,待查找元素为key,具体查找的方式如下:当区间[left, right)有效时循环进行一下操作

找到[left, right)区间中间位置
如果key等于中间位置元素,则找到,返回该元素在数组中的下标
如果key小于中间位置元素,到数组的左半侧继续二分查找
如果key大于中间位置元素,到数组的右半侧继续二分查找
如果循环结束时还没有找到,则不存在该元素。

【代码实现】

#include
int main()
{
    int array[15] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14};
    int left = 0;
    int right = sizeof(array) / sizeof(array[0]);
    int key = 0;

    printf("请输入要查找的数字: ");
    scanf("%d", &key);

    // 二分查找
    while (left < right)
    {
        // 找到中间位置
        int mid = left + ((right - left) >> 1);
        if (key == array[mid])
        {
            printf("%d\n", mid);
            break;
        }
        else if (key < array[mid])
        {
            right = mid;
        }
        else
        {
            left = mid + 1;
        }
    }

    if (left >= right)
        printf("无此数\n");
    return 0;
}

有一篇文章,共有3行文字,每行有80个字符。要求分别统计出其中英文大写字母、小写字母、数字、空格以及其他字符的个数。

【答案解析】

获取文章中的3行文本,并对每行文本进行以下操作

定义保存结果变量:upp、low、digit、space、other
遍历每行文本中的字符
如果该字符ch:ch >= ‘a’ && ch <=‘z’,则该字符是小写字母,给low++
如果该字符ch:ch >= ‘A’ && ch <=‘Z’,则该字符是小写字母,给up++
如果该字符ch:ch >= ‘0’ && ch <=‘9’,则该字符是小写字母,给digit++
如果该字符ch:ch == ’ ',则该字符是小写字母,给space++
否则为其他字符,给other++
输入统计结果

【代码实现】

#include
int main()
{
    int upp = 0, low = 0, digit = 0, space = 0, other = 0;
    char text[3][80];
    
    for (int i=0; i<3; i++)
    {
        // 获取一行文本
        printf("please input line %d:\n",i+1);
        gets(text[i]);
        
        // 统计该行文本中小写字母、大写字母、数字、空格、其他字符的个数
        for (int j=0; j<80 && text[i][j]!='\0'; j++)
        {
            if (text[i][j]>='A'&& text[i][j]<='Z')   // 大写字母
                upp++;
            else if (text[i][j]>='a' && text[i][j]<='z')  // 小写字母
                low++;
            else if (text[i][j]>='0' && text[i][j]<='9')  // 数字
                digit++;
            else if (text[i][j]==' ')  // 控制
                space++;
            else
                other++;   // 其他字符
        }
     }
    
     printf("\nupper case: %d\n", upp);
     printf("lower case: %d\n", low);
     printf("digit     : %d\n", digit);
     printf("space     : %d\n", space);
     printf("other     : %d\n", other);
 
    return 0;
}

输出一下图案:

* * * *
  * * * *
    * * * *
      * * * *
        * * * *

【答案解析】

该题非常简单,观察图形可以看出:

每行中*的个数相等,都是4个
每行中空格的个数在递增2个
每行先输出空格,然后输出*
按照以上方式通过循环来控制每行的输出内容即可

【代码实现】

#include
int main()
{
    for (int i = 0; i < 5; ++i)
    {
        // 输出空格
        for (int j = 0; j < i; ++j)
            printf("  ");

        // 输出*
        printf("* * * *\n");
    }
    return 0;
}

有一行电文,以按下面规律译成密码:

A--->Z   a--->z
B--->Y   b--->Y
C--->X   c--->x
……
即第1个字母编程第26个字母,第i个字母编程第(26-i+1)个字母,非字母字符不变,要求编程序将密码译回原文,并输出密码和原文。

【答案解析】

从题目给的实例中可以看到,编码规则非常简单,就是将从前往后数的第i个字母转化为从后往前数的第i个字母。

那解压时直接反过来转换即可:

即’Z’—>‘A’ ‘z’—>‘a’

​ ‘Y’—>‘B’ ‘y’—>‘b’

​ ‘X’—>‘C’ ‘x’—>‘c’

假设如果当前拿到的是小写字母,转换方式如下:

先用s[i] - 'a’计算出s[i]是26个字母中从前往后数的第几个
再用26 - (s[i]- ‘a’) - 1 转换为26个字母中从后往前数的第几个
在2的结果上加上’a’,即转换为对应从后往前的第几个字母
大写字母转换方式与上述相同,将上述每条中的’a’换为‘A’即可。

【代码实现】

#include
int main()
{
    char s[1024] = {0};
    scanf("%s", s);

    int len = strlen(s);
    // 转换
    for (int i = 0; i < len; ++i)
    {
        // 如果是小写字母(大写字母出来类似):
        // 1. 先用s[i] - 'a'计算出s[i]是26个字母中从前往后数的第几个
        // 2. 再用26 - (s[i]- 'a') - 1 转换为26个字母中从后往前数的第几个
        // 3. 在2的结果上加上'a',即转换为对应从后往前的第几个字母
        if (s[i] >= 'a' && s[i] <= 'z')
            s[i] = 'a' + 26 - (s[i]-'a')-1;
        else if (s[i] >= 'A' && s[i] <= 'Z')
            s[i] = 'A' + 26 - (s[i] - 'A')-1;
    }

    printf("%s", s);
    return 0;
}

编一程序,将两个字符串连接起来,不要用strcat函数

【答案解析】

直接将s2中的字符逐个拷贝到s1的末尾即可,用户需要保证s1中能存的下s2中的字符

获取s1末尾的位置
将s2中的字符逐个拷贝到s1中
【代码实现】

#include

int main()
{
    char s1[100] = {0};
    char s2[50] = { 0 };
    int index1 = 0, index2 = 0;
    printf("请输入字符串s1:");
    scanf("%s", s1);

    printf("请输入字符串s2:");
    scanf("%s", s2);

    printf("将s2拼接在s1之后: ");
    // 1. 找到s1的末尾
    while ('\0' != s1[index1])
        index1++;

    // 2. 将s2中的字符逐个往s1之后拼接
    while (s1[index1++] = s2[index2++]);

    printf("%s\n", s1);
    return 0;
}

编写一个程序,将连个字符串s1和s2比较,如果s1 > s2,输出一个整数;若s1 = s2,输出0;若s1 < s2,输出一个负数。不要用strcpy函数。两个字符串用gets函数读入。输出的正数或负数的绝对值应是相比较的两个字符串相对应字符的ASCII码的差值。例如,“A"和“C”相比,由于"A” < “C”,应输出负数,同时由于‘A’与‘C’的ASCII码差值为2,因此应输出"-2"。同理:“And”和"Aid"相比较,根据第2个字符比较结果,“n"比"i"大5,因此应输出"5”。

【答案解析】

字符串比较规则:从前往后逐个字符进行比较,相等时继续往后,不相等时返回该位置两个字符差值。

【代码实现】

#include

int main()
{
    int ret = 0;
    int index = 0;
    char s1[100] = { 0 };
    char s2[100] = { 0 };
    printf("请输入s1:");
    gets(s1);

    printf("请输入s2:");
    gets(s2);

    // 将s1和s2中的字符从前往后逐个进行比较,相等继续往后,
    // 不相等时ret中结果不为0,!ret则为0  循环结束
    // 如果一个走到末尾,一个未走到末尾 ret也不为0, !ret为0,循环结束
    // 如果两个字符串相等,同时达到末尾,循环结束
    while (!(ret = s1[index] - s2[index]) && '\0' != s1[index] && '\0' != s2[index])
    {
        ++index;
    }

    printf("%d\n", ret);
    return 0;
}

编写一个程序,将字符数组s2中的全部字符复制到字符数组s1中,不用strcpy函数。复制时,‘\0’也要赋值过去。’\0’之后的字符不复制。

【答案解析】

首先必须保证s1能否放的下s2中的字符,然后将s2中的每个字符逐个搬移到s1中即可。

【代码实现】

#include

int main()
{
    char s1[100] = { 0 };
    char s2[50] = { 0 };
    int index1 = 0, index2 = 0;
    printf("请输入字符串s2:");
    scanf("%s", s2);

    printf("将s2拷贝到s1中, s1现在为: ");
    
    // 将s2[index2]位置字符拷贝到s1[index]位置,
    // 然后以s1[index1]的值作为循环条件判断是否拷贝到s2的末尾
    while (s1[index1++] = s2[index2++]);
    printf("%s\n", s1);
    return 0;
}

写两个函数,分别求两个整数的最大公约数和最小公倍数,用主函数调用这两个函数,并输出结果。两个整数由键盘输人。

题目解析:
该题直接使用“辗转相除法”来求解最大公约数和最小公倍数

最大公约数找出两数中的最小值,然后直接相模,当能够同时被两数整除时,则为最大公约数。

最小公倍数找出两数中的最大值,然后直接进入死循环,直到找到一个数能够同时被两数整除时,则为最小公倍数

【注】此题还有一些比较高级的解法,比如求最大公约数的相减法、欧几里德辗转相除法等,有兴趣的同学可以查询相关资料

代码示例:
#include

//最大公约数
size_t GCD(size_t a, size_t b)
{      
    
    size_t gcd;      
    gcd = a > b ? b : a;
    while(gcd > 1)  
    {
        if((a % gcd == 0) && (b % gcd == 0))   
            return gcd; 
        gcd--; 
    }
    return gcd;
}

//最小公倍数
size_t LCM(size_t a, size_t b)
{
    size_t lcm;
    lcm = a > b ? a : b;
    while(1)
    {
        if((lcm % a==0) && (lcm % b==0))
            break;
        lcm++;
    }
    return lcm;
}

int main()
{
    size_t a, b, result;
    printf("请输入两个整数:>");
    scanf("%d %d", &a, &b);

    result = GCD(a, b);
    printf("%d和%d的最大公约数为:%d\n", a, b, result);
    result = LCM(a, b);
    printf("%d和%d的最小公倍数为:%d\n", a, b, result);

    return 0;
}

求方程 {ax}^2+bx+c=0的根,用3个函数分别求当:  b^2-4ac大于0、等于0和小于0时的根并输出结果。从主函数输入a,b,c的值。

代码示例
#include
#include

//x1为第一个根,x2为第二个根
float x1, x2, disc, p, q;

void greater_than_zero(float a, float b)
{
    float m = sqrt(disc);
    x1 = (-b + sqrt(disc)) / (2 * a);
    x2 = (-b - sqrt(disc)) / (2 * a);
}

void equal_to_zero(float a, float b)
{
    x1 = x2 = (-b) / (2 * a);
}

void smaller_than_zero(float a, float b)
{
    p = -b / (2 * a);
    q = sqrt(-disc) / (2 * a);
}

int main()
{
    int a, b, c;
    printf("请输入 a b c:");
    scanf("%d %d %d", &a, &b, &c);

    printf("表达式为: %d*x^2+%d*x+%d = 0\n", a, b, c);
    disc = b*b - 4 * a*c;

    if (disc > 0)
    {
        greater_than_zero(a, b);
        printf("disc>0的根为: x1=%f    x2=%f\n", x1, x2);
    }
    else if (disc == 0)
    {
        equal_to_zero(a, b);
        printf("disc==0的根为:x1=%f    x2=%f\n", x1, x2);
    }
    else
    {
        smaller_than_zero(a, b);
        printf("disc<0的根为:x1=%f+%f x2=%f-%f\n", p, q, p, q);
    }
    return 0;
}

写一个判素数的函数,在主函数输人一个整数,输出是否为素数的信息。

题目解析:
素数是一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做素数

该题可以使用概念直接判断法求解,不过不需要判断所有的数据,只需要判断数据的一半即可,因为偶数不可能为素数(除了2),所以只需判断该数的一半即可的到答案

代码示例:
#include
#include

bool IsPrime(int value)
{
    for(int i=2; i     {
        if(value % i == 0) //说明除了1和本身之外,还能被其他数整除
            return false;
    }
    return true;
}

int main()
{
    int value;
    bool flag;
    printf("请输入 value :>");
    scanf("%d", &value);
    
    flag = IsPrime(value);
    if(flag)
        printf("%d 是素数.\n", value);
    else
        printf("%d 不是素数.\n", value);

    return 0;
}

写一个函数,使给定的一个3X3的二维整型数组转置,即行列互换。

题目解析:
进行数组的行列互换,其关键在于数组互换的表达式 ar[i] [j] = ar[j] [i];其次在循环的时候,内层循环不能到达最大列,需要根据此时是第几行的交换来决定循环的次数,否则有可能数组行列交换之后最后又交换回原来的形状了。

代码示例
#include

void PrintArray(int ar[3][3])
{
    for(int i=0; i<3; ++i)
    {
        for(int j=0; j<3; ++j)
        {
            printf("%d ", ar[i][j]);
        }
        printf("\n");
    }
}

void ReverseArray(int ar[3][3])
{
    int tmp;
    for(int i=0; i<3; ++i)
    {
        for(int j=0; j         {
            if(i != j) //中间数不发生变化
            {
                //交换两个数
                tmp = ar[i][j];
                ar[i][j] = ar[j][i];
                ar[j][i] = tmp;
            }
            
        }
    }
}

int main()
{
    int array[3][3] = 
    {
        {1,2,3},
        {4,5,6},
        {7,8,9}
    };

    printf("转置前:\n");
    PrintArray(array);

    //进行数组转置
    ReverseArray(array);

    printf("转置后:\n");
    PrintArray(array);

    return 0;
}

写一个函数,使输人的一个字符串按反序存放,在主函数中输入和输出字符串。

题目解析及答案:
要把一个字符串反序存放,其实就是对字符串做一个逆序操作,操作过程为收尾字符交换,直到把所有字符全部交换完毕。
示例代码
#include

void ReverseString(char str[])
{
    int start, end;
    char tmp;
    start = 0;
    end = strlen(str)-1; //字符数组小标从0开始,所以-1
    while(start < end)
    {
        tmp = str[start];
        str[start] = str[end];
        str[end] = tmp;

        start++;
        end--;
    }
}

int main()
{
    char str[100] = {0};
    printf("请输入一个字符串:>");
    scanf("%s", str);
    printf("原始字符串为:> %s\n", str);
    ReverseString(str);
    printf("反序字符串为:> %s\n", str);
    return 0;
}

写一个函数,将两个字符串连接。

题目解析及答案:
利用一个临时数组,空间要保证能够容纳两个字符串,先把第一个字符串进行拷贝到临时数组,第二个字符串在临时数组的尾部接着链接,最后记得加上字符串的结束标记\0即可
代码示例:
#include

void ConcatStr(char string1[], char string2[], char string[])
{
    int i, j;
    for (i = 0; string1[i] != '\0'; i++)
        string[i] = string1[i];
    
    //找到字符串末尾,继续往后面链接字符串
    for (j = 0; string2[j] != '\0'; j++)
        string[i + j] = string2[j];

    //字符串末尾加上结束符 \0
    string[i + j] = '\0';
}

int main()
{
    char s1[200] = {0}, s2[100]= {0}, s[100] = {0};
    printf("input string1:");
    scanf("%s", s1);
    printf("input string2:");
    scanf("%s", s2);
    ConcatStr(s1, s2, s);
    printf("\nThe new string is %s\n", s);
    return 0;
}

写一个函数,将一个字符串中的元音字母复制到另一字符串,然后输出。

题目解析:
该题的重点在于元音字母的判断,通过或条件,凡是元音字母都进行拷贝
代码示例:
#include

void cpy(char s[], char c[])
{
    int i, j;
    for (i = 0, j = 0; s[i] != '\0'; i++)
    {
        //判断元音字母
        if (s[i] == 'a' || s[i] == 'A' || s[i] == 'e' || s[i] == 'E' || 
            s[i] == 'i' ||s[i] == 'I' || s[i] == 'o' || s[i] == 'O' ||
            s[i] == 'u' || s[i] == 'U')
        {
            c[j] = s[i];
            j++;
        }
    }
    c[j] = '\0';
}

int main()
{
    char str[80], c[80];
    printf("input string:");
    gets(str);
    cpy(str, c); //将str中的元音字母拷贝到c中
    printf("The vowel letters are:%s\n", c);
    return 0;
}

写一个函数,输人一个4位数字,要求输出这4个数字字符,但每两个数字间空一个空格。如输人1990,应输出“1 9 9 0”。

题目解析:
对字符串进行遍历输出,没输出一个字符,后面就跟着输出一个空格,关键点在于如果输出的是最后一个字符,则不能在输出字符,所以要对是否是最后一个字符的输出进行判断。

代码示例:
#include

void OutString(char str[])
{
    int i = 0;
    while(str[i] != '\0')
    {
        printf("%c", str[i]);
        if(str[i+1] == '\0') //清除最后一个空格不输出
            break;
        printf("%c", ' ');
        i++;
    }
    printf("\n");
}
int main()
{
    char str[5] = {0};
    printf("input four digits:");
    scanf("%s", str);
    OutString(str);

    return 0;
}

编写一个函数,由实参传来一个字符串,统计此字符串中字母、数字、空格和其他字符的个数,在主函数中输人字符串以及输出上述的结果。

题目解析:该题的关键在于要能够写出各种字符统计的条件
代码示例:
#include

int letter, digit, space, others;

void CountChar(char str[])
{
    int i;
    for (i = 0; str[i] != '\0'; i++)
    {
        //统计字母
        if ((str[i] >= 'a'&& str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z')) 
            letter++;
        else if (str[i] >= '0' && str[i] <= '9') //统计数字
            digit++;
        else if (str[i] == ' ')//统计空格
            space++;
        else
            others++;  //统计其他字符
    }
}

int main()
{
    char text[80];
    printf("input string:\n");
    gets(text);
    printf("string: %s\n", text);

    CountChar(text);
    printf("\nletter:%d\ndigit:%d\nspace:%d\nothers:%d\n", letter, digit, space, others);
    return 0;
}

写一个函数,输人一行字符,将此字符串中最长的单词输出。

题目解析及答案:
单词以空格进行分隔,因此寻找空格出现的位置即为关键,每次从单词的起始到空格出现的位置即为一个单词,此时计算单词的长度,如果比当前最大的还长,就进行跟新最长单词信息,当整个字符串遍历完成,word即保存最长字符串。
代码示例:
#include
#include

void LongestWord(char str[], char word[])
{
    int max_len = 0;
    int len = 0;
    int i = 0;
    while(str[i] != '\0')
    {
        if(str[i] == ' ')
        {
            str[i] = '\0';
            len = strlen(str);
            if(len > max_len)
            {
                max_len  = len;
                strcpy(word, str);
                str = str + len + 1;
            }
        }
        i++;
    }
}

int main()
{
    char line[100] = {0};
    char word[100] = {0};
    printf("input one line:\n");
    gets(line);

    LongestWord(line, word);

    printf("The longest word is : %s\n", word);
    return 0;
}

写一个函数,用“起泡法”对输人的10个字符按由小到大顺序排列。

题目解析及答案:
该题主要是对冒泡排序的理解,外层循环控制排序的趟数,内层循环主要是进行每一趟排序的比较,如果前面的字符大于后面的字符,就进行交换,每做一趟排序,就把一个最大字符排在最后,以及每做一趟排序就需要少比较一个字符。
代码示例:
#include
#include

void BubbleSort(char str[])
{
    int i, j;
    char tmp;
    int len = strlen(str);
    for(i=0; i     {
        for(j=0; j         {
            if(str[j] > str[j+1])
            {
                tmp = str[j];
                str[j] = str[j+1];
                str[j+1] = tmp;
            }
        }
    }
}

int main()
{
    int i;
    char str[11] = {0};
    printf("请输入10个字符:>");
    for(i=0; i<10; ++i)
        scanf("%c", &str[i]);

    BubbleSort(str);

    printf("string sorted: %s\n", str);
    return 0;
}

用牛顿迭代法求根。方程为ax^3+bx^2 +cx+d=0,系数a,b,c,d的值依次为1,2,3,4,由主函数输人。求x在1附近的一个实根。求出根后由主函数输出。

题目解析及答案:
此题的难点并不是编程,主要是要理解数学公式的求解方法,理解之后代码的实现并不困难。
代码示例:
#include
#include

float solut(int a, int b, int c, int d)
{
    float x = 1, x0, f, f1;
    do
    {
        x0 = x;
        f = ((a*x0 + b)*x0 + c)*x0 + d;
        f1 = (3 * a*x0 + 2 * b)*x0 + c;
        x = x0 - f / f1;
    } while (fabs(x - x0) >= 1e-3);
    return(x);
}

int main()
{
    int a, b, c, d;
    printf("input a,b,c,d:");
    scanf("%d %d %d %d", &a, &b, &c, &d);
    printf("x=%10.7f\n", solut(a, b, c, d));
    return 0;
}

用递归方法求n阶勒让德多项式的值,递归公式为

C语言程序设计第五版谭浩强课后答案_第6张图片

题目解析及答案:
递归函数的设计,有一个点非常重要,那就是必须要有返回条件,,此题中的返回条件即为n0和n1时,因为当n为这两值时,程序直接返回相应的值,只有n>=1时,才进行递归运算。
代码示例:
#include

double polya(int n,int x)
{
    double result; 
    if(n == 0)  
        result = 1;  
    if(n == 1)
        result = x; 
    if(n>1)
        result = ((2*n-1)*x*polya(n-1,x)-(n-1)*polya(n-2,x))/n;    
    return result;
}

int main()

    int x,n; 
    scanf("%d %d", &n, &x); 
    printf("%.2f\n", polya(n,x)); 
    return 0;
}

输人10个学生5门课的成绩,分别用函数实现下列功能:
①计算每个学生的平均分;
②计算每门课的平均分;
③找出所有50个分数中最高的分数所对应的学生和课程;
④计算平均分方差:

其中,x;为某一学生的平均分。

题目解析及答案:
此题的关键是如何存储某个学生对应某门课程的分数,这里利用了一个二维数组score,其中score[i] [j]就代表了第i个学生的第j门课程的分数,只要能够理解这个存储方式,其余的计算就是比较容易理解和实现的。
代码示例:
#include

#define N 10
#define M 5
float score[N][M];
float a_stu[N], a_cour[M];
int r, c;

//输入学生成绩信息函数
void input_stu(void)
{
    int i, j;
    for (i = 0; i < N; i++)
    {
        printf("\ninput score of student%2d:\n", i + 1);
        for (j = 0; j < M; j++)
            scanf("%f", &score[i][j]);
    }
}

//每个学生平均分
void aver_stu(void)
{
    int i, j;
    float s;
    for (i = 0; i < N; i++)
    {
        for (j = 0, s = 0; j < M; j++)
            s += score[i][j];
        a_stu[i] = s / 5.0;
    }
}

//每门课程平均分
void aver_cour(void)
{
    int i, j;
    float s;
    for (j = 0; j < M; j++)
    {
        s = 0;
        for (i = 0; i < N; i++)
            s += score[i][j];
        a_cour[j] = s / (float)N;
    }
}

//最高分函数
float highest()
{
    float high;
    int i, j;
    high = score[0][0];
    for (i = 0; i < N; i++)
    for (j = 0; j     if (score[i][j]>high)
    {
        high = score[i][j];
        r = i + 1;
        c = j + 1;
    }
    return(high);
}

//方差函数
float s_var(void)
{
    int i;
    float sumx, sumxn;
    sumx = 0.0;
    sumxn = 0.0;
    for (i = 0; i < N; i++)
    {
        sumx += a_stu[i] * a_stu[i];
        sumxn += a_stu[i];
    }
    return(sumx / N - (sumxn / N)*(sumxn / N));
}

int main()
{
    int i, j;
    float h;
    input_stu();
    aver_stu();
    aver_cour();
    printf("\n  NO.     cour1   cour2   cour3   cour4   cour5   aver\n");
    for (i = 0; i < N; i++)
    {
        printf("\n NO %2d ", i + 1);
        for (j = 0; j < M; j++)
            printf("%8.2f", score[i][j]);
        printf("%8.2f\n", a_stu[i]);
    }
    printf("\naverage:");
    for (j = 0; j < M; j++)
        printf("%8.2f", a_cour[j]);
    printf("\n");
    h = highest();
    printf("highest:%7.2f   NO. %2d   course %2d\n", h, r, c);
    printf("variance %8.2f\n", s_var());
    return 0;
}

写几个函数:
①输人10个职工的姓名和职工号;
②按职工号由小到大顺序排序,姓名顺序也随之调整;
③要求输人一个职工号,用折半查找法找出该职工的姓名,从主函数输人要查找的职工号,输出该职工姓名。

题目解析及答案:
利用二分查找的关键在于数据一定要先有序,所以在查找前我们需要对数据进行排序。

代码示例:
#include

#define N 10

void input(int num[], char name[N][8])
{
    int i;
    for (i = 0; i < N; i++)
    {
        printf("input NO.: ");
        scanf("%d", &num[i]);
        printf("input name: ");
        getchar();
        gets(name[i]);
    }
}

void sort(int num[], char name[N][8])
{
    int i, j, min, templ;
    char temp2[8];
    for (i = 0; i < N - 1; i++)
    {
        min = i;
        for (j = i; j         if (num[min]>num[j])  min = j;
        templ = num[i];
        strcpy(temp2, name[i]);
        num[i] = num[min];
        strcpy(name[i], name[min]);
        num[min] = templ;
        strcpy(name[min], temp2);
    }
    printf("\n result:\n");
    for (i = 0; i < N; i++)
        printf("\n %5d%10s", num[i], name[i]);
}

void search(int n, int num[], char name[N][8])
{
    int top, bott, mid, loca, sign;
    top = 0;
    bott = N - 1;
    loca = 0;
    sign = 1;
    if ((nnum[N - 1]))
        loca = -1;
    while ((sign == 1) && (top <= bott))
    {
        mid = (bott + top) / 2;
        if (n == num[mid])
        {
            loca = mid;
            printf("NO. %d , his name is %s.\n", n, name[loca]);
            sign = -1;
        }
        else if (n < num[mid])
            bott = mid - 1;
        else
            top = mid + 1;
    }
    if (sign == 1 || loca == -1)
        printf("%d not been found.\n", n);
}

int main()
{
    int num[N], number, flag = 1, c;
    char name[N][8];

    input(num, name);
    sort(num, name);

    while (flag == 1)
    {
        printf("\ninput number to look for:");
        scanf("%d", &number);
        search(number, num, name);
        printf("continue ot not(Y/N)?");
        getchar();
        c = getchar();
        if (c == 'N' || c == 'n')
            flag = 0;
    }
    return 0;
}

写一个函数,输人一个十六进制数,输出相应的十进制数。

题目解析及答案:
转换的过程需要乘的基数为16,其次注意十六进制中的a~f的字母转换,并且无论大小写都要能够转换。
代码示例:
#include

size_t HextoDec(char s[])
{
    size_t i, n;
    n = 0;
    for (i = 0; s[i] != '\0'; i++)
    {
        if (s[i] >= '0'&& s[i] <= '9')
            n = n * 16 + s[i] - '0';
        if (s[i] >= 'a' && s[i] <= 'f')
            n = n * 16 + s[i] - 'a' + 10;
        if (s[i] >= 'A' && s[i] <= 'F')
            n = n * 16 + s[i] - 'A' + 10;
    }
    return n;
}

int main()
{
    size_t result = 0;
    char hex[9] = {0}; 
    printf("input a HEX number:");
    scanf("%s", hex);

    result = HextoDec(hex);
    printf("0x%s = %u\n", hex, result);
    
    return 0;
}

用递归法将一个整数n转换成字符串。例如,输人483,应输出字符串”483”。n的位数不确定,可以是任意位数的整数。

题目解析及答案:
递归法求解主要要有结束条件,此题为n/10 == 0时就直接输出,其次本题还要考虑如果整数位负数的情形,此时需要输出一个字符串的负号。
#include

void Convert(int n)
{
    int i;
    if ((i = n / 10) != 0)
        Convert(i);
    putchar(n % 10 + '0');
}

int main()
{
    int number;
    printf("input an integer: ");
    scanf("%d", &number);
    printf("output: ");
    if (number < 0)
    {
        putchar('-');   //先输出一个负号'-'
        number = -number;
    }
    Convert(number);
    printf("\n");
    return 0;
}

给出年、月、日,计算该日是该年的第几天。

题目解析:
此题采用枚举法进行每月天数的累加,其中关键点注意需要判断年份是否为闰年,如果是还需要多累加1天。
代码示例:
#include
#include

/* 函数sum_day:计算日期 */
int sum_day(int month, int day)        
{
    int day_tab[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    int i;
    for (i = 1; i < month; i++)
        day += day_tab[i];      /* 累加所在月之前天数 */
    return day;
}                         

/* 函数leap:判断是否为闰年 */
int leap(int year)
{
    int leap;
    leap = year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
    return leap;
}

int main()
{
    int year, month, day, days;
    printf("input date(year,month,day):");
    scanf("%d %d %d", &year, &month, &day);
    printf("%d/%d/%d ", year, month, day);
    days = sum_day(month, day);                  /* 调用函数sum_day */
    if (leap(year) && month >= 3)                  /* 调用函数leap */
        days = days + 1;
    printf("is the %dth day in this year.\n", days);
    return 0;
}

输入3个整数,要求按由小到大的顺序输出。

解题思路: 先获取到三个变量的地址,然后获取三个数据,通过指针进行比较转换即可

答案:

#include

void swap(int *p_a, int *p_b)
{
    int temp = *p_a;
    *p_a = *p_b;
    *p_b = temp;
}
int main()
{
    int a, b, c, *p_a = &a, *p_b = &b, *p_c = &c;     // 获取每个变量空间的地址 
    printf("Please enter three numbers:");
    scanf_s("%d%d%d", p_a, p_b, p_c);
    if (*p_a > *p_b) {
        swap(p_a, p_b);//通过指针进行指向空间内的数据交换
    }
    if (*p_a > *p_c) {
        swap(p_a, p_c);
    }
    if (*p_b > *p_c) {
        swap(p_b, p_c);
    }
    printf("%d %d %d\n", *p_a, *p_b, *p_c);
    system("pause");
    return 0;
}

输入3个字符串,要求按由小到大的顺序输出。

解题思路: 字符串的比较可以使用strcmp函数,返回值>0表示大于,返回值小于0表示小于,返回追等于0表示相同。其他的比较排序思路与数字的排序交换没有区别,逐个进行比较先找出最大的,然后找出第二大的。

答案:

#include
int main()
{
    char str[3][32]; 
    char *p[3];
    printf("Please enter three strings:");
    for (int i = 0; i < 3; i++) {
        p[i] = str[i];
        scanf_s("%s", p[i], 32);//后边的数字限制缓冲区边界,防止缓冲区溢出访问越界
    }
    //让p[0]和p[1]/p[2]分别进行比较,找出最大的字符串,i+1之后,则让p[1]和p[2]进行比较,找出第二大
    //i循环总个数-1次,最后一个是不需要比较的
    for (int i = 0; i < 2; i++) {
        for (int j = i + 1; j < 3; j++) { 
            if (strcmp(p[i], p[j]) > 0) {
                char *tmp = p[i]; p[i] = p[j]; p[j] = tmp;
            }
        }
        
    }
    printf("%s %s %s\n", p[0], p[1], p[2]);
    system("pause");
    return 0;
}

输入10个整数,将其中最小的数与第一个数对换, 把最大的数与最后一个数对换。
写3个函数:

①输人10个数;
②进行处理;
③输出10个数。
解题思路: 在进行数值逐个比较的同时找到最小值的空间地址以及最大值的空间地址,使用这两个空间中的数据最终与第一和最后数据进行对换即可。

答案:

#include

void input(int *arry, int len)
{
    for (int i = 0; i < len; i++) {
        scanf_s("%d", &arry[i]);
    }
}
void print(int *arry, int len)
{
    for (int i = 0; i < len; i++) {
        printf("%d ", arry[i]);
    }
    printf("\n");
}
void handle(int *arry, int len)
{
    int max_num = arry[0], min_num = arry[0];
    int *p_max = NULL, *p_min = NULL;
    for (int i = 1; i < len; i++) {
        if (min_num > arry[i]) {//逐个比对后找出最小值
            min_num = arry[i];
            p_min = &arry[i];    //逐个比对后找到最小值的空间地址
        }
        if (max_num < arry[i]) {//逐个比对后找出最大值
            max_num = arry[i];
            p_max = &arry[i];   //逐个比对后找到最大值的空间地址
        }
    }
    int tmp;
    tmp = *p_min; *p_min = arry[0]; arry[0] = tmp;  //最小值与第一个数据交换
    tmp = *p_max; *p_max = arry[len - 1]; arry[len - 1] = tmp;//最大值与最后一个数据交换
}
int main()
{
    int arry[10];
    printf("Please enter ten nums:");
    input(arry, 10);
    handle(arry, 10);
    print(arry, 10);
    system("pause");
    return 0;
}

有n个整数,使前面各数顺序向后移m个位置,最后m个数变成最前面m个数,见图8.43。 写一函数实现以上功能,在主函数中输人n个整数和输出调整后的n个数。


解题思路: 找出倒数第m个数据,从这里开始保存倒数第m位置的数据,因为倒数第m位置的数据要放到数组最前方,将m之前的数据向后偏移一位,然后将数组第一个位置的数据替换为保存的m位的数据,逐个往后递增即可。

答案:

#include
void move(int *arry, int n, int m)
{
    int end_idx = n - m;//找到倒数第m个数据的位置,也就是要移动到数组首部的数据的起始位置
    for (int i = 0; i < m; i++) {
        int *p = arry + end_idx + i;//从倒数第m个数据的位置开始逐渐向后偏移直到数组尾部
        int tmp = *p;//获取到这个位置的值,用于数组前边数据向后偏移1位之后,向数组第i位赋值
        for (int j = end_idx + i; j > i; j--) {//从第i位开始逐个向后偏移一位
            *p = *(p - 1);
            p--;
        }
        *(arry + i) = tmp;//数组的前第i个数字逐个替换为后边被覆盖的值
    }
}
int main()
{
    int number[32], n, m, i;
    printf("Please enter the number of numbers: ");
    scanf_s("%d", &n);//先确定要输入多少个数字
    printf("Please enter %d numbers: ", n);
    for (i = 0; i < n; i++) {
        scanf_s("%d", &number[i]);//输入指定个数的数字
    }
    printf("Number of positions to move: ");
    scanf_s("%d", &m);//确定要向后移动多少个位置
    move(number, n, m);
    for (i = 0; i < n; i++) {
        printf("%d ", number[i]);
    }
    printf("\n");
    system("pause");
    return 0;
}

有n个人围成一圈,顺序排号。从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位。

解题思路: 从第一个人开始,逐个报数,谁报3就退出,并且重置报数,直到最后一个人后,又重新从第一个人继续报数,直到最终只剩一个人的时候退出即可。

答案:

#include
int main()
{
    int people[128], n;
    printf("Please input how many people: ");
    scanf_s("%d", &n);
    for (int i = 0; i < n; i++) {
        people[i] = i + 1; //对每个人顺序排号
    }
    int remain = n;
    int num_off = 0;
    int *p = NULL;
    while (remain > 1) {
        p = people;
        while (p != people + n) { // 每次从第一个位置开始,直到最后一个位置,报数是一直递增的
            if ((*p) != 0) {//若这个位置人还在
                num_off++; //则报数
                if (num_off == 3) {//否则当前的人即将要报的数字是3
                    *p = 0;  //则剔除这个人
                    num_off = 0; //并且重新开始计数,下边会++,所以是从1开始报数
                    remain--;//剩余人数-1
                }
            }
            p++;
        }
    }
    for (int i = 0; i < n; i++) {
        if (people[i] != 0) {
            printf("Serial number of the remaining person:%d\n", people[i]);
        }
    }

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

写一函数,求一个字符串的长度。在main函数中输入字符串,并输出其长度。

解题思路: 字符串以\0作为结尾,则从第一个字符开始向后移动遇到\0认为字符串结束。

答案:

#include
int mystrlen(char *str)
{
    int len = 0;
    char *ptr = str;
    while (*ptr != '\0') {
        ptr++;
        len++;
    }
    return len;
}
int main()
{
    char buf[1024];
    printf("Please enter a string: ");
    scanf_s("%s", buf, 1024);
    printf("string len:%d\n", mystrlen(buf));
    system("pause");
    return 0;
}

有一字符串,包含n个字符。写一函数,将此字符串中从第m个字符开始的全部字符复制成为另一个字符串。

解题思路: 当字符串指针移动到源字符串的第m位时,则开始向另一个缓冲区中写入剩下的数据

答案:

#include
#include

int main()
{
    char buf1[1024], buf2[1024];
    printf("Please enter a string: ");
    scanf_s("%s", buf1, 1024);
    int m;
    printf("Please enter a location to start copying: ");
    scanf_s("%d", &m);
    if (m < 0 || m > strlen(buf1)) {//检测输入的位置是否合法
        printf("Illegal location entered\n");
        return -1;
    }
    char *ptr1 = buf1 + m; // 从第m个位置开始复制新数据
    char *ptr2 = buf2;
    while (*ptr1 != '\0') {
        *ptr2++ = *ptr1++;
    }
    *ptr2 = '\0';//不要忘了字符串结尾标志
    printf("%s\n", buf2);
    system("pause");
    return 0;
}

输入一行文字,找出其中大写字母、小写字母、空格、数字以及其他字符各有多少。

解题思路: 字符可以直接进行比较,但是要注意字符串中的数字是字符数字,必须以字符的形式比较,也就是加上单引号

答案:

#include
#include

int main()
{
    char buf[1024];
    printf("Please enter a string: ");
    gets_s(buf, 1024);
    int upper_count = 0, lower_count = 0, digit_count = 0, space_count = 0, other_count = 0;
    char *ptr = buf;
    while (*ptr != '\0') {
        if (*ptr >= 'A' && *ptr <= 'Z') { //大写字母
            upper_count++;
        }else if (*ptr >= 'a' && *ptr <= 'z'){//小写字母
            lower_count++;
        }else if (*ptr >= '0' && *ptr <= '9') {//数字字符
            digit_count++;
        }else if (*ptr== ' ') {//空格字符
            space_count++;
        }else { //其他字符
            other_count++;
        }
        ptr++;
    }
    printf("upper:%d; lower:%d; digit:%d; space:%d; other:%d\n", \
        upper_count, lower_count, digit_count, space_count, other_count);
    system("pause");
    return 0;
}

写一函数,将一个3x3的整型矩阵转置。

解题思路: 矩阵转置就是行变列,列变行,说白了就是 arry[i][j] 转换为 arry[j][i] ; 但是需要注意的是,

一. 因为行列个数可能并非相同,转换后行数或者列数变多了或者变少,因此不能直接转换。需要重新申请空间存储转换后的数据。

二. 二维数组是线性扁平化存储的,无法确定列数的情况下传参后,在函数中使用时需要头指针向后偏移 列数*第n行 才能访问到第n行的数据。例如在函数中访问 arry[i][j] ,需要通过arry + col_num*i + j 方式进行访问。

答案:

#include
int **transform(int **arry, int row_count, int col_count)
{
    //列变行,行变列,则行的个数是以前列的个数,列的个数是以前行的个数
    int **p = NULL;
    //矩阵中有多少行,取决于以前有多少列,然后申请地址空间
    p = (int **)malloc(sizeof(int *) * col_count);
    for (int i = 0; i < col_count; i++) {
        //一行中有多少列,取决于以前有多少行,然后申请空间
        p[i] = (int *)malloc(sizeof(int) * row_count); 
    }
    for (int i = 0; i < col_count; i++) {
        for (int j = 0; j < row_count; j++) {
            //二维数组的存储是扁平化的, 访问第j行第i列的数据,应该是 arry + j*列数 + i
            //j是新数组的列,但是是源数组的行
            p[i][j] = (arry + col_count * j)[i]; 
        }
    }
    return p;
}
int main()
{
    int arry[3][4];
    printf("Please enter a 3 x 4 matrix: \n");
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 4; j++) {
            scanf_s("%d", &arry[i][j]);
        } 
    }
    int **p = transform(arry, 3, 4);
    printf("\n");
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 3; j++) {
            printf("%d ", p[i][j]);
        }
        free(p[i]); // 释放二级指针中每个一级指针申请的空间
        printf("\n");
    }
    free(p);//释放总体二级指针的空间
    system("pause");
    return 0;
}

将一个5x5的矩阵中最大的元素放在中心,4个角分别放4个最小的元素(顺序为从左到右,从上到下依次从小到大存放),写一函数实现之。用main函数调用。

解题思路: 将二维数组当做一维数组进行处理比较方便,而二维数组本身就是扁平化存储,所以直接使用首地址即可。

先遍历找到最大值,将其与中间数字交换,而中间数字的下标就是数字总数除以2;

其次寻找四次最小值,每次寻找的时候将最小值的下标记录起来,前提是这个数字如果已经是选中的最小数字之一,则需要跳过,也就是只跟剩余的数字作比较。(第二次开始遍历找最小数字的时候,千万不能与第一个最小数进行比较,否则永远都只有一个最小数)。

答案:

#include
#include
void transform(int *arry, int col_row)
{
    //找到最大值
    int max = arry[0], max_idx;
    for (int i = 0; i < col_row * col_row; i++) {
        if (max < arry[i]) max = arry[i];//找出最大数
        max_idx = i;
    }
    //行列相乘得到总数量,除以2后加1则为中心点(暂时不考虑偶数的情况)
    int center_idx = (col_row * col_row) / 2;
    int tmp = arry[cen ter_idx]; arry[center_idx] = arry[max_idx]; arry[max_idx] = tmp;

    //找到四个最小值
    int min_idx[4];
    for (int i = 0; i < 4; i++) {//循环4次获取到最小值
        int min_tmp = arry[col_row * col_row - 1];
        for (int j = 0; j < col_row * col_row; j++) {//遍历所有数据,逐个比较获取最小值
            int k = 0;
            for (; k < i; k++) {//但是要注意如果某个下标的数据已经是获取过的最小值,则不能进行判断(因为这个肯定是最小的)
                if (j == min_idx[k]) break;
            }
            if (k != i) { continue; }//k和i不同表示j这个坐标已经是找到的最小的几个数字之一,则找下一个判断
            if (min_tmp > arry[j]) { // 相当于在剩下的数中找到最小的那个数字
                min_tmp = arry[j];
                min_idx[i] = j; //并且记录这个数字的位置
            }
        }
    }
    int change_idx[4];//先计算四个角的下标,便于后边进行交换
    change_idx[0] = 0;//第一个要置换的数据的下标,也就是左上角
    change_idx[1] = col_row - 1;//第二个要置换的数据的下标,也就是右上角
    change_idx[2] = col_row * (col_row - 1);//第一个要置换的数据的下标,也就是左下角
    change_idx[3] = (col_row * col_row) - 1;//第一个要置换的数据的下标,也就是右下角
    for (int i = 0; i < 4; i++) {
        int tmp = arry[change_idx[i]]; arry[change_idx[i]] = arry[min_idx[i]]; arry[min_idx[i]] = tmp;
    }
    return ;
}
int main()
{
    int arry[5][5];
    printf("Please enter a 5x5 matrix: \n");
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {
            scanf_s("%d", &arry[i][j]);
        } 
    }
    transform(*arry, 5);//将二维数组当做一维数组传入处理,并且传入行列数
    printf("\n");
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {
            printf("%d ", arry[i][j]);
        }
        printf("\n");
    }
    system("pause");
    return 0;
}

在主函数中输入10个等长的字符串。用另一函数对它们排序。然后在主函数输出这10个已排好序的字符串。

解题思路: 排序方式与数字比较没什么不同,先遍历比较找出最大的字符串,与第一个字符串进行交换,然后剩下的进行比较找出最大的字符串与第二个交换…

需要主机的就是字符串的比较采用strcmp接口,返回值大于0表示第一个字符串大于第二个字符串

答案:

#include
#include
void sort(char s[10][32])
{
    int i, j;
    for (i = 0; i < 10; i++){
        for (j = i; j < 10; j++){
            if (strcmp(s[i], s[j])> 0){
                char tmp[32];
                strcpy_s(tmp, 32, s[i]);
                strcpy_s(s[i], 32, s[j]);
                strcpy_s(s[j], 32, tmp);
            }
        }
    }
}
int main()
{
    char str[10][32];
    printf("Please enter ten strings:\n");
    for (int i = 0; i < 10; i++){
        scanf_s("%s", str[i], 32);
    }
    sort(str);
    printf("\n");
    for (int i = 0; i < 10; i++){
        printf("%s\n", str[i]);
    }
    system("pause");
    return 0;
}

用指针数组处理上一题目,字符串不等长。

解题思路: 与数字的比较没什么区别,只不过需要采用strcmp进行字符串的大小比较,使用指针实现需要在最早接收数据的时候就采用字符串指针数组,这样的好处在于指针的指向可以直接通过赋值进行改变,而指针数组中的字符串的顺序只需要交换不同字符串的地址就可以实现

答案:

#include
#include
void sort(char *s[10])
{
    int i, j;
    for (i = 0; i < 10; i++){
        for (j = i; j < 10; j++){
            if (strcmp(s[i], s[j])> 0){
                char *tmp = s[i]; //指针的好处在于直接通过赋值可以改变指向
                s[i] = s[j];  //只要交换了字符串的地址就实现了字符串的交换
                s[j] = tmp;//因此通过指针指向的交换就能够实现数组中字符串的排序
            }
        }
    }
}
int main()
{
    char *str[10];
    printf("Please enter ten strings:\n");
    for (int i = 0; i < 10; i++) {
        str[i] = malloc(32);//为每一个指针分配空间
        scanf_s("%s", str[i], 32);
    }
    sort(str);
    printf("\n");
    for (int i = 0; i < 10; i++){
        printf("%s\n", str[i]);
        free(str[i]);
    }
    system("pause");
    return 0;
}

写一个用矩形法求定积分的通用函数,分别求

说明: sin,cos,exp 函数已在系统的数学函数库中,程序开头要用#include
解题思路:

矩形法,学过高等数学就知道化曲为直的思想。将定积分化为多个函数连续的和。基本思想是将区间[a,b]化成n等分,当n越大的时候结果越准确。图形化成一小块一小块的矩形。底边长都为(b-a)/n.高为每个等分点的函数值。然后将每个矩形的面积相加即为所求。

因为被分成n等分,就可以认为每一等分是一个矩形,那么每一矩形的面积为: 每一个矩形面积为:

Sn=f(x)(b-a)/n ;总面积为:S=S1+S2+…+Sn;具体计算过程根据公式套即可

这里主要在于函数指针的应用,将函数作为参数传递给另一个函数,在另一个函数中进行调用的方式向外提供统一接口,而接口内的处理方式随着传入的函数而不同。

答案:

#include
#include

double integral(double(*handler)(double), double a, double b, int n)
{
    double i,s = 0;
    double h = (b - a) / n;
    for (i = a; i <= b; i += h){
        s += handler(i) * h;
    }
    return s;
}
int main()
{
    double a, b;
    int n = 200000; // 区间划分个数
    int func_idx; // 计算函数选择id
    printf("Please enter the lower and upper limit of integration:");
    scanf_s("%lf %lf", &a, &b);
    printf("Please enter specific calculation function(1-sin/2-cos/3-exp): ");
    scanf_s("%d", &func_idx);
    switch (func_idx) {
        case 1:printf("The integral of sin(x) is:%lf\n", integral(sin, a, b, n)); break;
        case 2:printf("The integral of cos(x) is:%lf\n", integral(cos, a, b, n)); break;
        case 3:printf("The integral of exp(x) is:%lf\n", integral(exp, a, b, n)); break;
        default:
            printf("function id error\n");
            return -1;
    }
    system("pause");
    return 0;
}

将n个数按输入时顺序的逆序排列,用函数实现。

解题思路: 定义两个指针,一个指向数组头部,一个指向数组尾部,头部每次+1,尾部每次-1;则在头部小于尾部的情况下进行数据交换即可。

答案:

#include
#include

void reorder(int *arry, int n)
{
    int *start = arry;
    int *end = arry + n - 1;
    for (; start < end; start++, end--) {
        int tmp = *start;
        *start = *end;
        *end = tmp;
    }
    return;
}

int main()
{
    int arry[10];
    printf("Please enter ten numbers:");
    for (int i = 0; i < 10; i++) {
        scanf_s("%d", &arry[i]);
    }
    reorder(arry, 10);
    printf("\n");
    for (int i = 0; i < 10; i++) {
        printf("%d ", arry[i]);
    }
    printf("\n");
    system("pause");
    return 0;
}

有一个班4个学生,5门课程。
①求第1门课程的平均分;
②找出有两门以上课程不及格的学生,输出他们的学号和全部课程成绩及平均成绩;
③找出平均成绩在90分以上或全部课程成绩在85分以上的学生。
分别编3个函数实现以上3个要求。

解题思路: 4个学生,5门课程就是一个4x5的二维数组,

求第一门课的平均分,就是将第0列数据相加除以学生人数
遍历每个学生的成绩,判断不及格次数,若大于2则输出信息即可
统计每个学生总成绩,以及对每门课程成绩进行判断即可
答案:

#include
#include

float avg(int arry[][5], int n)
{
    float sum = 0;
    for (int i = 0; i < n; i++) {
        sum += arry[i][0];
    }
    printf("Average of course 1:%f\n", (sum / n));
    return (sum / n);
}
void fail(int arry[][5], int n)
{
    printf("Information on students who fail in more than two courses: ");
    for (int i = 0; i < n; i++) {
        int sum = 0, fail_count = 0;
        for (int j = 0; j < 5; j++) {
            if (arry[i][j] < 60) {
                fail_count++;
            }
        }
        if (fail_count <= 2) {
            continue;
        }
        printf("seq:%d ", i + 1);
        printf("score: ");
        for (int j = 0; j < 5; j++) {
            sum += arry[i][j];
            printf("%d ", arry[i][j]);
        }
        printf("avg:%d ", sum / 5);
        printf("\n");
    }
    return;
}
void excellent(int arry[][5], int n)
{
    int i, j;
    for (i = 0; i < n; i++) {
        int sum = 0, count = 0;
        for (j = 0; j < 5; j++) {
            sum += arry[i][j]; //计算总分用于计算平均分
            if (arry[i][j] > 85) {
                count++; //若每门课都大于85则count总会与j同步++
            }
        }
        if ((sum / 5) > 90 || count == j) {
            printf("Excellent students: %d\n", i + 1);
        }
    }
    return;
}

int main()
{
    int arry[4][5];
    printf("Please enter a 4x5 matrix:\n");
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 5; j++) {
            scanf_s("%d", &arry[i][j]);
        }
    }
    avg(arry, 4);
    fail(arry, 4);
    excellent(arry, 4);
    printf("\n");
    system("pause");
    return 0;
}

输入一个字符串,内有数字和非数字字符,例如:A123x456 17960? ,302tab5876,将其中连续的数字作为一个整数,依次存放到一数组a中。例如,123放在a[0],456放在a1[1]…统计共有多少个整数,并输出这些数。

解题思路: 遇到数字字符,则开始统计连续数字字符的个数,统计完毕后,则从右往左每次乘以10(除了个位数)作为数字的单位,最终相加得到数字;然后越过这个数字,从后边继续查找。

答案:

#include
#include

void count_digit(char *str)
{
    int digit[32], count = 0;
    char *ptr = str;
    int i = 0, str_len = strlen(str);
    while (i < str_len) {
        if (*(ptr+i) >= '0' && *(ptr+i) <= '9') {
            int len = 1;//用于统计连续数字的个数
            while (*(ptr + i + len) >= '0' && *(ptr + i+ len) <= '9' && (i+len) < str_len) {//找出从当前位置连续数字的个数
                len++;
            }
            int sum = *(ptr + i + len - 1) - '0';//先获取个位数的数据
            int unit = 1;//每一位的单位,从十位开始每次乘以10作为单位
            for (int j = len - 2; j >= 0; j--) {//从右往左逐个处理
                unit *= 10;
                sum += (*(ptr + i + j) - '0') * unit;
            }
            digit[count++] = sum;
            i += len; // i需要加上len的长度,越过这个数字,防止一个连续数字中的字符重复处理
            continue;
        }
        i++;
    }
    for (int i = 0; i < count; i++) {
        printf("%d ", digit[i]);
    }
    return;
}
int main()
{
    char buf[1024] = { 0 };
    printf("Please enter a string with numbers:\n");
    gets_s(buf, 1024);
    count_digit(buf);
    printf("\n");
    system("pause");
    return 0;
}

写一函数,实现两个字符串的比较。即自己写一个strcmp函数,函数原型为int strcmp(char * p1 ,char * p2); 设p1指向字符串s1, p2指向字符串s2。要求当s1=s2时,返回值为0;若s1≠s2,返回它们二者第1个不同字符的ASCII码差值(如"BOY"与"BAD" ,第2个字母不同,0与A之差为79- 65=14)。如果s1>s2,则输出正值;如果s1

解题思路: 使用两个指针指向两个字符串首部,逐个往后进行比较,不相等的时候则将数据进行相减,作为返回值。

答案:

#include
#include

int mystrcmp(char *str1, char *str2)
{
    char *ptr1 = str1;
    char *ptr2 = str2;
    int res;
    while (*ptr1 != '\0' && *ptr2 != '\0') {
        if (*ptr1 != *ptr2) {
            res = *ptr1 - *ptr2;
            break;
        }
        ptr1++;
        ptr2++;
    }
    if (*ptr1 == '\0' || *ptr2 == '\0') {//注意一个字符串到达结尾或者两个都到达结尾的情况
        res = *ptr1 - *ptr2;
    }
    return res;
}
int main()
{
    char buf1[1024] = { 0 };
    char buf2[1024] = { 0 };
    while (1) {
        printf("Please enter two strings:\n");
        gets_s(buf1, 1024);
        gets_s(buf2, 1024);
        printf("mystrcmp:%d", mystrcmp(buf1, buf2));
        printf("\n");
    }
    system("pause");
    return 0;
}

编一程序,输入月份号,输出该月的英文月名。例如,输人3,则输出"March" ,要求用指针数组处理。

解题思路: 首先定义字符串指针数字,数组中每一个元素都存放一个字符串指针,每个指针指向不同字符串的位置。则输入月份数字后,根据下标获取对应月份字符串的地址即可

答案:

#include
int main()
{
    int month;
    char* Month[12] = { "January","February","March","April","May","June",
    "July","August","September","October","November","December" };
    while (1) {
        printf("Please enter the month: ");
        scanf_s("%d", &month);
        if (month < 1 && month>12) {
            printf("Input error, Month should be greater than 0 and less than 12\n");
        }
        printf("%s\n", Month[month - 1]);
    }
    return 0;
}

1) 编写一个函数new,对n个字符开辟连续的存储空间,此函数应返回一个指针(地址),指向字符串开始的空间。new(n)表示分配n个字节的内存空间。(2)写一函数free,将前面用new函数占用的空间释放。free§表示将p(地址)指向的单元以后的内存段释放。

解题思路: 封装malloc函数申请空间,封装free函数释放空间;

答案:

#include
#include

void *mynew(int n)
{
    return malloc(n);
}
void myfree(char *p)
{
    return free(p);
}
int main()
{
    int num;
    char *str = NULL;
    printf("Please enter number: ");
    scanf_s("%d", &num);
    printf("before new p--%p:%s\n", str, str);//申请空间之前,查看指针的地址和指向空间数据
    str = (char*)mynew(num);
    printf("after new p--%p:%s\n", str, str);//申请空间之后,查看指针的地址和指向空间数据
    printf("Please enter a string:");
    scanf_s("%s", str, num);
    printf("before free p--%p:%s\n", str, str);//释放空间之前,查看指针的地址和指向空间数据
    myfree(str);
    printf("after free p--%p:%s\n", str, str);//释放空间之后,查看指针的地址和指向空间数据
    system("pause");
    return 0;
}

用指向指针的指针的方法对5个字符串排序并输出。

**解题思路:**指向指针的指针其实就是二级指针,使用二级指针的保存一级指针的地址,让这个一级指针指向具体的数据空间; 定义一个字符串指针数组包含5个元素,每个元素可以保存一个字符串的首地址,而这个地址指向的是具体的字符串数据空间,通过指针访问实现对指向空间内的字符串进行比较排序交换即可。

答案:

#include
#include
void sort(char *s[10])
{
    int i, j;
    for (i = 0; i < 10; i++){
        for (j = i; j < 10; j++){
            if (strcmp(s[i], s[j])> 0){//s[i]保存的就是一个字符串的首地址
                char *tmp = s[i]; //指针的好处在于直接通过赋值可以改变指向
                s[i] = s[j];  //只要交换了字符串的地址就实现了字符串的交换
                s[j] = tmp;//因此通过指针指向的交换就能够实现数组中字符串的排序
            }
        }
    }
}
int main()
{
    char *str[5];//定义字符串指针数组,可以分别保存指向5个字符串所在空间首地址
    printf("Please enter five strings:\n");
    for (int i = 0; i < 5; i++) {
        str[i] = malloc(32);//为每一个指针分配空间
        scanf_s("%s", str[i], 32);
    }
    sort(str);
    printf("\n");
    for (int i = 0; i < 5; i++){
        printf("%s\n", str[i]);
        free(str[i]);
    }
    
    system("pause");
    return 0;
}

用指向指针的指针的方法对n个整数排序并输出。要求将排序单独写成一个函数。n个整数在主函数中输入,最后在主函数中输出。

解题思路: 指向指针的指针其实就是二级指针,使用二级指针的保存一级指针的地址,让这个一级指针指向具体的数据空间。排序就是按照每个元素指针指向空间中的数据进行比对排序即可。

答案:

#include
#include
void sort(int *s[], int len)
{
    int i, j;
    for (i = 0; i < len; i++) {
        for (j = i; j < len; j++) {
            //s[i]就是s指针数组中第i个元素保存的一级指针,再次解引用就是最终的数据空间
            if (*(s[i]) > *(s[j])) {
                int tmp = *(s[i]); //指针的好处在于直接通过赋值可以改变指向
                *(s[i]) = *(s[j]);  //只要交换了字符串的地址就实现了字符串的交换
                *(s[j]) = tmp;//因此通过指针指向的交换就能够实现数组中字符串的排序
            }
        }
    }
}
int main()
{
    int *integers;
    int count = 0;
    printf("Please enter the number of count: ");
    scanf_s("%d", &count);
    integers = (int*)malloc(count * sizeof(int));//为指针申请count个int空间用于存放输入的数据
    int **p = (int **)malloc(count * sizeof(int*));//为指针申请count个int*空间用于存放int空间的首地址
    printf("Please enter %d integers: \n", count);
    for (int i = 0; i < count; i++) {
        p[i] = integers + i; //将数组中每个int元素空间的首地址赋值给指针数组中的各个元素
        scanf_s("%d", p[i]);//p[i]就保存时第i个数据的地址,因此这里不用取地址
    }
    sort(p, count);
    for (int i = 0; i < count; i++) {
        printf("%d ", integers[i]);
    }
    printf("\n");
    free(integers);
    free(p);
    system("pause");
    return 0;
}

定义一个结构体变量(包括年、月、日)。计算该日在本年中是第几天,注意闰年问题。

解题思路及答案:

用一个日期数组保存每一月的天数,二月的天数记为28天,后面根据输入的时间确定是否是闰年的二月,如果是,天数在加1。
#include

struct Date{
    int year;
    int month;
    int day;
};

int main(){
    struct Date date;
    printf("Please give date: ");
    scanf("%d%d%d", &date.year, &date.month, &date.day);
    int Days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    
    int i, days = 0;
    for (i = 1; i < date.month; i++)
        days += Days[i];
    days += date.day;
    //如果包含闰年的二月,天数加1
    if(date.month > 2)
    {
       if (date.year%400 == 0 || (date.year%4 == 0 && date.year%100 != 0)){
            ++days;
        } 
    }
    printf("It's day %d in the year.\n", days);
    return 0;
}

写一个函数days,实现第1 题的计算。由主函数将年、月、日传递给days函数,计算后将日子数传回主函数输出。

#include

struct Date{
    int year;
    int month;
    int day;
};

int Days(struct Date date)
{
    static int Days[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

    int i, days = 0;
    for (i = 1; i < date.month; i++)
        days += Days[i];
    days += date.day;
    //如果包含闰年的二月,天数加1
    if (date.month > 2)
    {
        if (date.year % 400 == 0 || (date.year % 4 == 0 && date.year % 100 != 0)){
            ++days;
        }
    }
    return days;
}

int main(){
    struct Date date;
    printf("Please give date: ");
    scanf("%d%d%d", &date.year, &date.month, &date.day);
    int days = Days(date);
    printf("It's day %d in the year.\n", days);
    return 0;
}

编写一个函数print,打印一个学生的成绩数组,该数组中有5个学生的数据记录,每个记录包括num,name,score[3],用主函数输人这些记录,用print函数输出这些记录。

#include

#define NAMLEN 20
//定义一个student结构体数组,包含5个元素
struct student_t{
    int num;
    char name[NAMLEN];
    int score[3];
} students[5];

void print(struct student_t *stu);

int main(){
    for (int i = 0; i < 5; i++){
        scanf("%d%s%d%d%d", &students[i].num, students[i].name, &students[i].score[0],
            &students[i].score[1], &students[i].score[2]);
    }
    print(students);
    return 0;
}

void print(struct student_t *stu){
    for (int i = 0; i < 5; i++){
        printf("%d %s %d %d %d\n", students[i].num, students[i].name, students[i].score[0],
            students[i].score[1], students[i].score[2]);
    }
}

在上题的基础上,编写一个函数input,用来输人5个学生的数据记录。

#include

#define NAMLEN 20
//定义一个student结构体数组,包含5个元素
struct student_t{
    int num;
    char name[NAMLEN];
    int score[3];
} students[5];

void print(struct student_t *stu);
void input(struct student_t *stu);

int main(){
    input(students);
    print(students);
    return 0;
}

void input(struct student_t *stu)
{
    for (int i = 0; i < 5; i++){
        scanf("%d%s%d%d%d", &students[i].num, students[i].name, &students[i].score[0],
            &students[i].score[1], &students[i].score[2]);
    }
}

void print(struct student_t *stu){
    for (int i = 0; i < 5; i++){
        printf("%d %s %d %d %d\n", students[i].num, students[i].name, students[i].score[0],
            students[i].score[1], students[i].score[2]);
    }
}

有10个学生,每个学生的数据包括学号、姓名、3门课程的成绩,从键盘输人10个学生数据,要求输出3门课程总平均成绩,以及最高分的学生的数据(包括学号、姓名、3门课程成绩、平均分数)。

#include

#define NAMLEN 20
#define STUCNT 10

typedef struct student_t{
    int num;
    char name[NAMLEN];
    int score[3];
} student;

int main(){
    student students[STUCNT];
    int maxi = 0, maxsum = 0;
    double aver_0 = 0, aver_1 = 0, aver_2 = 0;
    for (int i = 0; i < STUCNT; i++){
        scanf("%d%s%d%d%d", &students[i].num, students[i].name, &students[i].score[0], &students[i].score[1], &students[i].score[2]);
        int sum = students[i].score[0] + students[i].score[1] + students[i].score[2];
        if (sum > maxsum){
            maxsum = sum;
            maxi = i;
        }
        aver_0 += students[i].score[0];
        aver_1 += students[i].score[1];
        aver_2 += students[i].score[2];
    }
    aver_0 /= STUCNT;
    aver_1 /= STUCNT;
    aver_2 /= STUCNT;
    printf("%lf %lf %lf\n", aver_0, aver_1, aver_2);
    printf("%d %s %d %d %d %lf\n", students[maxi].num, students[maxi].name, students[maxi].score[0], students[maxi].score[1], students[maxi].score[2],
        (students[maxi].score[0] + students[maxi].score[1] + students[maxi].score[2]) / 3.0);
    return 0;
}

13个人围成一圈,从第1个人开始顺序报号1,2,3。凡报到3者退出圈子。找出最后留在圈子中的人原来的序号。要求用链表实现。

解题思路及答案:

创建一个环形链表,给链表中的每一个节点从1~13编号,然后开始淘汰过程,对于淘汰的节点,序号置为0,淘汰完成之后,找到序号不为0的即为最后留下的。

#include
#define NUM 13
typedef struct people
{
    int num;
    struct people *next;
} people;

int main()
{
    int count = NUM;
    people p[NUM];
    people *head;
    head = p; //head 指向p[0]
    //1~13编号
    for (int i = 0; i < NUM; i++)
    {
        head->num = i + 1;
        head->next = &p[i + 1];
        head = head->next;
    }
    //最后一个元素指向第一个元素 , 形成环
    p[NUM - 1].next = p; 

    int i = 1;
    head = p;
    while (count > 1)
    {
        //跳过已经被淘汰的节点
        if (head->num == 0)
        {
            head = head->next;
            continue;
        }
        if (i == 3)
        {
            //被淘汰的节点,num置为0
            printf("第 %d 位置被淘汰\n", head->num);
            head->num = 0;
            count--;
        }
        head = head->next;
        i++;
        if (i > 3)
        {
            i = 1;
        }
    }
    printf("--------------\n");
    while (head->num == 0)
    {
        //非0节点即为最后留下的
        head = head->next;
        if (head->num != 0)
        {
            printf("留到最后的是 %d \n", head->num);
        }
    }

    return 0;
}

在第9章例9.9和例9.10的基础上,写一个函数del,用来删除动态链表中指定的节点

解题思路及答案:

首先创建一个带头的单链表,然后让用户输入需要删除的节点,调用del函数,找到需要删除的节点,把待删除节点的前驱和后继重新链接。

#include
#include

typedef struct LNode
{
    int num;
    struct LNode *next;
} LNode;

//创建含有n个值的节点
LNode* creat(int n)
{
    LNode *head, *p;
    head = (LNode *)malloc(sizeof(LNode));
    p = head; //头节点为0 加上头节点共n + 1个节点
    head->num = 0;
    head->next = NULL;
    for (int i = 1; i <= n; i++)
    {
        LNode *newNode = (LNode *)malloc(sizeof(LNode));
        newNode->num = i;
        newNode->next = NULL;
        p->next = newNode;
        p = p->next;
    }
    return head;
}

//删除值为n的节点
void del(int n, LNode *head)
{
    LNode *pre, *current;
    pre = head;
    current = head->next;
    //从第一个有效节点开始查找待删除节点
    printf("delete node %d\n", n);
    while (current != NULL)
    {
        //找到待删除节点,重新链接,释放待删除节点
        if (current->num == n)
        {
            pre->next = current->next;
            free(current);
            break;
        }
        //更新查找位置
        pre = current;
        current = current->next;
    }
}

int main()
{
    LNode *head, *p;
    int n;
    head = creat(10);
    printf("请输入需要删除的节点:1-10\n");
    scanf("%d", &n);
    del(n, head);
    int i = 1;
    p = head->next;
    while (p != NULL)
    {
        printf("p %d.num -> %d\n", i, p->num);
        p = p->next;
        i++;
    }
    return 0;
}

写一个函数insert,用来向一个动态链表插入结点

#include
#include

typedef struct LNode
{
    int num;
    struct LNode *next;
} LNode;

void insert(int n, LNode *node)
{
    //创建新节点
    LNode *newNode = (LNode *)malloc(sizeof(LNode));
    newNode->num = n;

    LNode* next = node->next;

    // node ---> newNode  ---> next
    newNode->next = next;
    node->next = newNode;
}

LNode* creat(int n)
{
    LNode *head, *p;
    head = (LNode *)malloc(sizeof(LNode));
    p = head; //头节点为0 加上头节点共11个节点
    head->num = 0;
    head->next = NULL;
    for (int i = 1; i <= n; i++)
    {
        LNode *newNode = (LNode *)malloc(sizeof(LNode));
        newNode->num = i;
        newNode->next = NULL;
        p->next = newNode;
        p = p->next;
    }
    return head;
}

void printNode(LNode* head)
{
    LNode* p = head->next;
    while (p != NULL)
    {
        printf("num -> %d\n", p->num);
        p = p->next;
    }
}

int main()
{
    LNode *head;
    int n;
    head = creat(10);
    printNode(head);
    printf("请输入需要插入的节点:\n");
    scanf("%d", &n);
    insert(n, head);
    printf("链表的新内容:\n");
    printNode(head);
    return 0;
}

综合本章例9.9(建立链表的函数creat)、例9.10(输出链表的函数print)和本章习题第7题(删除链表中结点的函数del)、第8题(插入结点的函数insert),再编写一个主函数,先后调用这些函数。用以上5个函数组成一个程序,实现链表的建立、输出、删除和插入,在主函数中指定需要删除和插人的结点的数据。

#include
#include
#define COUNT 5
typedef struct LNode
{
    int num;
    struct LNode *next;
} LNode;

LNode* create(int n)
{
    LNode *head, *p;
    head = (LNode *)malloc(sizeof(LNode));
    p = head; //头节点为0 加上头节点共11个节点
    head->num = 0;
    head->next = NULL;
    for (int i = 1; i <= n; i++)
    {
        LNode *newNode = (LNode *)malloc(sizeof(LNode));
        newNode->num = i;
        newNode->next = NULL;
        p->next = newNode;
        p = p->next;
    }
    return head;
}
//在指定位置插入数据
void insert(int n, int positon, LNode *root)
{
    //首先找到指定位置
    while (positon--)
    {
        root = root->next;
    }
    //插入新的数据,重新链接插入点的前后节点关系
    LNode *newNode = (LNode *)malloc(sizeof(LNode));
    newNode->num = n;
    newNode->next = root->next;
    root->next = newNode;
}
void del(int n, LNode *root)
{
    LNode *pre;
    while (root->num != n)
    {
        pre = root;
        root = root->next;
    }
    pre->next = root->next;
}
void printList(LNode *root)
{
    printf("----\n");
    int i = 0;
    while (root != NULL)
    {
        printf("node %d -> %d\n", i, root->num);
        root = root->next;
        i++;
    }
}

int main()
{
    int n, position;
    printf("请输入插入/删除的数,及插入的位置,位置最大为:%d\n", COUNT);
    scanf("%d %d", &n, &position);
    LNode *head = create(COUNT);
    printList(head->next);
    insert(n, position, head->next);
    printList(head->next);
    del(n, head->next);
    printList(head->next);
    return 0;
}

已有a,b两个链表,每个链表中的结点包括学号、成绩。要求把两个链表合并, 按学号升序排列。

解题思路及答案:

首先合并两个链表,然后采用选择排序,给合并之后的链表进行排序。

#include
typedef struct student
{
    int num;
    double grade;
    struct student *next;
} student;

student *merge(student *a, student *b)
{
    //先合并,后排序
    student *head = a;
    while (a->next != NULL)
    {
        a = a->next;
    }
    a->next = b;
    //选择排序,每次选最小的,放在未排序的链表头部
    student *pre;
    pre = head;
    while (pre->next != NULL)
    {
        a = pre->next;
        while (a != NULL)
        {
            if (pre->num > a->num)
            {
                int num = pre->num;
                double grade = pre->grade;
                pre->num = a->num;
                pre->grade = a->grade;
                a->num = num;
                a->grade = grade;
            }
            a = a->next;
        }
        pre = pre->next;
    }
    return head;
}
int main()
{
    student a[3] = {{1, 79}, {4, 36}, {5, 79}};
    for (int i = 0; i < 2; i++)
    {
        a[i].next = &a[i + 1];
    }

    student b[2] = {{2, 38}, {6, 98}};
    for (int i = 0; i < 1; i++)
    {
        b[i].next = &b[i + 1];
    }
    student *combine = merge(a, b);
    while (combine != NULL)
    {
        printf("%d -> %.2lf\n", combine->num, combine->grade);
        combine = combine->next;
    }

    return 0;
}

有两个链表a和b,设结点中包含学号、姓名。从a链表中删去与b链表中有相同学号的那些结点。

解题思路及答案:

对于b链表中的每一个节点,都从a链表的表头开始查找,如果可以找到,直接删除,如果找不到,继续从a链表表头找下一个b的节点。

#include
typedef struct student
{
    int num;
    double grade;
    struct student *next;
} student;
student *del(student *a, student *b)
{
    student *pre, *current, *head;
    head = a;

    while (b != NULL)
    {
        //重置指针指向a链表的头部
        pre = head;
        current = head->next;
        //a 链表的头等于b
        if (pre->num == b->num)
        {
            pre->next = NULL;
            pre = current;
            current = current->next;
            //更新表头
            head = pre;
        }
        else
        {
            while (pre->next != NULL)
            {
                if (current->num == b->num)
                {
                    //找到就删除
                    pre->next = current->next;
                    break;
                }
                else
                {
                    //否则继续遍历
                    pre = pre->next;
                    current = current->next;
                }
            }
        }
        b = b->next;
    }
    return head;
}

void printList(student *root)
{
    printf("----\n");
    int i = 0;
    while (root != NULL)
    {
        printf("student %d -> %d -> %.2lf\n", i, root->num, root->grade);
        root = root->next;
        i++;
    }
}

int main()
{
    student a[3] = { { 1, 79 }, { 4, 36 }, { 5, 79 } };
    for (int i = 0; i < 2; i++)
    {
        a[i].next = &a[i + 1];
    }
    a[2].next = NULL;
    printf("链表a:\n");
    printList(&a[0]);

    student b[2] = { { 5, 38 }, { 4, 98 } };
    for (int i = 0; i < 1; i++)
    {
        b[i].next = &b[i + 1];
    }
    b[1].next = NULL;
    printf("链表b:\n");
    printList(&b[0]);
    student *combine = del(a, b);
    printf("删除之后:\n");
    while (combine != NULL)
    {
        printf("%d -> %.2lf\n", combine->num, combine->grade);
        combine = combine->next;
    }

    return 0;
}

建立一个链表,每个结点包括:学号、姓名、性别、年龄。输入一个年龄,如果链表中的结点所包含的年龄等于此年龄,则将此结点删去。

#include
#include
typedef struct student
{
    int num;
    char sex[10];
    char name[100];
    int age;
    struct student *next;
} student;

void printList(student *root)
{
    printf("----\n");
    while (root != NULL)
    {
        printf("num:%d, sex: %s, name: %s, age: %d\n", root->num, root->sex, root->name, root->age);
        root = root->next;
    }
}

int main()
{
    student a[] = { { 1, "woman", "apple", 12 }, { 4, "woman", "banbana", 36 }, { 5, "man", "candy", 79 }, { 5, "man", "danny", 36 }, { 4, "man", "enjoy", 98 } };
    for (int i = 0; i < 4; i++)
    {
        a[i].next = &a[i + 1];
    }
    a[4].next = NULL;

    printList(&a[0]);

    int n;
    printf("请输入要删除的年龄:\n");
    scanf("%d", &n);
    student *pre = a, *current = a->next, *head;

    head = a;
    while (current != NULL)
    {
        //如果头结点需要删除,则更新头结点
        if (head->age == n)
        {
            pre->next = NULL;
            pre = current;
            current = current->next;
            head = pre;
        }
        else
        {
            //删除节点,重新链接
            if (current->age == n)
            {
                pre->next = current->next;
            }
            pre = current;
            current = current->next;
        }
    }
    printList(head);

    return 0;
}

从键盘输入一个字符串,将其中的小写字母全部转换成大写字母,然后输出到一个磁盘文件test中保存,输入的字符串以“!”结束。

#include
#include

int main( void ) {
    FILE *fp = NULL;
    char c;
    int i;
    
    if ( (fp=fopen("test", "w")) == NULL ) {
        printf("open file test error!\n");
        exit(EXIT_FAILURE);
    }

    while ( (c=getchar()) != EOF && c != '!' ) {
        if ( c>='a' && c<='z' )
            c = c-'a' + 'A';
        fputc(c, fp);
    }

    fclose(fp);
}

结果:

输入 : 123我的AbcABC!
test文件的内容 : 123我的ABCABC

有两个磁盘文件A和B,各存放一行字母,今要求把这两个文件中的信息合并(按字母顺序排列),输出到一个新文件C中去。

#include
#include
#include

void swap(char *s, int i, int j) {
    char t = s[i];
    s[i] = s[j];
    s[j] = t;
}

void select_sort(char *str) {
    int i, j;
    int len = strlen(str);
    for (i=0; i         int min = i;
        for (j=i+1; j             if ( str[j] < str[min] )
                min = j;
        }   
        swap(str, min, i); 
    }   
}

int main( void ) { 
    FILE *fa, *fb, *fc;
    char buf[1024] = {0};

    fa = fopen("A", "r");
    fb = fopen("B", "r");
    fc = fopen("C", "w");

    fgets(buf, 1024, fa);
    int len = strlen(buf);
    fgets(buf+len, 1024-len, fb);
    select_sort(buf);
    fputs(buf, fc);

    fclose(fa);
    fclose(fb);
    fclose(fc);
}

有5个学生,每个学生有3门课程的成绩,从键盘输人学生数据(包括学号,姓名,3门课程成绩),计算出平均成绩,将原有数据和计算出的平均分数存放在磁盘文件stud中。

#include
#include

struct student {
    int num;
    char name[32];
    int score[3];
    float avg;
};

int main( viod ) { 
    int i;
    struct student stu[5];
    FILE *fp = NULL;
        
    for (i=0; i<5; i++) {
        printf("num name score1 score2 score3:\n");
        scanf("%d %s %d %d %d", &stu[i].num, &stu[i].name, 
            &stu[i].score[0],&stu[i].score[1],&stu[i].score[2]);
        stu[i].avg = (stu[i].score[0]+stu[i].score[1]+stu[i].score[2])/3.0;
    }   

    if ( (fp=fopen("stud", "wb")) == NULL ) { 
        printf("open file stud for write error\n");
        return 1;
    }

    if ( fwrite(stu, sizeof(stu), 1, fp) != 1 ) {
        printf("write error\n");
        return 1;
    }
    fclose(fp);
}

测试程序查看输入文件的容:

1 zhagnsan 10 20 30 20.000000
2 lisi 3 6 9 6.000000
3 wangwu 1 2 3 2.000000
4 zhaoliu 90 80 10 60.000000
5 sunqi 90 1 1 30.000000

将上题stud文件中的学生数据,按平均分进行排序处理,将已排序的学生数据存入一个新文件stu_ sort 中。

#include
#include

struct student {
    int num;
    char name[32];
    int score[3];
    float avg;
};

void sort(struct student stu[], int len) {
    int i, j;
    struct student tmp;
    for (i=0; i         int min = i;
        for (j=i+1; j             if ( stu[j].avg > stu[min].avg )
                min = j;
        }   
        tmp = stu[min];
        stu[min] = stu[i];
        stu[i] = tmp;
    }   
}

int main( viod ) {
    int i;
    struct student stu[5];
    FILE *fp = NULL;
    if ( (fp=fopen("stud", "rb")) == NULL ) {
        printf("open file stud for read error\n");
        return 1;
    }

    if ( fread(stu, sizeof(stu), 1, fp) != 1 ) {
        printf("write error\n");
        return 1;
    }
    fclose(fp);

    sort(stu, 5);

    FILE *fw = fopen("stu_sort", "wb");
    fwrite(stu, sizeof(stu), 1, fw);
    fclose(fw);
}

测试程序,查看文件内容,确实排过序:

4 zhaoliu 90 80 10 60.000000
5 sunqi 90 1 1 30.000000
1 zhagnsan 10 20 30 20.000000
2 lisi 3 6 9 6.000000
3 wangwu 1 2 3 2.000000

将上题已排序的学生成绩文件进行插人处理。插人一个学生的3门课程成绩,程序先计算新插人学生的平均成绩,然后将它按成绩高低顺序插入,插入后建立一个新文件。

#include
#include
#include

struct student {
    int num;
    char name[32];
    int score[3];
    float avg;
};

void sort(struct student stu[], int len) {
    int i, j;
    struct student tmp;
    for (i=0; i         int min = i;
        for (j=i+1; j             if ( stu[j].avg > stu[min].avg )
                min = j;
        }   
        if ( min != i ) { 
            tmp = stu[min];
            stu[min] = stu[i];
            stu[i] = tmp;
        }   
    }   
}
int main( viod ) { 
    int i;
    struct student stu[5];
    FILE *fp = NULL;
    if ( (fp=fopen("stu_sort", "rb")) == NULL ) {
        printf("open file stud for read error\n");
        return 1;
    }

    if ( fread(stu, sizeof(stu), 1, fp) != 1 ) {
        printf("write error\n");
        return 1;
    }
    fclose(fp);

    struct student new_stu[6];
    memcpy(new_stu, stu, sizeof(stu));
    printf("num name score0 score1 score2:\n");
    scanf("%d %s %d %d %d", &new_stu[5].num, &new_stu[5].name, &new_stu[5].score[0],
            &new_stu[5].score[1], &new_stu[5].score[2]);
    new_stu[5].avg = (new_stu[5].score[0]+new_stu[5].score[1]+new_stu[5].score[2])/3.0;
    sort(new_stu, 6);

    FILE *fw = fopen("tmp_sort", "wb");
    fwrite(new_stu, sizeof(new_stu), 1, fw);
    fclose(fw);
}

查看tmp_sort文件,确实插入和排序了:

4 zhaoliu 90 80 10 60.000000
5 sunqi 90 1 1 30.000000
1 zhagnsan 10 20 30 20.000000
8 hehe 12 3 4 6.333333
2 lisi 3 6 9 6.000000
3 wangwu 1 2 3 2.000000

将上题结果仍存人原有的stu_sort 文件而不另建立新文件。

#include
#include
#include

struct student {
    int num;
    char name[32];
    int score[3];
    float avg;
};

int main( viod ) { 
    int i;
    struct student stu[6];
    FILE *fp = NULL;
    if ( (fp=fopen("tmp_sort", "rb")) == NULL ) { 
        printf("open file stud for read error\n");
        return 1;
    }   

    if ( fread(stu, sizeof(stu), 1, fp) != 1 ) { 
        printf("write error\n");
        return 1;
    }   
    fclose(fp);

    FILE *fw = fopen("stu_sort", "wb");
    fwrite(stu, sizeof(stu), 1, fw);
    fclose(fw);
}

查看原本的stu_sort文件:

4 zhaoliu 90 80 10 60.000000
5 sunqi 90 1 1 30.000000
1 zhagnsan 10 20 30 20.000000
8 hehe 12 3 4 6.333333
2 lisi 3 6 9 6.000000
3 wangwu 1 2 3 2.000000

有一磁盘文件employee,内存放职工的数据。每个职工的数据包括职工姓名、职工号、性别、年龄、住址、工资、健康状况、文化程度。今要求将职工名、工资的信息单独抽出来另建一个简明的职工工资文件。

#include
#include
#include

struct employee {
    int  num;      // 编号
    char name[32];
    char sex[4]; 
    int  age;
    char addr[60];
    int  salary;   
    char health[10]; // 健康状况
    char class[10];  // 文化程度
};

struct emp {
    char name[32];
    int salary;
};

int main( void ) { 
    int i;
    FILE *fp1, *fp2; 
    struct emp emp_arr[5];
    struct employee employee_arr[5];

    fp1=fopen("employee", "rb");
    fread(employee_arr, sizeof(employee_arr), 1, fp1);
    fclose(fp1);

    for (i=0; i<5; i++) {
        strcpy(emp_arr[i].name, employee_arr[i].name);
        emp_arr[i].salary = employee_arr[i].salary;
    }

    fp2=fopen("emp", "wb");
    fwrite(emp_arr, sizeof(emp_arr), 1, fp2);
    fclose(fp2);
}

查看emp文件的内容如下:

abc 1800 
def 2000 
hehe 3000 
haha 2800 
ggg 2500 

从上题的“职工工资文件”中删去一个职工的数据,再存回原文件。

#include
#include
#include

struct emp {
    char name[32];
    int salary;
};

int main( void ) { 
    int i;
    FILE *fp;
    char name[32]; 
    struct emp emp_arr[5];

    fp=fopen("emp", "rb");
    fread(emp_arr, sizeof(emp_arr), 1, fp);
    fclose(fp);

    printf("name:");
    scanf("%s", &name);
    fp=fopen("emp", "wb");
    for (i=0; i<5; i++) {
        if ( strcmp(emp_arr[i].name, name) == 0 ) { 
            continue;
        }   
        fwrite(&emp_arr[i], sizeof(emp_arr[i]), 1, fp);
    }   
    fclose(fp);
}

删除ggg后的源文件内容:

abc 1800 
def 2000 
hehe 3000 
haha 2800 

从键盘输人若干行字符(每行长度不等),输人后把它们存储到一磁盘文件中。再从该文件中读入这些数据,将其中小写字母转换成大写字母后在显示屏上输出。

#include
#include
#include

int main( void ) { 
    int i;
    FILE *fp = fopen("tmp.txt", "w");
    char buf[1024] = {}; 
    
    while ( fgets(buf, 1024, stdin) != NULL ) { 
        fputs(buf, fp);
        memset(buf, 0x00, sizeof(buf));
    }   
    fclose(fp);

    fp = fopen("tmp.txt", "r");
    while ( !feof(fp) ) { 
        memset(buf, 0x00, sizeof(buf));
        fgets(buf, 1024, fp);
        for (i=0; buf[i] != '\0'; i++) {
            if ( buf[i]>='a' && buf[i]<='z' )
                printf("%c", buf[i]-32);
            else
                printf("%c", buf[i]);
        }   
    }   
    fclose(fp);
}

执行结果:

输入:
this is maomaochong
litao love IDFD
1243
输出:
THIS IS MAOMAOCHONG
LITAO LOVE IDFD
1243

你可能感兴趣的:(c语言,笔记,开发语言)