[C++/PTA] 2017Final キャリーとボロー

[C++/PTA] 2017Final キャリーとボロー

トピックの要件

鳳湖小学校 2 年生の陳先生は、クラスの生徒が 3 つのグループに分けられ、1 つのグループは常に 3 桁の整数の足し算と引き算を正確に完了できることに驚きました (グループ A)。常に正確に完了する 3 桁の整数 加算、ただし減算演算については、借入の処理を常に忘れます (グループ B); 残りは常に加算の桁上げを忘れ、減算の借入を常に忘れます (グループ C)。

では、授業中に陳先生が質問したときに生徒たちが答えるであろう答えを教えてください。

以下の基底クラスフレームワーク
クラスGroup
{ をベースに実装してください。

公共:

virtual int add(int x, int y)=0;//加算結果を出力

virtual int sub(int x, int y)=0;//減算結果を出力
}

GroupA、GroupB、GroupC の 3 つのディスパッチ クラスを構築し、
main 関数を作成します。これには、main 関数内に基本クラスのグループ ポインターの配列が必要です。これにより、配列の要素を使用して加算およびサブ演算を均一に実行できます。

入力形式:
まず、クラスの人数である 20 以内の整数 n を入力します。

次に、各生徒のカテゴリとなる n 個の数値 (値は 1、2、または 3) を入力します。最初の数値は 1 番目の生徒のカテゴリ、次は 2 番目の生徒のカテゴリです... 、最後にn回生のカテゴリー。カテゴリが 1 の場合はカテゴリ A に属していることを示し、2 の場合はカテゴリ B に属していることを示し、3 の場合はカテゴリ C に属していることを示します。

次の各行には数学の問題が入ります。数学の質問は 2 つの部分で構成されています。最初の部分は、質問されている生徒の番号です。n を超えない正の整数です。1 は最初の生徒を意味し、2 は 2 番目の生徒を意味し、n は n 番目の生徒を意味します。部分は、特定の数学の問題は加算または減算です。注: オペランドとプラス記号またはマイナス記号の間にスペースはありません。両方のオペランドは 999 を超えない非負の整数です。減算する場合、被減数は減数以上になります。

行が 0 で始まる場合は、質問が終了したことを意味します。

出力形式:
指定された質問に対する指定された生徒の回答を出力します。

入力例:
4
1 2 3 3
1 79+81
2 81-79
4 183+69
0

出力例:
160
12
142

問題解決のアイデア

3 つのクラス GroupA、GroupB、GroupC を定義して、足し算と引き算ができる生徒、足し算だけはできるが引き算はできない生徒、足し算の桁上げを忘れる生徒、引き算の借り入れを忘れる生徒を表します。

仮想関数を使用すると、各クラスにポリモーフィズムを備えた add メソッドと sub メソッドが存在し、実際のオブジェクトの型に応じて対応するメソッドを呼び出すことができます。

main 関数では、まず各生徒のクラスサイズ n と型 temp[i] を読み取り、次に生徒番号モード、演算子 ch、値 x および値に従って生徒に対応する加算と減算を呼び出します。 yを入力質問方式で計算結果を出力します。

コード

#include <iostream>
using namespace std;

class GroupA //加减都会的学生
{
    
    
public:
    virtual int add(int x, int y)//重写虚函数
    {
    
    
        return x+y;   //直接返回正确结果就好
    }
    virtual int sub(int x, int y)  
    {
    
    
        return x-y;
    }
};

class GroupB  //会加法而减法忘记借位的学生
{
    
    
    public:
    virtual int add(int x, int y)
    {
    
    
        return x+y;   //加法直接返回正确值 
    }
    virtual int sub(int x, int y)  //这里有点技巧性,大家可以自己列一个数写个过程来体会
    {
    
    
       int b=x-y, b1=10;   //先得正确结果
       while(x&&y)   //避免有0而出现不需要借位的情况
       {
    
    
           if(x%10<y%10)  b+=b1;//需要借位是因为当前位上不够,所以我们对两个数的每一位逐一比较,如果有小了的,因为忘记借位而导致最终结果是变大了,我们相应减去
           x/=10;
           y/=10;
           b1*=10;  //往上走要借位也就以10倍递增
       }
       return b;
    }
};

class GroupC //加法忘记进位,减法忘记借位的学生,和上面原理是一样的
{
    
    
    public:
    virtual int add(int x, int y)
    {
    
    
       int c=x+y, c1=10;  
       while(x&&y)
       {
    
    
           if(x%10+y%10>=10)  c-=c1;  //如果两个数同一个位上的数相加大于了10,就减去10
           x/=10;
           y/=10;
           c1*=10;
       }
       return c;
    }
    virtual int sub(int x, int y)
    {
    
    
        int c=x-y, c1=10;
       while(x&&y)
       {
    
    
           if(x%10<y%10)  c+=c1;
           x/=10;
           y/=10;
           c1*=10;
       }
       return c;
    }
};

int main()
{
    
    
    int n;//班级人数
    cin>>n;  //先统计要输入的数
    int temp[n+1]; 
    temp[0]=0;  //从1开始用,方便的
    for(int i=1;i<=n;i++)
        cin>>temp[i]; //读入每个同学的类型

    int x,y,mode=1;//mode为被提问学生的编号
    char ch;//运算符
    GroupA   A;
    GroupB   B;
    GroupC   C;
    while(mode!=0)  //不断读入问题,直到以0开头结束
    {
    
    
        cin>>mode>>x>>ch>>y; //读入提问学生编号和数学问题

        if(temp[mode]==1)  //根据学生类型调用相应的方法
        {
    
    
            if(ch=='+')   //判断是什么运算
                cout<<A.add(x,y)<<endl;
            else if(ch=='-')
                cout<<A.sub(x,y)<<endl;
        }

        if(temp[mode]==2)
        {
    
    
            if(ch=='+')
                cout<<B.add(x,y)<<endl;
            else if(ch=='-')
                cout<<B.sub(x,y)<<endl;
        }

        if(temp[mode]==3)
        {
    
    
            if(ch=='+')
                cout<<C.add(x,y)<<endl;
            else if(ch=='-')
                cout<<C.sub(x,y)<<endl;
        }
    }

    return 0;
}

要約する

この質問では、次の知識点を検討します。

  1. 仮想関数の使用、関数の書き換えとカバレッジなどを含むポリモーフィズムの理解と応用。

  2. ループ文 (while) や条件文 (if-else) などの制御構造の使用。

  3. 添字アクセスと配列の走査など。

  4. 加算と減算、キャリーとボロー演算などの基本的な算術演算の実装方法。

私はです、また会いましょう。

おすすめ

転載: blog.csdn.net/2301_77485708/article/details/131211381