C语言谭浩强第三版第八章例题及课后题:函数
eg8.6用弦截法求方程的根
//eg8.6用弦截法求方程的根
#include<stdio.h>
#include<math.h>
float fun(float x);
float xpoint(float x1, float x2);
float root(float x1, float x2);
float root(float x1, float x2){
float x = xpoint(x1, x2);
while(fabs(fun(x)) >= 1e-6){
if(fun(x)*fun(x1) > 0){
x1 = x;
}else if(fun(x)*fun(x2) > 0){
x2 = x;
}
x = xpoint(x1, x2);
}
return x;
}
float xpoint(float x1, float x2){
float x;
return x = (x1*fun(x2)-x2*fun(x1)) / (fun(x2)-fun(x1));
}
float fun(float x){
float y;
return y = x*x*x-5*x^2+16*x-80;
}
void main(void){
float x1;
float x2;
float x;
printf("Please input x1 and x2 :");
scanf("%f%f", &x1, &x2);
printf("What you just input are :%f , %f\n", x1, x2);
while(fun(x1)*fun(x2) >= 0){
printf("What you input is wrong, please input again :");
scanf("%f%f", &x1, &x2);
printf("What you just input are :%f , %f\n", x1, x2);
}
x = root(x1, x2);
printf("The root of the function is :%f\n", x);
}
eg8.7递归求年龄
一个递归问题可以分为“回推”好“地推”两个阶段,要经历若干步才能求出最后的值。显而易见,如果要求递归过程不是无限制进行下去,必须具有一个结束递归过程的条件。
总结:递归其实也不难,首先分析题意,写出递归表达式,根据表达式进行程序编写。
//eg8.7递归求年龄
#include<stdio.h>
int age(int n);
int age(int n){
int c;
if(n==1){
c = 10;
}else{
c = age(n-1)+2;
}
return c;
}
void main(void){
printf("%d\n", age(5));
}
eg8.8用递归方法求n!
#include<stdio.h>
int factorial(int n);
int factorial(int n){
int y;
if(n == 0 || n == 1){
y = 1;
}else{
y = n*factorial(n-1);
}
return y;
}
void main(void){
int n;
int y;
printf("Please input a positive number:");
scanf("%d", &n);
y = factorial(n);
printf("%d!为%d\n", n, y);
}
eg8.9汉诺塔
#include<stdio.h>
void hanoi(int n, char a, char b, char c);
void move(char a, char b);
void move(char a, char b){
printf("%c ---> %c\n", a, b);
}
void hanoi(int n, char a, char b, char c){
if(n == 1){
move(a, c);
}else{
hanoi(n-1, a,c,b);
move(a,c);
hanoi(n-1, b,a,c);
}
}
void main(void){
int n;
printf("Please input a positive number:");
scanf("%d", &n);
hanoi(n, 'A', 'B', 'C');
}
eg8.10比较两个数组的元素
/*
有两个数组a和b,各有10个元素,将它们对应地逐个比较。
如果a数组中的元素大于b数组中的相应元素的数目多余b数组中元素大于a数组中相应元素的数目,
则认为a数组大于b数组,并分别统计出两个数组相应元素大于、小于、等于的次数。
*/
//1 3 5 7 9 8 6 4 2 0
//5 3 8 9 -1 -3 5 6 0 4
#include<stdio.h>
void initial(int a[], int n);
void initial(int a[], int n){
int i;
for(i = 0; i < n; i++){
scanf("%d", &a[i]);
}
}
void main(void){
int a[10];
int b[10];
int i;
int big = 0;
int small = 0;
int equal = 0;
int sum = 0;
printf("请输入a数组10个元素的值:");
initial(a,10);
printf("请输入b数组10个元素的值:");
initial(b,10);
for(i = 0; i < 10; i++){
if(a[i] > b[i]){
big++;
}else if(a[i] < b[i]){
small++;
}else{
equal++;
}
}
sum = big-small;
if(sum > 0){
printf("a数组大于b数组\n");
}else if(sum < 0){
printf("a数组小于b数组\n");
}else{
printf("a数组等于b数组\n");
}
printf("大于的次数为%d,小于的次数为%d,等于的次数为%d\n", big, small, equal);
}
eg8.11有一个一维数组score,内放10个学生成绩,求平均成绩
数组名做函数参数:此时形参应该是数组名或用指针变量 在被调用函数中声明形参数组的大小是不切任何作用的,因为c语言编译对形参数组不做检查,只是将实参数组的首元素的地址传给形参数组。 形参数组可以不指定大小,在定义数组时在数组名后面跟一个空的方括号。有时为了在被调用函数中处理数组元素的需要,可以另设一个形参,传递需要处理的数组元素的个数。
|
//eg8.11有一个一维数组score,内放10个学生成绩,求平均成绩
//100 56 78 98.5 76 87 99 67.5 75 97
#include<stdio.h>
void initial(float a[], int n);
float average(float a[], int n);
void show(float a[], int n);
void show(float a[], int n){
int i;
printf("这十个同学的成绩为:");
for(i = 0; i < n; i++){
printf("%.1f ", a[i]);
}
printf("\n");
}
float average(float a[], int n){
float av = 0;
int i;
for(i = 0; i < n; i++){
av += a[i];
//printf("av=%.1f\n", av); //debug
}
printf("av=%.1f\n", av);
return av /= n;
}
void initial(float a[], int n){
int i;
for(i = 0; i < n; i++){
scanf("%f", &a[i]); // scanf("%d", &a[i]);
}
}
void main(void){
float a[10];
float av;
printf("请输入10个学生成绩:");
initial(a,10);
show(a,10);
av = average(a, 10);
printf("平均成绩为:%.1f\n", av);
}
eg8.14求二维数组元素中的最大值
多维数组名做函数参数
|
//eg8.14求二维数组元素中的最大值
//1 3 5 7 2 4 6 8 15 17 34 12
#include<stdio.h>
void initial(int a[][4], int n);
void show(int a[][4], int n);
int max(int a[][4], int n);
void swap(int *a, int *b);
void swap(int *a, int *b){
int tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
int max(int a[][4], int n){
int m = a[0][0];
int i,j;
for(i = 0; i < n; i++){
for(j = 0; j < 4; j++){
if(m < a[i][j]){
swap(&m, &a[i][j]);
}
}
}
return m;
}
void show(int a[][4], int n){
int i,j;
printf("二维数组元素的值为:\n");
for(i = 0; i < n; i++){
for(j = 0; j < 4; j++){
printf("%2d ", a[i][j]);
}
printf("\n");
}
}
void initial(int a[][4], int n){
int i,j;
int m;
printf("请输入3x4个元素:");
for(i = 0; i < n; i++){
for(j = 0; j < 4; j++){
scanf("%d", &a[i][j]);
}
}
}
void main(void){
int a[3][4];
int m;
initial(a, 3);
show(a, 3);
m = max(a,3);
printf("该二维数组中的最大值为%d\n", m);
}
8.1求最大公约数和最小公倍数(同6.1)
8.2求一元二次方程的根(似eg5.6)
greater than zero / smaller than zero / equal to zero
//8.2求一元二次方程的根
#include<stdio.h>
#include<math.h>
//2 4 1
//1 2 1
//2 4 3
void diataGreaterThanZero(double diata, double a, double b);
void diataEqualToZero(double diata, double a, double b);
void diataSmallerThanZero(double diata, double a, double b);
void diataEqualToZero(double diata, double a, double b){
double m;
double n;
double x1;
double x2;
m = -b * 1.0 / (2 * a);
n = sqrt(diata) * 1.0 / (2 * a);
x1 = m + n;
x2 = m - n;
printf("该方程有一对相等的实根:%lf, %lf\n", x1, x2);
}
void diataSmallerThanZero(double diata, double a, double b){
double m;
double n;
//double x1;
//double x2;
m = -b * 1.0 / (2 * a);
//n = sqrt(diata) * 1.0 / (2 * a);
n = sqrt((-1)*diata) * 1.0 / (2 * a);
//printf("该方程有一对相等的实根:%lf, %lf\n", x1, x2);
printf("该方程有两个共轭复根: %lf + i%lf, %lf - i%lf\n", m, n, m, n);
}
void diataGreaterThanZero(double diata, double a, double b){
double m;
double n;
double x1;
double x2;
m = -b * 1.0 / (2 * a);
n = sqrt(diata) * 1.0 / (2 * a);
x1 = m + n;
x2 = m - n;
printf("该方程有一对不相等的实根:%lf, %lf\n", x1, x2);
}
void main(void){
double a, b, c;
double diata;
printf("请输入一元二次方程的三个系数:");
scanf("%lf%lf%lf", &a, &b, &c);
printf("三个系数为:%f %f %f\n", a, b, c);
if(fabs(a) <= 1e-6){//if(a == 0){
printf("该方程不是一元二次方程\n");
}
diata = pow(b,2) - 4*a*c;
if(diata < 0){
diataSmallerThanZero(diata, a, b);
}else if(diata == 0){
diataEqualToZero(diata, a, b);
}else{
diataGreaterThanZero(diata, a, b);
}
}
8.3判断素数(似eg6.8)
//8.3
//eg6.8判断m是否素数
//质数(prime number)又称素数,有无限个。
//质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数。
#include<stdio.h>
#include<math.h>
int isPrimeNumber(int m);
int isPrimeNumber(int m){
int i;
int n = 0;
for(i = 2; i <= sqrt(m); i++){
if(m%i == 0){
n++;
break;
}
}
return n;
}
void main(void){
int m;
int n;
printf("请输入一个正整数:");
scanf("%d", &m);
printf("输入的值为:%d\n", m);
n = isPrimeNumber(m);
if(n == 1){
printf("m不是素数\n" );
}else{
printf("m是素数\n");
}
}
8.4转置二维数组的行列
小技巧:之前的那个题要求存到另一个数组中,所以需要另外开辟一个数组 ;现在这个题只要求转置行列,书中给了一个比较好的方法,只开辟一个变量,就像交换两个数一样,这样就可以节省很多存储空间
错误:如果遍历数组的所有元素,则会转置两次,相当于没有转置;所以课本中从i+1遍历,这样只遍历上三角的元素,对角线也不用转置,所以省了很多操作。
|
//8.4
//eg7.4将一个二维数组a的行和列的元素互换,存到另一个二维数组b中
/*
之前的那个题要求存到另一个数组中,所以需要另外开辟一个数组
现在这个题只要求转置行列,书中给了一个比较好的方法,只开辟一个变量,
就像交换两个数一样,这样就可以节省很多存储空间
*/
#include<stdio.h>
#define N 3
void initial(int a[][N]);
void show(int a[][N]);
void convert(int a[][N]);
/*
void convert(int a[][N]){
int i,j;
int tmp;
for(i = 0; i < N; i++){
for(j = 0; j < N; j++){
tmp = a[i][j];
a[i][j] = a[j][i];
a[j][i] = tmp;
}
printf("\n");
}
}
*/
void convert(int a[][N]){
int i,j;
int tmp;
for(i = 0; i < N; i++){
for(j = i+1; j < N; j++){
tmp = a[i][j];
a[i][j] = a[j][i];
a[j][i] = tmp;
}
printf("\n");
}
}
void show(int a[][N]){
int i,j;
for(i = 0; i < N; i++){
for(j = 0; j < N; j++){
printf("%d ", a[i][j]);
}
printf("\n");
}
}
void initial(int a[][N]){
int i, j;
for(i = 0; i < N; i++){
for(j = 0; j < N; j++){
scanf("%d", &a[i][j]);
}
}
}
void main(void){
int a[N][N];
printf("Please input %dx%d 个元素:", N, N);
initial(a);
printf("a数组中的元素为:\n"); //将a数组元素的输出和u具体的元素交换放到一起做了,没有什么影响
show(a);
convert(a);
printf("交换后a数组中的元素为:\n");
show(a);
}
8.5写一个函数,使输入的字符串按反序存放,在主函数中输入和输出字符串
小技巧:数组元素反序存放
//若index=10,即零字符结束标志在下标为10的地方 i ---- index-i-1 0 ----- 9 1 ----- 8 2 ----- 7 3 ----- 6 4 ----- 5 |
//8.5写一个函数,使输入的字符串按反序存放,在主函数中输入和输出字符串
#include<stdio.h>
#include<string.h>
void convert(char str[]);
void convert(char str[]){
int index;
int i;
int tmp;
index = strlen(str);
printf("index=%d\n", index);
for(i = 0; i < index/2; i++){ //for(i = 0; i < index; i++){
tmp = str[i];
str[i] = str[index-i-1]; //str[i] = str[index-i+1];
str[index-i-1] = tmp; //str[index-i+1] = tmp;
printf("**%c**\n", str[i]);
}
}
void main(void){
char str[100];
printf("请输入一串字符:");
gets(str);
printf("输入的字符串为:%s\n", str);
convert(str);
printf("按反序存放后的字符串为:%s\n", str);
}
8.6写一个函数,将两个字符串连接
#include<stdio.h>
#include<string.h>
void stringCat(char str1[], char str2[], char str[]);
void stringCat(char str1[], char str2[], char str[]){
int index;
int i;
/*
for(i = 0; i < 80; i++){
if(str1[i] == '\0'){
index = i;
break;
}
}
*/
index = strlen(str1);
printf("index=%d\n", index);
strcpy(str,str1);
for(i = index; i < strlen(str2)+index+1; i++){
str[i] = str2[i-index];
}
}
void main(void){
char str1[80];
char str2[80];
char str[80] = {0};
printf("请输入第一串字符:");
gets(str1);
printf("请输入第二串字符:");
gets(str2);
stringCat(str1, str2, str);
printf("合并的字符串为:");
puts(str);
}
8.7写一个函数,将一个字符串中的元音字母复制到另一个字符串,然后输出
//
//abcdefghijklmn
#include<stdio.h>
#include<string.h>
void stringCopy(char str1[], char str2[]); //将1的复制到2
void stringCopy(char str1[], char str2[]){
int index;
int i, j;
char c;
index = strlen(str1);
for(i = 0, j = 0; i < index; i++){
c = str1[i];
if(c == 'a' || c == 'o' || c == 'e' || c == 'i' || c == 'u' || c == 'A' || c == 'O' || c == 'E' || c == 'I' || c == 'U'){
str2[j++] = c;
}
}
}
void main(void){
char str1[80];
char str2[80];
printf("请输入一串字符:");
gets(str1);
stringCopy(str1, str2);
printf("这串字符中的元音字符有:%s\n", str2);
}
8.8输入一个4位数字,要求输出这4个数字字符,但没两个数字间空一个空格
小技巧:中间加空间输出
思考:为什么要用--的形式? 因为用++的形式会覆盖原值,用--的话先从数组的后面开始,这样就不会影响原来数组中的值;这也给了我们一种新的输出数值的方法。
|
//8.8输入一个4位数字,要求输出这4个数字字符,但没两个数字间空一个空格
/*
//自己输入的这个是数字,但题目要求是字符
//自己的这个没有弄出最终结果,出了一些问题
#include<stdio.h>
void showBySomeRule(int n);
void showBySomeRule(int n){
int m = n;
int tmp;
int i = 1000;
while(((i*10)%10) == 1){
tmp = n/i%10;
printf("%d ", tmp);
n %= i;
//printf("n=%d\n", n);
i/=10;
}
printf("\n");
}
void main(void){
int num;
printf("请输入一个4位数字:");
scanf("%d", &num);
printf("该4位数字为:%d\n", num);
showBySomeRule(num);
printf("按规则输出为:");
}
*/
#include<stdio.h>
#include<string.h>
void showBySomeRule(char str[]);
/* 自己
void showBySomeRule(char str[]){
int index;
int i;
index = strlen(str);
for(i = 0; i < index; i++){
printf("%c ", str[i]);
}
printf("\n");
}
*/
//课本
void showBySomeRule(char str[]){
int i;
for(i = strlen(str); i>0; i--){
str[2*i] = str[i];
str[2*i-1] = ' ';
}
printf("%s", str);
}
void main(void){
char str[80];
printf("请输入4个数字字符:");
scanf("%s", str);
printf("该4个数字字符为:%s\n", str);
printf("按规则输出为:");
showBySomeRule(str);
}
8.9统计字符串中字母、数字、空格和其他字符的个数
//My address is #123 Shanghai Road,Beijing,100045.
#include<stdio.h>
#include<string.h>
int letter;
int digit;
int space;
int other;
void doIt(char str[]);
void doIt(char str[]){
char c;
int i;
for(i = 0; i < strlen(str); i++){
c = str[i];
if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')){
letter++;
}else if(c == ' '){
space++;
}else if(c >= '0' && c <= '9'){
digit++;
}else{
other++;
}
}
}
void main(void){
char str[80];
letter = 0;
space = 0;
digit = 0;
other = 0;
printf("请输入一行字符:");
gets(str);
doIt(str);
printf("其中英文字母的个数为:%d\n空格数为:%d\n数字数为:%d\n其他字符的个数为:%d\n", letter, space, digit, other);
}