c语言之基础循环练习

这篇博客通过一系列循环基础题目,包括杨辉三角、九九乘法表、斐波那契数列和不同排序算法,深入探讨了C语言中循环的应用。通过对每个题目详细的问题分析和解题思路,帮助读者掌握如何运用循环解决实际问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前面我们大概的已经学习过很多关于循环的知识,这一篇博客我们重点引入一些习题进行分析,涉及到循环的东西,无非就是将变量之间的关系和规律找到,这一解我们就将要仔细的分析每一个题目具体怎么去寻找这种规律。

第一题

打印杨辉三角十行 如下:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1

这就是我们的输出目的

问题分析

方法一:首先我们观察到这个样子的一个三角结构,好像可以把它放到一个二维数组当中,那些不需要打印的数字,我们都可以将其初始化为0。那么,我们就可以观察到这样一个现象,除了每一行的第一个数字以外,其余的数字均可以这样表示。
a[i][j] = a[i-1][j-1] + a[i-1][j];
而每一行的第一个数据我们都可以使其初始化为1。
最终我们三角化打印这个二维数据即可
i来控制第几行
j来控制每行打印多少个数据。
那么i的取值范围应该是[0,len),j的取值范围应该是[0,i]。

#include<iostream>
using namespace std;
int main(){
	int a[10][10] = {0};
	for (int i = 0; i < 10; ++i){
		for (int j = 0 ; j <= i; ++j){
			if(j == 0){
				a[i][j] = 1;
			}else{
				a[i][j] = a[i-1][j-1] + a[i-1][j];
			}
		}
	}

	for(int i = 0 ; i < 10; ++i){
		for(int j = 0; j <= i ++j){
			cout<<a[i][j]<<"\t"
		}
		cout<<endl;
	}
	return 0;
}

方法二:我们同样可以这样思考这个问题,通过观察我们很容易看出来,如果想要打印第十行数据的时候,一共需打印十个值,那么我们就可以一开始定义一个长度为10的数组,第一行,打印这个数组的一个元素,第二行打印两个以此类推。
接下来我们观察数组中元素的特点。
{1, 2, 1}---->{1, 3, 3, 1}。
假设i表示第i行的打印,那么我们可以很明显的看出来,每次首先给数组当中新添加的a[i]元素的值就是1,并且除了第0号元素和第i号元素以外,其他元素均满足这样的关系:
a[i] += a[i-1];
所以如果用j的值来实现每一行具体的操作时候,j的取值范围应该是从i-1一直到1。
这里我们为什么不说是从1到i-1呢,仔细思考这样一个问题,当我们把i的值覆盖以后,当我们计算i+1的值时候,用到的i位置的值还是原来的值吗?这也就是我们这样设计的原因,最后把整个数组打印即可。

#include<iostream>
using namespace std;

int main(){
	int a[10];
	for (int i = 0; i < 10, ++i){
		a[i] = 1;
		for (int j = i - 1; j > 0; --j){
			a[j] += a[j-1]; 
		}
		for (int k = 0 ; k <= i; ++k){
			cout<<a[k]<<"\t";		
			}
		cout<<endl;
	}
	return 0;
}

题目二

打印九九乘法表,打印格式如下:
1 * 1 = 1
1 * 2 = 2 2 * 2 = 4
1 * 3 = 3 2 * 3 = 6

题目分析

观察乘法表,我们可以很明显看到,每个算式都是由三个数字构成的,i,j和result。每一行当中的i的值都是不变的,并且i的取值范围是[1, 9]。而我们可以很明显的看出来,j的取值范围应该是[1, i]。所以这个题目我们可以很快的给出如下一种解法:

#include<iostream>
using namespace std;

int main(){
	for(int i = 1; i < 10; ++i){
		for (int j = 1; j <+ i; ++j){
			cout<<j<<" * "<<i<<" = "<<j*i<<"\t";
		}
		cout<<endl;
	}
	return 0;
}

题目三

打印100位斐波纳契数列,如下:
1, 1, 2, 3 ,5 ,8, …

题目分析

首先我们观察这个数列,前面两位都是固定的数字1,从第三位开始,每个数字都是前面两位之和,题目要求打印一百位的数列,所以我们很自然而然想到了定义的i的取值范围应该是[2 ,100]。
代码如下:

#include<iostream>
using namespace std;
int main(){
	int arr[100] = {1, 1};
	cout<<a[0]<<"\t";
	cout<<a[1]<<"\t";
	for (int i = 2; i < 101; ++i) {
		arr[i] = arr[i-1] + arr[i-2];
		cout<<arr[i]<< "\t";
	}
	return 0;
}

题目三

打印下列格式的一组数字
1 2 3 4 5 6
12 23 34 45 56
123 234 345 456
1234 2345 3456
12345 23456
123456

题目分析

我们这样分析这个题目,首先观察这6行数,第一行每个都是1位数,到了第6行是6位数。我们抽取其中的一行进行具体的分析

123 234 345。假设i表示每个数字的首位,j表示每个数字的末尾,s表示这是第几行。s取值范围是[1, 6]
那么我们可以明显的得到这样的结论,i的值是从1开始到n - s + 1;
而j的取值范围应该是从i到i+s-1。
所以代码实现如下:

#include<iostream>
using namespace std;

int main(){
	for (int s = 1; s <= 6; s++){
		for(int i = 1; i <= n-s+1; ++i){
			for(int j = i; j <= i+s-1; ++j){
				cout<<j;	
			}
			cout<<"\t"
		}
		cout<<endl;
	}
	return 0;
}

排序基础之冒泡排序

写出冒泡排序的改良版本,要求当排序完成后,就停止排序而不是做无用功继续遍历,并且要求左右一起进行排序,加快排序进度。

题目分析

题目需要的是冒泡排序的升级版,所以首先我们先写出来普通的冒泡再进行分析

#include<iostream>
using namespace std;
// 改良冒泡排序


void PrintArray(int *arr, int len){
  for(int i = 0; i<len;++i){
    cout<<*(arr+i)<<" ";
  }
  cout<<endl;
}


void bubble_sort(int *arr ,int len){
  for(int i = 1; i < len; ++i){
    for (int j = 0;j < len-i;++j)
      if(*(arr+j) > *(arr + j+ 1)) {
        int tmp = *(arr +j);
        *(arr+j) = *(arr + j + 1);
        *(arr +j + 1) = tmp;
      }
  }
}


int main(){

  int arr[] = {45, 56, 12, 34, 89, 90, 100, 23, 56, 78};
  int n = sizeof(arr) /sizeof(int);
  PrintArray(arr, n);
  bubble_sort(arr, n);
  PrintArray(arr, n);

  return 0; 
}

分析代码

题目要求我们改良这个冒泡排序,首先我们考虑这样的一个问题,那就是如何让这个冒泡排序一旦排序完成就不会继续做无用功了。我们需要这样思考这个问题,当排序完成后,继续执行代码,我们的程序会有什么特点,答案是显而易见的,那就是值不会发生交换了,所以从这一点入手,我们很轻松就找到了方法,我们可以给交换时候加一个标记,一旦不再调用,那么就意味着排序完成了。
接着是第二个问题,左右一起排序,那么首先考虑一共要排序len/2次的,并且j的值应该不再从0开始了,应该是从i开始,一直到len-1-i,同时j的值应该是len-1-i,一直到i。
所以代码如下

/*===============================================================
*   Copyright (C) 2019 All rights reserved.
*   
*   文件名称:08-冒泡排序改良版.cpp
*   创 建 者:Ma Junjie
*   创建日期:2019年07月03日
*   描    述:
*
*   更新日志:
*
================================================================*/
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<time.h>
using namespace std;

void PrintArray(int *arr, int len){
    for (int i = 0; i < len; ++i){
        cout<<arr[i]<<" ";
    }
    cout<<endl;
}

void BubbleSort(int *arr, int len){
    for (int i = 0; i < len/2; ++i){
        bool tag = true;
        for(int j = i,k = len-1-i; j < len-i-1, k>i; ++j,--k){
            if(arr[j] > arr[j+1]){
                tag = false;
                int temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
            if(arr[k] < arr[k-1]){
                tag = false;
                int temp = arr[k];
                arr[k] = arr[k-1];
                arr[k-1] = temp;
            }
        }
        if(tag){
            break;
        }
    }
}

void InitArray(int *arr, int len){
    srand(time(NULL));
    for (int i = 0; i < len; i++){
        arr[i] = random()%100;
    }
}

int main()
{
    const int len = 30;
    int arr[len]; 
    InitArray(arr, len);
    PrintArray(arr, len);
    BubbleSort(arr, len);
    PrintArray(arr, len);
    return 0;
}

排序基础之直接选择排序

编写代码完成直接选择排序,直接选择排序算法思路如下:
从第一个数开始,后面的每个数都开始和第一个数进行比较,那么我们可以很容易就得到,一个最小值,放到第一个位置。一次类推,直到排序完成。

根据算法思路可以知道,i的取值范围应该是从[0, len-1)。j的取值范围应该是[i+1, len)。并且每次都比较i和j的值。
所以代码如下:

#include<iostream>
using namespace std;


void swap(int *a, int *b){
    int temp = *a;
    *a = *b;
    *b = temp;
}

void PrintArray(int *arr, int len){
    for(int i = 0; i < len; ++i){
        cout<<arr[i]<<" ";
    }
    cout<<endl;
}

void SelectSorted(int *arr, int len){
  for(int i = 0; i< len; ++i){
    int index = i;
    for (int j = i+1; j < len; ++j){
      if(arr[index] > arr[j]){
          index = j;
      }
    }
    if (i != index) swap(&arr[i],&arr[index]);
  }
}

int main(){
   int arr[] = {9, 5,3, 4,8, 6,3, 8, 6,1,2}; 
   int len = sizeof(arr) / sizeof(int);
   SelectSorted(arr, len);
   PrintArray(arr, len);
  return 0;
}

排序基础之插入排序

编写代码实现插入排序,插入排序算法思路如下:从第一个数开始,有序数列逐渐增加1个元素,并且每次增加完毕以后都使其有序。直到有序数列增加到最后一个数列,完成排序。
根据算法设计:
首先如果后面一个数小于前面的话,说明新的元素加入以后整体变得无序了,所以从这个元素开始向前比较,直到找到合适的位置插入。
代码实现如下:

/*===============================================================
*   Copyright (C) 2019 All rights reserved.
*   
*   文件名称:07-插入排序.cpp
*   创 建 者:Ma Junjie
*   创建日期:2019年07月03日
*   描    述:
*
*   更新日志:
*
================================================================*/
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<time.h>
using namespace std;

void InitArray(int *arr, int len){
    srand(time(NULL));
    for(int i = 0; i < len; ++i){
        arr[i] = random()%100;
    }
}

void PrintArray(int *arr, int len){
    for (int i = 0; i < len; ++i){
        cout<<arr[i]<<" ";
    }
    cout<<endl;
}

void InsertSort(int *arr, int len) {
    for (int i = 0; i < len; ++i) {
        if(arr[i] < arr[i-1]){
            int j = i - 1;
            int temp = arr[i];
            do{
                arr[j+1] = arr[j];
                --j;
            }while(j >= 0 && arr[j] > temp);
            arr[j+1] = temp;
        }
    }
}

int main()
{
    const int len = 20;
    int arr[len];
    InitArray(arr, len);
    PrintArray(arr, len);
    InsertSort(arr, len);
    PrintArray(arr, len);
    cout<<endl;
    return 0;
}
1. 请写1个支付宝接龙红包程序. 随机产生1-100的随机数,作为红包金额. 让用户不断的去猜,直到猜正确为止.最后发给用户的红包金额是 红包金额/猜得次数. 2. 循环录入5个人的年龄并计算平均年龄,如果录入的数据出现负数或大于100的数,立即停止输入并报错. 3. 实现要求用户一直输入QQ号码和密码,只要不是123456、888888就一直提示要求重新输入,如果正确则提登录成功. 4. 1-100之间不能够被7整除的数的和. 5. 求1-200之间的所有的整数的累加和 6. 求1-100之间6的倍数的个数 7. 输入班级人数,然后依次输入学员成绩,计算班级学员的平均成绩和总成绩 8. 2006年培养学员80000人,每年增长25%,请问按此增长速度,到哪一年培训学员人数将达到20万人?*** 9. 从键盘输入10个数,求出最大数 10. 1000~ 5000之间有多少整数,其各位数字之和为5,分别是哪些数(例如整数2003的各位数字之和为 2+0+0+3 ,等于5)), 并统计满足条件的整数有多少个。 11. 求1-100中 是7的倍数 的数值之和 12. 求1-1000之间的所有的奇数之和 13.猜数字游戏. 随机产生1个1-100之间的数 让用户猜 当用户输入的数比产生的随机数大 就输出 猜大了 并让用户继续输入新的数.。 当用户输入的比产生的随机数小的时候 就输出 猜小了 并且继续猜 当用户刚好输入的就是这个随机数的时候 提示成功 并显示用户猜了多少次. 14. 老师问学生,这道题你会做了吗? 如果学生答"会了(y)",则可以放学. 如果学生不会做(n),则老师再讲一遍,再问学生是否会做了......直到学生会为止,才可以放学. 直到学生会或老师给他讲了10遍还不会,都要放学 15. 写1个程序. 随机的产生1个2位数的加法运算.让用户输入这个运算的结果 然后判断这个结果是否正确. 来10次. 每个人默认有10分. 产生10个加法运算.操作数的范围在0-100之间. 每产生1个加法运算 就让用户输入结果.判断是否正确. 当回答正确的时候就为用户加1分. 错误的时候就扣1分. 当10道题目回答完毕之后 就显示用户得的分数. ***
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值