八、循环(一)

1、for循环

1)for循环语法

//for循环语法
for(初始化表达式;运行条件表达式;变动表达式)
{
    循环内容;
}

//示例
for(int i=0;i<10;i++)
{
    std::cout<<i<<std::endl;
}
std::cout<<"循环结束";

①打印9-1

//打印9-1
#include <iostream>

int main()
{
    for (int i = 9; i > 0; i--)
    {
        std::cout << i << std::endl;
    }
}

②打印所有大写字母

//打印所有大写字母
#include <iostream>

int main()
{
    for (char i = 65; i <=90; i++)  //A的ascii码为65
    {
        std::cout << i << std::endl;
    }
}

③打印所有大写字母,但是每行只有五个字母

//打印所有大写字母
#include <iostream>

int main()
{
    int count{ 0 };
    for (char i = 65; i <=90; i++)  //A的ascii码为65
    {
       
        count++;
        if (count > 5)
        {
            std::cout << std::endl;
            count = 1;
        }
        std::cout << i;
    }
}

法二:

//打印所有大写字母
#include <iostream>

int main()
{
	for (char a{ 65 }; a < 91; a++)
	{
		if ((!((a - 65) % 5)) && (a > 65)) //取余数,如果余数=0,则进行换行
		{
			std::cout << std::endl;
		}
		std::cout << a;
	}
}

④要求用户输入一个大写字母,打印从这个字母后的所有大写字母,比如用户输入C,那么屏蔽上打印DEFG..Z

//输入一个大写字母,打印从这个字母后的所有大写字母
#include <iostream>

int main()
{
	char userIn;
	std::cout << "请输入一个大写字母:";
	std::cin >> userIn;
	for (char a = userIn + 1; a < 91; a++)
	{
		if (!((a - userIn - 1) % 5) && (a > (userIn + 1)))
		{
			std::cout << std::endl;
		}
		std::cout << a;
	}
}

2、for循环之网银证书密码攻击

需求:设计一个系统来模拟网银密码被攻击的场景,用户输入一个6位数字密码,然后我们破解它的密码并显示出来

#include <iostream>
#include <conio.h>
int main()
{
	int password, repassword;
	std::cout << "请设置一个6位数字的密码:";
	std::cin >> password;
	std::cout << "请再次输入你的密码:";
	std::cin >> repassword;
lset:
	if (password == repassword)
	{
		system("cls");
		//破解程序
		std::cout << "破解程序启动";
		for (int hackpass = 0; hackpass < 1000000; hackpass++)
		{
			if (hackpass == password)
			{
				std::cout << "你的密码为:" << hackpass << std::endl;
				goto lexit;
			}
		}
	}
	else
	{
		goto lset;
	}
lexit:
	std::cout << "密码破解成功,程序退出!";
}

3、for循环补充知识

1)循环的嵌套

①打印九九乘法表,输出结果如下

#include <iostream>
#include <iomanip>

int main()
{
	std::cout << std::setfill('0');
	for (int y{}; y < 10; y++)
	{
		for (int x{}; x < 10; x++)
		{
			std::cout << std::setw(3)<<x * y << " ";
		}
		std::cout << std::endl;
		
	}
}

2)跳出for循环的三种方式

能力 语句 说明
1 continue 跳出本次循环,进入下一次循环
2 break 跳出循环
3 goto 跳出嵌套循环,即跳出所有循环

①continue:跳出本次循环

//continue:跳出本次循环
#include <iostream>
#include <iomanip>

int main()
{
	std::cout << std::setfill('0');
	for (int y{}; y < 10; y++)
	{
		if (y == 0) continue;
		for (int x{}; x < 10; x++)
		{
			if (x == 0) continue;
			std::cout << std::setw(3) << x * y << " ";
		}
		std::cout << std::endl;

	}
}

②break:跳出循环

//break:跳出循环
#include <iostream>
#include <iomanip>

int main()
{
	std::cout << std::setfill('0');
	for (int y{}; y < 10; y++)
	{
		for (int x{}; x < 10; x++)
		{
			if (x == 5) break;
			std::cout << std::setw(3) << x * y << " ";
		}
		std::cout << std::endl;

	}
}

注:break只能跳出本层循环,但是无法跳出上层循环

③goto:可以跳出所有循环

3)for循环的变体

//正常for循环
for(初始化;条件;变动表达式)
{
    
}

//变体一:无初始化,只要前面声明过,for中就不需要初始化
for(;条件;变动表达式)
{
    
}

//变体二:无变动表达式
for(;条件;)       //死循环
{
    
}

//变体三:
for(;;)       //无条件执行,中间是一个条件表达式,即bool值
{
    
}
4、for循环练习
需求:质数是只能被自己和1整除的数,在不对称加密算法中,质数扮演着重要的作用,设计一个程序,找出1000以内的质数

补充知识:数学库cmath提供了计算平方根的函数sqrt。a=sqrt(100);则a=10
//找出1000以内的质数(法一)
#include <iostream>
#include <cmath>

int main()
{
	bool bcase{};  //用于记录
	for (int i = 3; i < 1000; i++)
	{
		bcase = false;
		for (int c = 2; c < i; c++)
		{
			if (i % c == 0) //可以整除说明,不是质数,则跳出循环
			{
				bcase = true;   //只要不是质数,就将bcase设置为true
				break;
			}
		}
		if (!bcase)  std::cout << i << std::endl;   //若bcase为false,说明是质数,就将其输出

	}
}
//找出1000以内的质数(法一代码优化)
#include <iostream>
#include <cmath>

int main()
{
	bool bcase{};  //用于记录
	for (int i = 3; i < 1000; i+=2)  //质数一定是奇数,所有每一次+2,相比法一提高50%运算效率
	{
		bcase = false;
		for (int c = 3; c < i; c+=2)  //因为第一次从3开始,且没有偶数了,所以此处也直接从3开始,并且因为是奇数,所以此处也+2
		{
			if (i % c == 0) 
			{
				bcase = true;   
				break;
			}
		}
		if (!bcase)  std::cout << i << std::endl;   

	}
}
//找出1000以内的质数(法一代码优化)
#include <iostream>
#include <cmath>

int main()
{
	bool bcase{};  //用于记录
	for (int i = 3; i < 1000; i+=2)  //质数一定是奇数,所有每一次+2,相比法一提高50%运算效率
	{
		bcase = false;
		for (int c = 3; c < sqrt(i); c+=2)  //开平方
		{
			if (i % c == 0) 
			{
				bcase = true;   
				break;
			}
		}
		if (!bcase)  std::cout << i << std::endl;   

	}
}

5、for循环练习:政府采购项目

需求:某单位要采购一批办公家具,共有10000元资金,要买100件家具,其中高级桌子每张500元,普通桌子每张300元,椅子三把100元,要求把资金刚好花完,并且所有 家具的数量刚好加起来是100件。请设计一个软件系统来给出采购方案。

//政府采购项目(法一)
#include <iostream>

int main()
{
	for (int a = 0; a <= 100; a++)   //高级桌子
	{
		for (int b = 0; b <= 100; b++)  //普通桌子
		{
			for (int c = 0; c <= 100; c++)  //高级椅子
			{
				if ((a + b + c == 100) && (a * 500 + b * 300 + c * 100 / 3 == 10000))
				{
					std::cout << "高级桌子采购" << a << "张,普通桌子采购" << b << "张,高级椅子采购" << c << "把\n";
				}		

			}
		}
	}
}
//运算次数=100*100*100=1000000次

//政府采购项目(法二)
#include <iostream>

int main()
{
	int acount = 10000 / 500;  //高级桌子最多允许购买数量
	int bcount = 10000 / 300;	//普通桌子最多允许购买数量
	for (int a = 0; a <= acount; a++)   
	{
		for (int b = 0; b <= bcount; b++)  //普通桌子
		{
		
				int c = 100 - a - b;        //椅子购买数量
				if ((c%3==0)&&(a * 500 + b * 300 +c * 100 / 3 == 10000))   //椅子只能一次买3把
				{
					std::cout << "高级桌子采购" << a << "张,普通桌子采购" << b << "张,高级椅子采购" << c << "把\n";

			}
		}
	}
}
//运算次数=20*33=660次
//政府采购项目(法三)
#include <iostream>

int main()
{
	for (int num = 0; num <= 3; num++)
	{
		std::cout << "高级桌子采购" << num*4 << "张,普通桌子采购" << 25-num*7 << "张,高级椅子采购" << 75+3+num << "把\n";
	}
}
//运算次数=3次

法三解析:

a:高级桌子 b:普通桌子 c:高级椅子

0≤a≤20 0≤b≤33

当a和b都取到最大,则20+33+c=100,可知c的最小值为45,即45≤c≤100

a * 500 + b * 300 +c * 100 / 3 == 10000

等式两边同时*3

1500a+900b+100c=30000

等式两边同时/100

得出等式①:15a+9b+c=300

又因为等式②:a+b+c=100

由等式①-等式②得等式③:14a+8b=200

由等式③/等式②得:7a+4b=100,即4b=100-7a,即b=25-7/4a

通过b的取值范围可知:0≤25-7a/4≤33

因b是整数,即25-7a/4是整数,所以a是4的倍数,即a=4num

可得a=4num,b=25-7a/4,即b=25-7a/4 *4num

即b=25-7num

c=100-a-b,即c=100-4um-25+7num,即c=75+3num

综上:

a=4num

b=25-7num

c=75+3num

根据a,b的范围,可得

0≤4num≤20,即0≤4num≤20 ,,即num≤5

0≤25-7num≤33,即-25≤-7num≤7,即25/7≥num,即num≤3

根据c的取值范围,可知

45≤75+3num≤100,即num≤33

所以综上所述:即num≤3

6、for循环练习:麟江湖显示升级经验列表

需求:为游戏麟江湖设计升级所需的经验梯度表,用户按下L键,将为用户打印出我们游戏从1-100级所需的升级经验表、设等级为lv,当前等级需要的经验值为lvlv100。要求输入不分大小写,对齐输出内容。

#include <iostream>
#include <conio.h>
#include <iomanip>

int main()
{
	std::cout << "请输入字母L查看等级所需经验:\n";
	char cIn = _getch();
	if ((cIn == 'l') || (cIn == 'L'))
	{
		for (int lv{1}; lv < 101; lv++)
		{
			std::cout << std::setfill(' ');
			std::cout << "\n等级" << std::setw(3) << lv << "    所需经验" << std::setw(10) << lv * lv * 100 << std::endl;
		}
	}
}