程序设计基础作业03-数组练习

【实验准备】

实验教材:《C++程序设计实验指导》(第二版),孟桂蛾编, 上海交大出版社,2019

IDE: Microsoft Visual Studio Code September 2022 (version 1.71.2)

编译器:MingW-W64-builds 10.0.0 & GCC 12.1.0

操作系统:Windows 11 家庭中文版22H2 22623.870 Beta Preview(64-bit)

【实验题目】

1.打印杨辉三角形

问题描述:由杨辉三角形可以看出每行的数存在如下规律:每行数据的个数和行序相同;每行的第一个数和最后一个数都是 1;中间的数为上一行中前一列的数和后一列的数之和。
请编写程序,用户输入要打印的杨辉三角形的总行数 n,程序打印出总行数为 n 的杨辉三角形。
提示:可以应用循环语句和一个二维数组,并控制输出间距来打印杨辉三角形。

使用一个初始值均为0动态二维数组,其大小由n决定;

为三角形最外层赋值1搭建框架,随后按照公式计算出整个三角形;

最终输出时遇0则不输出,否则输出对应数值;输出间隔通过switch语句根据n的值动态调整。

#include<iostream>
using namespace std;

int main(){
    int input;                                    //输入的预期行数
    int **pascalTriangle;                        //杨辉三角:动态二维数组
    int i,j,k;                                    //计数器
    cout<<"请输入要打印的杨辉三角形的总行数n:";
    cin>>input;
    int line=input;                                //实际行数
    int column=2*input-1;                        //实际列数
    pascalTriangle=new int *[line];                //申请每一行首地址指针

    //为每一行申请空间
    for(i=0;i<line;i++){
        pascalTriangle[i]=new int[column];
    }

    //为杨辉三角所有元素赋初值0
    for(i=0;i<line;i++){
        for(j=0;j<column;j++){
            pascalTriangle[i][j]=0;
        }
    }

    //建立三角型框架:最外层赋值为1
    pascalTriangle[0][input-1]=1;
    j=1;
    for(i=1;i<line;i++){
        pascalTriangle[i][input-1+j]=1;
        pascalTriangle[i][input-1-j]=1;
        j++;
    }

    //计算三角形元素:中间的数为上一行中前一列的数和后一列的数之和
    for(i=1;i<line;i++){
        for(j=1;j<column-1;j++){
            pascalTriangle[i][j]=pascalTriangle[i-1][j-1]+pascalTriangle[i-1][j+1];
        }
    }

    //最终输出:为0不输出,不为0时输出对应值;每一位数字随n的变化调整占位
    switch(line/12){
        case 0:
            for(i=0;i<line;i++){
                for(j=1;j<line-i;j++){
                    printf("  ");
                }
                for(j=0;j<column;j++){
                    if(pascalTriangle[i][j]==0){
                        continue;
                    }
                    else{
                        printf("%-4d",pascalTriangle[i][j]);
                    }            
                }
                cout<<endl;        //完整输出一行后换行
            }
            break;
        case 1:
            for(i=0;i<line;i++){
                for(j=1;j<line-i;j++){
                    printf("    ");
                }
                for(j=0;j<column;j++){
                    if(pascalTriangle[i][j]==0){
                        continue;
                    }
                    else{
                        printf("%-8d",pascalTriangle[i][j]);
                    }            
                }
            cout<<endl;        //完整输出一行后换行
            }
            break;
        default:
            for(i=0;i<line;i++){
                for(j=1;j<line-i;j++){
                    printf("      ");
                }
                for(j=0;j<column;j++){
                    if(pascalTriangle[i][j]==0){
                        continue;
                    }
                    else{
                        printf("%-12d",pascalTriangle[i][j]);
                    }            
                }
            cout<<endl;        //完整输出一行后换行
            }
            break;
    }
    return 0;
}

2.字符串排序

问题描述:输入 5 个不相同的字符串,将它们按照字母序由小到大顺序排列并输出。可以考虑字符数组或string 类型数组保存输入的字符串,然后采用冒泡或选择排序 方法实现排序并输出。 

程序运行示例:

Please input strings: 
China India Korea Japan Canda 
Sorted Strings: 
Canda China India Japan Korea

字符串使用string类储存,排序使用冒泡排序

#include<iostream>
#include<vector>
using namespace std;

const int len=5;                            //字符串个数

int main(){
    int i,j;                                //计数器
    bool flag;                                //记录一次起泡中是否发生过交换
    vector<string> str;                        //字符串容器
    string input;                            //用户输入的字符串
    cout<<"Please input strings:"<<endl;

    //用户输入
    for(i=1;i<=len;i++){
        cin>>input;
        str.push_back(input);
    }
    cout<<endl;

    //冒泡排序
    for(i=1;i<len;i++){
         flag=false;                            //记录重置
        for(j=0;j<len-i;j++){
            if(str[j+1]<str[j]){
                str[j].swap(str[j+1]);        //字符串交换
                flag=true;                    //标记
            }
        }
        if(!flag){
            break;                            //没有发生交换,终止排序
        }
    }

    //最终输出
    cout<<"Sorted Strings:"<<endl;
    for(i=0;i<len;i++){
        cout<<str[i]<<endl;
    }
    return 0;
}

3.判断黑色星期五

问题描述:黑色星期五是指某天既是 13 号又是星期五。13 号在星期五的情况比在其他日子的少吗?为了回答这个问题,编写一个程序,计算每个月的 13 号分别落在周一到周日的次数。给出一个正整数 n (n 不大于400),要求计算从 1900 年 1 月 1 日至 1900+n-1 年 12 月 31 日中 13 号落在周一到周日的次数.(已知 1900 年 1 月 1 日是星期一)

程序运行示例:

20
34 33 35 35 34 36 33

用到函数:int year2startDay(int year) 输入一个1900年及以后的年份,计算其1月1日是星期几;vector<int> dateNum(int date,bool leapYear)

输入日期,将每月的该日期转换为其在一年中的第几天;

(dateNum(tgDate,ifLeapYear(year))[month-1]%7+year2startDay(year)-1)%7通过此公式计算得到星期结果并计数

#include<iostream>
#include<vector>
using namespace std;

vector<int> dateNum(int date,bool leapYear);
bool ifLeapYear(int year);
int year2startDay(int year);

const int tgDate=13;        //需要求的目标日期

int main(){
    int day[7]={0};         //day[n]即星期n
    int n;                    //输入年数
    cout<<"请输入n:";
    cin>>n;

    //计数阶段
    for(int year=1900;year<1900+n;year++){
        for(int month=1;month<=12;month++){
            switch((dateNum(tgDate,ifLeapYear(year))[month-1]%7+year2startDay(year)-1)%7){
                //计算year年month月tgDate日是星期几,表达式结果范围在-1~6之间,对应结果如下:
                case -1: day[6]++; break;  case 0: day[0]++; break;
                case 1: day[1]++; break;   case 2: day[2]++; break;
                case 3: day[3]++; break;   case 4: day[4]++; break;
                case 5: day[5]++; break;   case 6: day[6]++; break;
            }
        }
    }

    //最终输出
    cout<<"MON\tTUE\tWED\tTHU\tFRI\tSAT\tSUN"<<endl;
    for(int i=1;i<=6;i++){
        cout<<day[i]<<"\t";
    }
    cout<<day[0]<<endl;
    return 0;
}

/**
 * @brief 输入日期,将每月的该日期转换为其在一年中的第几天
 * 
 * @param date 输入日期
 * @param leapYear 是否为闰年
 * @return 每月date日所对应的在一年中的第几天,一个长度为12的整型数容器
 */
vector<int> dateNum(int date,bool leapYear){
    vector<int> target;
    int n=date;    
    target.push_back(n);
    for(int i=1;i<12;i++){
        switch(i){
            case 1: n+=31; break; case 11: n+=30; break;
            case 2:
                if(!leapYear)
                    n+=28;
                else
                    n+=29;
                break;
            case 3: n+=31; break; case 4: n+=30; break;
            case 5: n+=31; break; case 6: n+=30; break;
            case 7: n+=31; break; case 8: n+=31; break;
            case 9: n+=30; break; case 10: n+=31; break;
        }
        target.push_back(n);
    }
    return(target);
}

/**
 * @brief 判断某个年份是否为闰年
 * 
 * @param year 输入年份
 * @return true 是闰年
 * @return false 不是闰年
 */
bool ifLeapYear(int year){
    return((year%4==0&&year%100!=0)||(year%400==0));
}

/**
 * @brief 输入一个1900年及以后的年份,计算其1月1日是星期几
 * 
 * @param year 输入年份
 * @return year年的1月1日是星期几
 */
int year2startDay(int year){
    int startDay=1;                    //year年的1月1日是星期几
    for(int i=1901;i<=year;i++){
        if(ifLeapYear(i-1))
            startDay+=2;
        else
            startDay++;
        if(startDay>=7)
            startDay-=7;
    }
    return(startDay);
}

4. 寻找整数矩阵元素的最大值

问题描述:有一个 3×4 的整数矩阵,使用二维整数数组表示,示例如下:
int a[3][4]={{30,25,23,56},{12,2,6,46},{-12,-34,16,28}};
要求编程序输出其中值最大的那个元素的值,以及其所在的行号和列号。

算法如下:先把 a[0][0]的值赋给变量 max,然后通过两层循环、一次遍历整个数组的元素,让每个被访问到元素与 max 进行比较,如果其值大于 max,则将该值保存在 max 中,并记录下该元素的行和列的值,重复这个过程,直到最后一个元素为止。

#include<iostream>
using namespace std;

int main()
{
    int a[3][4]={{30,25,23,56},{12,2,6,46},{-12,-34,16,28}};    //定义数组
    int max=a[0][0];                                            //max大小初始化
    int maxX,maxY;                                                //max坐标初始化
    
    //遍历循环查找max并且记录值和坐标
    for(int i=0;i<3;i++){
        for(int j=0;j<4;j++){
            if(a[i][j]>max){
                max=a[i][j];
                maxX=i;
                maxY=j;
            }
        }
    }

    //最终输出
    printf("max=%d,row=%d,column=%d\n",max,maxX,maxY);
    return 0;
}

5. 寻找整数矩阵元素的多个最大值及其位置

问题描述:上题(第4题)算法在处理有多个最大值的数组时,只能输出遍历时访问的第一个最大值及其位置,例如对于如下数组:
int a[3][4]={{27,12,23,56},{37,2,56,46},{-12,-34,56,8}};
输出如下:
max = 56,row = 0,column = 3
请修改第 4 题中的算法,编程要求仍然通过两层循环(一次遍历所有元素),找出所有最大值元素及其它们的位置。最后输出它们。仍以上面数组为例, 输出如下:
max = 56,row = 0,column = 3
max = 56,row = 1,column = 2
max = 56,row = 2,column = 2

增加了两个整型数容器分别依次记录最大值的横纵坐标;一旦最大值更新则清空容器重新记录

#include<iostream>
#include<vector>
using namespace std;

int main()
{
    int a[3][4]={{27,12,23,56},{37,2,56,46},{-12,-34,56,8}};    //定义数组
    int max=a[0][0];                                            //max定义及大小初始化
    vector<int> maxX,maxY;                                        //max坐标容器定义及初始化
    maxX.push_back(0);
    maxY.push_back(0);
    
    //遍历循环查找max并且记录值和坐标
    for(int i=0;i<3;i++){
        for(int j=0;j<4;j++){
            if(a[i][j]>=max){
                //最大值发生更新,清空容器重新计数
                if(a[i][j]>max){
                    maxX.erase(maxX.begin(),maxX.end());
                    maxY.erase(maxY.begin(),maxY.end());
                    max=a[i][j];
                }
                maxX.push_back(i);
                maxY.push_back(j);
            }
        }
    }

    //最终输出
    for(int i=0;i<maxX.size();i++)
        printf("max=%d,row=%d,column=%d\n",max,maxX[i],maxY[i]);
    return 0;
}

6. 附加题:报数离队问题

问题描述:有 20 个人围成一个圆圈玩报数游戏:每人背后依次贴上一个编号(编号从 0 到 19),从第 0 号的人开始从 1 报数,第 1 号的人报数 2,…,凡报到 3 的倍数的人离开圈子,后面的人继续往下报数,直到最后只剩下一个人为止。请程序模拟上面的游戏过程,按顺序将依次离开圈子的人的编号打印出来。
提示:可以考虑设计一个数组和一个整型变量来帮助程序的设计。
  1. 设计一个数组用来保存是否离开圈子的状态。
    bool isInGroup[20];
    // isInGroup[i] = true 表示编号为 i 的人在圈子里,否则表示他/她离开圈子; 由于开始时,所有 20 人都在圈子里,所以 isInGroup[20]需要如下初始化:
    for (int i=0;i<20;i++) isInGroup[i] = true;
  2. 定义一个变量 personNumberInGroup 来表示当前还有多少人在圈子里,初值 是 20,所以可以定义如下:
    int personNumberInGroup = 20
#include<iostream>
using namespace std;

bool isInGroup[20];

int main(){
    bool isInGroup[20];                                //是否还在圈内
    for (int i=0;i<20;i++) 
        isInGroup[i]=true;                    
    int personNumberInGroup=20;                        //当前圈内人数
    int flag=0;                                        //报数统计标志
    while(personNumberInGroup>1){                    //不到最后一人不停止
        for(int i=0;i<20;i++){                      //开始一轮报数
            if(isInGroup[i])                        //还在圈内,报数
                flag++;
            if(flag==3){                            //达到3的倍数,离开圈子,flag归零
                isInGroup[i]=false;
                personNumberInGroup--;
                flag=0;
                printf("Player %d quited.\n",i);    //打印出局者
            }
        }
    }
    for (int i=0;i<20;i++) 
        if(isInGroup[i])
            printf("Player %d winned.\n",i);        //打印幸存者
    return 0;
}


暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇