《C语言程序设计(第3版)》教材配套习题 第四章

第四章 循环结构

    • 简单的循环
          • 统计指定数量学生的平均成绩与不及格人数
          • 统计一个整数的位数
          • 用格里高利公式求给定精度的PI值
          • 从高位开始逐位输出各位数字
    • 素数
          • 判断是否素数
          • 输出2到n之间的素数
    • 循环迭代
          • 计算阶乘和
          • 输出前 n 个菲波那契Fibonacci数
    • 嵌套循环
          • 穷举问题-搬砖

简单的循环

统计指定数量学生的平均成绩与不及格人数

小结:

  1. 输入多个数不需要存储时,直接使用后直接覆盖即可,不必用数组装起来
  2. 数组的空间分配不能用另一个 从键盘输入值的变量 来初始化,即a[N]中的N不能是依靠键盘输入取值的变量
//平均成绩,并统计不及格(成绩低于60分)的人数。题目保证输入与输出均在双精度范围内
#include <stdio.h>
//#define MAX 255

int main()
{
    int n; //学生人数
    //double score[MAX];
    double score = 0;
    
    int cnt = 0; //不及格人数
    double sum = 0; //总成绩
    double average = 0; //平均数
    
    scanf("%d", &n);
    
    for ( int i=0; i<n; i++ ){
        scanf("%lf", &score);
        sum += score;
        if ( score<60 ) cnt++;
    }
    
    if ( n>0 ) average = sum / n;
    
    printf("average = %.2f\n", average);
    printf("count = %d", cnt);
    
    return 0;
}
统计一个整数的位数

输入:在一行中给出一个绝对值不超过10​9​​的整数N。
分析:

  1. “绝对值”,说明有负数,先要有if判断,将负数转成正数
  2. 不超过10​9​​,即 ①有0(需要先统计用do-while),②int型就可以装得下
 #include <stdio.h>
//输入在一行中给出一个绝对值不超过10^9的整数N
int main()
{
    int N, tmp, cnt = 0;
    
    scanf("%d", &N);
    tmp = N;
    
    //用非负整数来判断
    if ( tmp<0 ){
        tmp = -tmp;
    }
    
    //因为有0,所以先循环一次
    do{
        cnt++;
        tmp /= 10;
    }while( tmp != 0 );
    
    printf("%d", cnt);
    
    return 0;
}
用格里高利公式求给定精度的PI值

要求:计算序列部分和 4∗(1−1/3+1/5−1/7+…) ,直到最后一项的绝对值小于给定精度eps。题目保证输入数据和计算结果均不超过双精度范围。
分析:

  1. 总公式:先求和,后乘以系数4→sum, (const)ratio
  2. 每项:分子为1,分母从1开始以2递增→结果为double
  3. 每项正负:奇数项为正,偶数项为负→可以 ①计项数,判奇偶;②给系数,控正负
  4. “后一项的绝对值小于给定精度eps”,即小于给定精度的那一项也要加上→第一项肯定可加,可设sum初始值为1
#include <stdio.h>
#include <math.h>
//最后一项的绝对值小于给定精度eps,即小于给定精度的那一项也要加上

int main()
{
    double eps;
    double sum = 1; //第一项是肯定有的
    double denominator = 1; //分母不能为0
    double pi = 0;
    double item = 1; //第一项为1
    int factor = 1; //控制正负项
    const double ratio = 4.0; //系数
    
    scanf("%lf", &eps);
    
    
    while ( fabs(item) >= eps ){
        factor = -factor;
        denominator += 2;
        item = factor * 1.0 / denominator;
        sum += item;
    }
    
    pi = ratio * sum;
    printf("Pi = %.4f", pi);
    
    return 0;
}
从高位开始逐位输出各位数字

输入:一个非负整数
思路

  1. 除以10的n-1次方,来依次获得从高位开始的数字
    →需要知道这个数的位数
int number, t_number;
int pow = 1; //用来存除数——10的n-1次方
int digit = 0; 

scanf ("%d", &number);
t_number = number;

while(t_number > 9){
	pow *= 10;
	t_number /= 10;
}

while(pow >= 1){
	digit = number / pow; //取最高位
	number %= 10*pow; //留下低位
	pow /= 10;
	printf ("%d ", digit);
}

素数

判断是否素数

题目:判断一个给定的整数是否为素数。素数就是只能被1和自身整除的正整数,1不是素数,2是素数。
输入:在一行中给出一个需要判断的整数 M(−2​31​​≤M≤2​31​​−1)。
分析

  1. 先初始化is_prim为1,即是素数;一下排除非素数即可
  2. 根据M的范围,可知,需要排除非正数;加上1,m<=1的整数都不是素数。
  3. 再排除2和可以被2整除的m
  4. 只需要从3开始,以2递增,测试到sqrt(m)(需要等号,否则9判断不了),若整除,则标记为非素数,并”break;“
int is_prime = 1; //默认为素数;0为非素数
int m;
int limit = 0;

scanf("%d", &m);
limit = sqrt(m);

//if ( m<=1 ){
//    is_prime = 0; 
//}
//else if ( m==2 ) ;
//else if ( m%2==0 ) is_prime = 0;
//--以上可以合并如下,即可用逻辑运算简化
if ( m<=1 || (m%2==0 && m!=2) ) is_prime = 0;
else{
    for ( int i=3; i<=limit; i+=2 ){
        if ( m%i==0 ){
            is_prime = 0;
            break;
        }
    }
}

if ( is_prime ) printf("Yes");
else printf("No");
输出2到n之间的素数

输入:在一行中给出一个长整型范围内的整数。
输出:素数,每个数占6位,每行输出10个。如果最后一行输出的素数个数不到10个,也需要换行。
思路

  1. 封装:把判断素数装在函数里面
  2. 计数器:控制换行;换行后重新计数,可满足最后一行的换行条件
#include <stdio.h>
#include <math.h>

int isPrime(long long m);
int main()
{
    long long n;
    long long cnt = 0; //计数器
    
    scanf("%lld", &n);
    
    for ( int i=2; i<=n; i++ ){
    	//输出素数并计数
    	if ( isPrime(i) ){  
    		printf("%6lld", i);
    		cnt++;
		}
		//控制每行10个
		if ( cnt==10 ){  
			printf("\n");
			cnt = 0; //清零后,控制最后一行不到10个也要换行 
		}
	}
	
	//控制最后一行不到10个也要换行
	if ( cnt ) printf("\n");   
    
    return 0;
}

int isPrime(long long m)
{
	int is_prime = 1;  //默认为素数
	
	//只要排除非素数即可
	if ( m<=1 || (m%2==0 && m!=2) ) is_prime = 0;
	else{
		for ( int i=3; i<=sqrt(m); i+=2 ){ //这里需要等号,否则9判断不了
			if ( m%i==0 ){
				is_prime = 0;
				break;
			}
		}
	}
	
	return is_prime;
}

循环迭代

计算阶乘和

方案:

  1. 依次单独求n!后,求和
  2. 阶乘直接累乘,求和,如下
int n;
double sum = 1;
double fact = 1;
 
scanf("%d", &n);
if ( n<=10 ){
    for ( int i=2; i<=n; i++ ){
        fact *= i;
        sum += fact;
    }
    printf("%.0f", sum);
}
输出前 n 个菲波那契Fibonacci数

Fibonacci数列就是满足任一项数字是前两项的和(最开始两项均定义为1)的数列,例如:1,1,2,3,5,8,13,…。
输入:在一行中给出一个整数N(1≤N≤46)。
输出:前N个Fibonacci数,每个数占11位,每行输出5个。如果最后一行输出的个数不到5个,也需要换行。如果N小于1,则输出"Invalid."。题目保证输出结果在长整型范围内。
方法:迭代法

  1. 初始化三个变量a,b,f为1,分别作为a[n], a[n+1], a[n+2]
  2. f:作为输出值,f=a+b(前两项之和)
  3. a,b:先后移a(即赋b的值),则后移b(即赋f的值)
  4. 计数器:控制输出,【同例.输出素数】
#include <stdio.h>

int main()
{
    int n;
    int cnt = 0;
    long long f, a, b;
    f = a = b = 1;
    
    scanf("%d", &n);
    
	if ( n<1 ) printf("Invalid.");
	else if ( n==1 ) printf("%11lld", a);
	else if ( n<=46 ){
		printf("%11lld%11lld", a, b);
		cnt = 2;
		
		//从第三项开始计算 
		for ( int i=3; i<=n; i++ ){
    		f = a+b; //前两项之和     		
    		a = b; //第一项后移一项 
    		b = f; //第二项后移一项 
    		
    		//输出 
    		printf("%11lld", f);
    		cnt++;
			if ( cnt==5 ){
				printf("\n");
				cnt = 0; //清零后,可控制最后一行换行【同例.输出素数】 
			} 
		}
		
		if ( cnt ) printf("\n"); //最后一行不到5个也要换行【同例.输出素数】
	}    
       
    return 0;
}

嵌套循环

穷举问题-搬砖

某工地需要搬运砖块,已知男人一人搬3块,女人一人搬2块,小孩两人搬1块。如果想用n人正好搬n块砖,问有多少种搬法?(输入为正整数)
易错易漏点

  1. 小孩两人搬1块,人数必须为偶;
  2. (审题)n人正好搬n块砖,即人数和为输入的n的条件也要同时满足
int n;
int hasProject = 0;
int cnt = 0; //比较用 
int sum = 0;
	
scanf("%d", &n);

for ( int i=0; i<=n/3; i++ ){ //men的人数,一次3块 
	for ( int j=0; j<=n/2; j++ ){ //women的人数,一次2块
		for ( int k=0; k<=n; k+=2 ){ //child的人数;两人一块,故必须是偶数 
			cnt = 3*i + 2*j + 0.5*k;
			sum = i + j + k;
			if ( cnt==n && sum==n ){
				printf("men = %d, women = %d, child = %d\n", i, j, k);
				hasProject++;
			} 	
		}		
	}
}
	
if ( hasProject==0 ) printf("None");

你可能感兴趣的:(教材配套习题)