零基础学习C++系列课程(六) 持续更新中

目录

项目五 黑客攻击系统-重复验证

第 0 节: 需求分析、项目实现

第 1 节 “愚公移山”之 while 循环

第 2 节 "后羿射日"之 for 循环

第 3 节 项目精讲-"不服就干-直接干"之 do-while 循环

第 4 节 项目需求、项目实现

第 5 节 循环中的特殊控制:continue 与 break

第 6 节 代码世界中的传送阵:goto 语句

第 7 节 “甜蜜的谎言”之循环嵌套

第 8 节 常见错误总结

第 9 节 英语不是障碍:计算机英语加油站

第 10 节 编程思维修炼

第 11 节 职场修炼:程序员到底能干多久

第 12 节 逼格提升:github-使用项目创建代码仓库

第 13 节 项目拓展 1-循环的经典应用:暴力破解密码

第 14 节 项目拓展 2-宅男福利:控制台上跳极乐净土(动画版)

第 15 节 项目练习-循环控制强化训练

循环练习第 1 关

循环练习第 2 关

循环练习第 3 关

循环练习第 4 关

循环练习第 5 关

循环练习第 6 关

循环练习第 7 关

循环练习第 8 关

循环练习第 9 关

循环练习第 10 关

循环练习第 11 关

循环练习第 12 关

循环练习第 13 关


项目五 黑客攻击系统-重复验证

为看书困难的小伙伴推荐视频教程:百度网盘 提取码:r59a

第 0 节: 需求分析、项目实现

项目实现:

#include <iostream>
#include <Windows.h>
#include <string>

using namespace std;

int main(void) {
     string name;
     string pwd;

     while (1) {
           system("cls");

           std::cout << "请输入账号:";
           std::cin >> name;

           std::cout << "请输入密码:";
           std::cin >> pwd;

           if (name == "54hk" && pwd == "123456") {
                break;
           } else {
                system("pause");
                cout << "用户名或密码错误!" << endl;
           }
     }

     system("cls");
     std::cout << "1.网站 404 攻击" << std::endl;
     std::cout << "2.网站篡改攻击" << std::endl;
     std::cout << "3.网站攻击记录" << std::endl;
     std::cout << "4.DNS 攻击" << std::endl;
     std::cout << "5.服务器重启攻击" << std::endl;

     system("pause");
     return 0;
}

第 1 节 “愚公移山”之 while 循环

使用场合:

当需要反复执行某些“过程”时,就可以使用 while 循环。

移山,移到什么时候?

只要山还在,就一直挖!

while (门前的山还在) {

         一直挖

}

使用方法

while (条件) {

    语句 1

    语句 2

    .......

}

强烈建议,无论循环体内有几条语句,都使用{}

break 的作用

跳出所在的循环。

死循环

有些场合(比如,游戏引擎的主循环, 就是一个死循环)

更多场合,需要避免死循环。

demo:

1+2+3+4+...100

#include <iostream>
#include <Windows.h>
#include <string>

using namespace std;

int main(void) {
     int i = 1;
     int s = 0;

     while (i<=100) {
           s += i;
           i++;
     }

     cout << "s=" << s << endl;

     system("pause");
     return 0;
}

流程图

第 2 节 "后羿射日"之 for 循环

从功能上,for 循环和 while 循环是完全等效的!

使用场合

在循环次数已经确定的情况下,使用 for 循环更方便!

射掉 9 个太阳即可。

使用方法

for (表达式 1; 表达式 2;表达式 3){

      循环体

}

说明:

表达式 1: 为循环做准备

表达式 2: 循环条件

表达式 3: 改变循环计数

注意:

表达式 1、表达式 2、表达式 3, 这 3 个表达式的任意一个或多个,都可以省略!

但是其中的“;”不可以省略!

for (; ; ) {

     循环体

}

相当于:

while (1) {

    循环体

}

for 循环的表达式 1

在 C89 标准中,表达式 1 不能定义变量

在 C99 标准和 C++中,表达式 1 可以定义变量

表达式 1 中定义的变量,仅在 for 循环中有效。

流程图

for (表达式 1; 表达式 2;表达式 3){

      循环语句

​for 循环的次数控制:

for (int i=0; i<10; i++) { ... } //常用方式

for (int i=1; i<=10; i++) { ... } //较少使用

使用 for 循环实现“后裔射日”

#include <iostream>
#include <Windows.h>
#include <string>

using namespace std;

//后羿射日
int main(void) {
     for (int i=1; i<=9; i++) {
            cout << "射第" << i << "个太阳" << endl;
     }

     system("pause");
     return 0;
}

for 和 while 的选择

1)当已经确定了循环次数时,建议使用 for

2)其他情况,可以使用 for ,也可以使用 while, 建议使用 while

使用 for 循环实现 1+2+3+...100 = ?

#include <iostream>
#include <Windows.h>
#include <string>

using namespace std;

int main(void) {
     int s = 0;

     //1 + 2 + 3 + ... 100
     for (int i=1; i<=100; i++) {
             s += i;
     }

     cout << s << endl;

     system("pause");
     return 0;
}

第 3 节 项目精讲-"不服就干-直接干"之 do-while 循环

使用场合:

先执行一次循环体,然后再判断条件,以判定是否继续下一轮循环!

即:至少执行一次循环体!

使用方法

do {

    循环体

} while (条件)

使用 do-while 计算 1+2+3+...100

#include <iostream>
#include <Windows.h>
#include <string>

using namespace std;

int main(void) {
    int s = 0;
    int i = 1;

    do {
       s += i;
       i++;
    } while(i<=100);

    cout << s << endl;

    system("pause");
    return 0;
}

特殊用法:【在特殊的宏定义中使用】

do {

    // 循环体

} while(0);

第 4 节 项目需求、项目实现

需求分析:

不能重复输入账号和密码.

项目实现:

#include <iostream>
#include <Windows.h>
#include <string>

using namespace std;

int main(void) {
    string name;
    string pwd;

    while (1) {
        std::cout << "请输入账号:";
        std::cin >> name;

        std::cout << "请输入密码:";
        std::cin >> pwd;

        if (name == "54hk" && pwd == "123456") {
             break;
        } else {
             cout << "用户名或密码错误!" << endl;
        }
    }

    std::cout << "1.网站 404 攻击" << std::endl;
    std::cout << "2.网站篡改攻击" << std::endl;
    std::cout << "3.网站攻击记录" << std::endl;
    std::cout << "4.DNS 攻击" << std::endl;
    std::cout << "5.服务器重启攻击" << std::endl;

    system("pause");
    return 0;
}

第 5 节 循环中的特殊控制:continue 与 break

break

结束本层循环。

continue

结束本次循环,进入一次循环

for 语句中的 continue

​while 语句中的 continue

demo:

#include <iostream>
#include <Windows.h>
#include <string>

using namespace std;

int main(void) {
    string ret;

    for (int i=0; i<3; i++) {
          cout << "开始第" << i+1 << "次相亲..." << endl;
          cout << "你喜欢打王者吗?" << endl;
          cin >> ret;
   
          if (ret != "yes") {
                 continue;
          }

          cout << "加个微信吧..." << endl;
    }

    system("pause");
    return 0;
}

第 6 节 代码世界中的传送阵:goto 语句

传送阵

demo:

#include <iostream>
#include <Windows.h>
#include <string>

using namespace std;

int main(void) {
     string ret;

     for (int i=0; i<3; i++) {
           cout << "开始第" << i+1 << "次相亲..." << endl;
           cout << "你喜欢打王者吗?" << endl;
           cin >> ret;

           if (ret != "yes") {
                 continue;
           }

           cout << "加个微信吧..." << endl;

           cout << "我中意你, 你中意我吗?" << endl;
           cin >> ret;
           if (ret == "yes") {
                 goto happy;
           }
    }

    system("pause");
    return 0;
happy:
    cout << "开启浪漫之旅..." << endl;
    
    system("pause");
    return 0;
}

第 7 节 “甜蜜的谎言”之循环嵌套

要点:

把内层的循环,看成一个完整的“大语句”

demo:

#include <iostream>
#include <Windows.h>
#include <string>

using namespace std;

// 一天想我几次?
// 24 小时,每秒一次
int main(void) {
     int count = 0;

     for (int i=0; i < 24; i++) {
           for (int j=0; j<60; j++) {
                 for (int k=0; k<60; k++) {
                       count++;
                       cout << i << ":" << j << ":" << k
                            << " 想你第" << count << "次" << endl;
                       Sleep(1000);
                }
          }
    }

    cout << "一天想你" << count << "次" << endl;

    system("pause");
    return 0;
}

第 8 节 常见错误总结

1. 循环体之前加分号

2. 循环结束后,循环计数变量的值

第 9 节 英语不是障碍:计算机英语加油站

while

当...时候,用于 while 循环

for

用于for循环

break

破裂
跳出所在的那重循环

continue

继续 -> 调到

success

成功

fail

失败

error

错误

commit

提交

push

create

创建

clone

克隆,复制

第 10 节 编程思维修炼

效果分享:

分析:

玫瑰曲线:

x = cos(t) * a * sin(nt) //t 表示角度

y = sin(t) * a * sin(nt)

a 可以取一个值,例如 150

x = cos(t) * 150 * sin(nt) //t 表示角度

y = sin(t) * 150 * sin(nt)

当 n 是奇数正整数时,玫瑰曲线有 n 个花瓣,t 的范围是 0 到 180 度

当 n 是偶数正整数时,玫瑰曲线有 2n 个花瓣,t 的范围是 0 到 360 度

解决方案:

使用循环,绘制 0 到 180 度或 360 度的曲线。

添加画笔模块:

​每个角色,都有一个隐藏的画笔

当这个画笔处于“抬笔”状态时, 角色移动时,就不会画出笔迹

当这个画笔处于“落笔”状态时, 角色移动时,就会画出笔迹

注意:调整画笔的中心点。

第 11 节 职场修炼:程序员到底能干多久

现状:

很多程序员,过了 30 岁,纷纷转行。

原因:

1)薪资过万后,很难进一步提升

2)可替代性高,在新人面前,没有绝对优势。

3)结婚成家后,在 996 工作环境下,难以承受。

解决方案:

1)选择合适的方向

前端开发,PHP 开发等方向,技术含量低,可替代性高。

2)掌握企业的核心业务,核心技术,向技术管理方向发展

3)掌握外包开发核心技能,逐步拓展外包人脉。

第 12 节 逼格提升:github-使用项目创建代码仓库

已经在本地创建项目,然后再发布到 github。

第 13 节 项目拓展 1-循环的经典应用:暴力破解密码

client.cpp

#include <iostream>
#include <Windows.h>
#include <string>

using namespace std;

int main (void){
      string pwd;

      while (1) {
            cout << "Please input your password: ";
            cin >> pwd;

           if (pwd == "000123") {
                 break;
           } else {
                 cout << "Password error." << endl;
           }
     }

     cout << "login success" << endl;
     cout << "1. 注册" << endl;
     cout << "2. 管理" << endl;
     cout << "3. 查询" << endl;
     cout << "4. 删除" << endl;

    system("pause");
    return 0;
}

crack.cpp

#include <iostream>

using namespace std;

int main(void)
{
    char pwd[7];
    char dict[64]; // 10+26+26+1 = 63;
    char tmp[32];
    int index = 0;

    for (int i = 0; i < 10; i++)
    {
        dict[index++] = '0' + i;
    }
    /*
    for (int i=0; i<26; i++) {
    dict[index++] = 'a' + i;
    }

    for (int i=0; i<26; i++) {
    dict[index++] = 'A' + i;
    }

    dict[index++] = '_';
    */

    dict[index] = '\0';
    int n = index; // 字符个数

    for (int p1 = 0; p1 < n; p1++)
    {
        for (int p2 = 0; p2 < n; p2++)
        {
            for (int p3 = 0; p3 < n; p3++)
            {
                for (int p4 = 0; p4 < n; p4++)
                {
                    for (int p5 = 0; p5 < n; p5++)
                    {
                        for (int p6 = 0; p6 < n; p6++)
                        {
                            tmp[0] = dict[p1];
                            tmp[1] = dict[p2];
                            tmp[2] = dict[p3];
                            tmp[3] = dict[p4];
                            tmp[4] = dict[p5];
                            tmp[5] = dict[p6];
                            tmp[6] = '\0';
                            cout << tmp << endl;
                        }
                    }
                }
            }
        }
    }
    return 0;
}

在控制台:

crack.exe | client.exe

第 14 节 项目拓展 2-宅男福利:控制台上跳极乐净土(动画版)

_T( ) 补充说明:

如果项目使用的是字符集是”多字节字符集”

那么在使用 easyx 的相关接口时, 就不需要使用 _T( )

如果项目使用的是字符集是”Unicode 字符集”或其他字符集

那么在使用 easyx 的相关接口时, 就要使用 _T( )

不论什么字符集, 都使用_T(), 则都可以适应.

_T( )是一个特殊的”宏”, 其中的参数是常量时,才有效果.

如果参数是变量, 则可能会无效.

所以, 当加载的文件名是变量时, 有两个方法:

方法 1) 把字符集改为 使用”多字节字符集”

方法 2) 使用自定义的函数, 进行字符编码的转换

Demo

#include <iostream>
#include <graphics.h>
#include <Windows.h>
#include <string>
#include <string.h>
#include <MMSystem.h>             // 播放音乐需要的头文件
#pragma comment(lib, "winmm.lib") //告诉编译器, 加载 winmm.lib 库文件

using namespace std;

#define COUNT 148

int main(void)
{
    char fileName[128];

    std::cout << "正在加载..." << std::endl;

    //预加载
    IMAGE images[COUNT];
    for (int i = 1; i <= COUNT; i++)
    {
        sprintf(fileName, "D:\\tmp\\images2\\_%04d_图层-%d.jpg", COUNT - i, i);
        loadimage(&images[i - 1], fileName);
    }

    initgraph(800, 450);

    // 重复播放"极乐净土.mp3"
    mciSendString(_T("play 极乐净土.mp3 repeat"), 0, 0, 0);

    while (1)
    {
        for (int i = 0; i < COUNT; i++)
        {
            putimage(0, 0, &images[i - 1]);
            Sleep(75);
        }
    }

    system("pause");
    closegraph();
    return 0;
}

第 15 节 项目练习-循环控制强化训练

循环练习第 1 关

难度: 1

行数和每行*的个数,由用户输入。

参考:

#include <iostream>
#include <Windows.h>
using namespace std;
int main(void)
{
    int rows;
    int cols;
    cout << "请输入行数: ";
    cin >> rows;
    cout << "请输入每行需要打印的列数: ";
    cin >> cols;
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        {
            cout << "*";
        }
        cout << endl;
    }
    system("pause");
    return 0;
}

循环练习第 2 关

难度 1.5

dmeo

#include <iostream>
#include <Windows.h>
using namespace std;
int main(void)
{
    int rows;
    cout << "请输入行数: ";
    cin >> rows;
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < i + 1; j++)
        {
            cout << "*";
        }
        cout << endl;
    }
    system("pause");
    return 0;
}

循环练习第 3 关

难度: 1.5

Demo

#include <iostream>
#include <Windows.h>
using namespace std;
int main(void)
{
    int rows;
    cout << "请输入行数: ";
    cin >> rows;
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < rows - i; j++)
        {
            cout << "*";
        }
        cout << endl;
    }
    system("pause");
    return 0;
}

循环练习第 4 关

难度系数 2.0

*的个数

空格的个数

第1行

1

7(n-1)

第2行

3

6(n-2)

第3行

5

3

第4行

7

2

第i行

2*i-1

n-i

第n行

2*n-1

​Demo

#include <iostream>
#include <Windows.h>
using namespace std;
int main(void)
{
    int rows;
    cout << "请输入行数: ";
    cin >> rows;
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < rows - i - 1; j++)
        {
            cout << " ";
        }
        for (int j = 0; j < 2 * i + 1; j++)
        {
            cout << "*";
        }
        cout << endl;
    }
    system("pause");
    return 0;
}

循环练习第 5 关

难度:2.5

打印乘法口诀表

Demo

#include <iostream>
#include <Windows.h>
#include <iomanip>
using namespace std;
int main(void)
{
    for (int i = 1; i <= 9; i++)
    {
        for (int j = 1; j <= i; j++)
        {
            // setw(2) 是下一个数据的输出宽度为 2,
            //仅对下一个数据的输出有效, 即只有一次效果
            //  std::left 使数据在自己规定的宽度内左对齐,默认是右对齐, 持续有效
            cout << i << "*" << j << "=";
            if (j == 1)
            {
                cout << setw(1) << std::left << i * j << " ";
            }
            else
            {
                cout << setw(2) << std::left << i * j << " ";
            }
        }
        cout << endl;
    }
    system("pause");
    return 0;
}

循环练习第 6 关

输出所有水仙花数

水仙花数: 3 位数字, 各位的立方之和,等于这个数本身.

说明: 严格的说只有 3 位的整数, 才可能是水仙花数.

Demo

#include <iostream>
#include <Windows.h>
#include <iomanip>
using namespace std;
int main(void)
{
    int a, b, c;
    for (int i = 100; i <= 999; i++)
    {
        a = i % 10;
        b = (i / 10) % 10;
        c = i / 100;
        if (a * a * a + b * b * b + c * c * c == i)
        {
            cout << i << endl;
        }
    }
    system("pause");
    return 0;
}

循环练习第 7 关

输出指定项的斐波那契数列.

1, 1, 2, 3, 5, 8, 13, 21, ..

难度: 2.5

Demo

#include <iostream>
#include <Windows.h>
#include <iomanip>
using namespace std;
int main(void)
{
    int n = 0;
    long long a = 1;
    long long b = 1;
    long long value;
    cout << "请输入斐波那契数列的个数: ";
    cin >> n;
    if (n <= 0)
    {
        cout << "要求是大于 0 的正数." << endl;
        system("pause");
        return 1;
    }
    if (n == 1)
    {
        cout << "1" << endl;
        system("pause");
        return 0;
    }
    if (n == 2)
    {
        cout << "1 1" << endl;
        system("pause");
        return 0;
    }
    cout << "1 1 ";
    for (int i = 3; i <= n; i++)
    {
        value = a + b;
        // a 和 b 前进一位
        a = b;
        b = value;
        cout << value << " ";
    }
    cout << endl;
    system("pause");
    return 0;
}

循环练习第 8 关

输入一个 10 进制的正整数,把它转换为 2 进制输出。

6

110

Demo

#include <iostream>
#include <Windows.h>
#include <iomanip>
using namespace std;
int main(void)
{
    int ret[32] = {0};
    int n;
    int i;
    cout << "请输入一个正整数: ";
    cin >> n;
    if (n < 0)
    {
        cout << "需要输入一个正整数!" << endl;
        system("pause");
        return 1;
    }
    i = 0;
    while (n != 0)
    {
        ret[i] = n % 2;
        n = n / 2;
        i++;
    }
    for (i--; i >= 0; i--)
    {
        cout << ret[i];
    }
    system("pause");
    return 0;
}

循环练习第 9 关

输入一个 2 进制正数,把它转换为 10 进制输出。

#include <iostream>
#include <Windows.h>
#include <string>
using namespace std;
int main(void)
{
    string str;
    int s = 0;
    int p = 1;
    cout << "请输入一个二进制数: ";
    cin >> str;
    for (int i = str.length() - 1; i >= 0; i--)
    {
        int x = str[i] - '0';
        s += x * p;
        p *= 2;
    }
    cout << "s=" << s << endl;
    system("pause");
    return 0;
}

循环练习第 10 关

输入一个字符串,然后把这个字符串逆转输出

123456789

987654321

#include <iostream>
#include <Windows.h>
#include <string>
using namespace std;
int main(void)
{
    string str;
    int i;
    int j;
    char tmp;
    cout << "请输入一个字符串: " << endl;
    cin >> str;
    i = 0;
    j = str.length() - 1;
    while (i < j)
    {
        tmp = str[i];
        str[i] = str[j];
        str[j] = tmp;
        i++;
        j--;
    }
    cout << str << endl;
    system("pause");
    return 0;
}

循环练习第 11 关

经典算法题: 千鸡百钱.

1000 块钱, 要买 100 只鸡.

公鸡每只 50 块

母鸡每只 30 块

小鸡每 3 只 10 块

问:一共有多少种买法?

难度 3.0

Demo

#include <iostream>
#include <Windows.h>
#include <string>
using namespace std;
/*
1000 块钱, 要买 100 只鸡.
公鸡每只 50 块
母鸡每只 30 块
小鸡每 3 只 10 块
*/
int main(void)
{
    int cock_max = 1000 / 50;
    int hen_max = 1000 / 30;
    for (int i = 1; i <= cock_max; i++)
    {
        for (int j = 1; j <= hen_max; j++)
        {
            int k = 100 - i - j; //小鸡的个数
            if (k % 3 == 0 && i * 50 + j * 30 + k / 3 * 10 == 1000)
            {
                cout << "公鸡:" << i << " 母鸡:" << j << " 小鸡:" << k << endl;
            }
        }
    }
    system("pause");
    return 0;
}

循环练习第 12 关

输入一个英文字符串(一句话),统计输入的单词个数.

难度 2.8

I love you!

demo

#include <iostream>
#include <Windows.h>
#include <string>
using namespace std;
int main(void)
{
    char line[256]; //'\0'就是 0
    int i = 0;
    // 访问字符串(字符数组)的下标
    int count = 0; //单词计数
    cout << "请输入一句话:";
    gets_s(line, sizeof(line));
    // 跳过前面的连续空格
    while (line[i] == ' ')
        i++;
    while (line[i])
    { // while(line[i] != '\0')
        // 跳过连续的多个非空格组合(就是单词!)
        while (line[i] && line[i] != ' ')
            i++;
        while (line[i] == ' ')
            i++;
        count++;
        '\0' 就是 0
    }
    cout << "一共有" << count << "个单词" << endl;
    system("pause");
    return 0;
}

循环练习第 13 关

输入一句话,然后把这个字符串以单词为单位,逆转输出。(腾讯笔试题)

比如将“Alice call Jack”转换为“Jack call Alice”,

实现速度最快,移动最少。

难度: 3.0

为看书困难的小伙伴推荐视频教程:百度网盘 提取码:r59a

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乐成书院

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值