C语言谭浩强第三版第八章例题及课后题:函数

 

eg8.6用弦截法求方程的根

C语言谭浩强第三版第八章例题及课后题:函数

C语言谭浩强第三版第八章例题及课后题:函数

//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递归求年龄

C语言谭浩强第三版第八章例题及课后题:函数

C语言谭浩强第三版第八章例题及课后题:函数

一个递归问题可以分为“回推”好“地推”两个阶段,要经历若干步才能求出最后的值。显而易见,如果要求递归过程不是无限制进行下去,必须具有一个结束递归过程的条件。

总结:递归其实也不难,首先分析题意,写出递归表达式,根据表达式进行程序编写。

//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语言编译对形参数组不做检查,只是将实参数组的首元素的地址传给形参数组。

形参数组可以不指定大小,在定义数组时在数组名后面跟一个空的方括号。有时为了在被调用函数中处理数组元素的需要,可以另设一个形参,传递需要处理的数组元素的个数。

C语言谭浩强第三版第八章例题及课后题:函数       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求二维数组元素中的最大值 

多维数组名做函数参数

 

C语言谭浩强第三版第八章例题及课后题:函数   C语言谭浩强第三版第八章例题及课后题:函数

//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)

C语言谭浩强第三版第八章例题及课后题:函数

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)

C语言谭浩强第三版第八章例题及课后题:函数

//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转置二维数组的行列

C语言谭浩强第三版第八章例题及课后题:函数

小技巧:之前的那个题要求存到另一个数组中,所以需要另外开辟一个数组 ;现在这个题只要求转置行列,书中给了一个比较好的方法,只开辟一个变量,就像交换两个数一样,这样就可以节省很多存储空间 

 

错误:如果遍历数组的所有元素,则会转置两次,相当于没有转置;所以课本中从i+1遍历,这样只遍历上三角的元素,对角线也不用转置,所以省了很多操作。

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

 

//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写一个函数,使输入的字符串按反序存放,在主函数中输入和输出字符串

小技巧:数组元素反序存放

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

//若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个数字字符,但没两个数字间空一个空格

小技巧:中间加空间输出

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

思考:为什么要用--的形式?

因为用++的形式会覆盖原值,用--的话先从数组的后面开始,这样就不会影响原来数组中的值;这也给了我们一种新的输出数值的方法。

 

//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统计字符串中字母、数字、空格和其他字符的个数

C语言谭浩强第三版第八章例题及课后题:函数

//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);

}