C++程序设计实验报告



C++程序设计

实验报告


实验一、字符和格式的输出实验

一,实验目的

1、重点把握各种内部数据类型、数值和逻辑运算,各种表达式、函数声明、定义和调用。

2、掌握过程控制编程方法,正确编制多重循环过程,对简单问题能够临场加以解决。

3、学会使用简单的c++标准库;

4、学习良好的编程习惯和形成自己的编程风格。

二、实验设备与环境

装有C++语言工具软件 (Vs2008)的计算机。

三、       实验内容

a)        P.30,3.2.1,字符三角形;

b)        P.31,3.2.2,背靠背字符三角形;

c)        P.33,3.2.5,格式阵列一。

四、实验过程及结果

1.1字符三角形

【问题描述】:根据读入的字符值以及三角形的高,输入以该字符为填充字符的等腰三角形。

【输入描述】:输入数据含有不超过50组的数据,每组数据包括一个可见字符c(33<=c<=126)和一个整数n(1<=n<=30)。

【输出描述】:输出以c为填充字符、高为n的等腰三角形,勾画每个三角形时都应另起 一行。

【程序代码】:

#include<iostream>

#include<string>

using namespace std;

int main(){

char c;

for(int n; cin>>c>>n; )

for(int i=1; i<=n; i++)

cout<<string(n-i,' ')+string(2*i-1,c)+'\n';

}

【输入】:

A 5 B 3

【输出】:

1.2 字符菱形

【问题描述】:根据读入的字符和边长,勾画字符菱形。

【输入描述】:输入数据含有不超过50组的数据,每组数据包括一个可见字符c和一个整数n(1<=n<=30)。

【输出描述】:输出以c为填充字符、边长为n的菱形,勾画每个菱形时都应另起一行。

【程序代码】:

#include<iostream>

#include<string>

using namespace std;

int main(){

char c;

for(int n; cin>>c>>n; )

{

for(int i=1; i<=n; i++)

cout<<string(n-i,' ')+string(2*i-1,c)+ '\n';

for(int i=1; i<=n-1; i++)

cout<<string(i,' ')+string(2*n-1-2*i,c)+ '\n';

}

}

【输入】:

 A 5 B 3

【输出】:

1.3背靠背字符三角形

【问题描述】:根据读入的字符和高,勾画背靠背字符三角形。

【输入描述】:输入数据不超过50组的数据,每组数据包括一个可见字符c和一个整数n(1<=n<=30)。

【输出描述】:输出以c为填充字符,高为n的背靠背字符三角形,勾画每个三角形时都应另起一行。

【程序代码】:

#include<iostream>

#include<string> 

using namespace std;

int main(){

char c; 

for(int n; cin>>c>>n; )

for(int i=1; i<=n; i++) 

cout<<string(n-i,' ')+string(i,c)+" "+string(i,c)+"\n";

}

【输入】:

   W 5 B 3

【输出】:

1.4 格式阵列一

【问题描述】:根据读入的阶,按样例打印格式阵列。

【输入描述】:输入读入的阶,按样例打印格式阵列。

【输出描述】:输出以n为阶的格式阵列。

每行开始先打印行号,行号为两个字符宽,右对齐,行号与元素之间空2格。

每个元素占3个字符宽。右对齐,元素值起始位置为0,以后每向右前进一个,元素值便取前一元素加1除n的余数,每进到下一行,起始的元素值为上一元素加1除以n的余数,以此类推。

每个格式阵列之间应有一空行,最前与最后不应有空行。

【程序代码】:

#include <iostream>

using namespace std;

int n,casen;

void computing(){ 

   for(int i=0;i<n;i++){

      cout<<" "<<i+1;

      cout<<"    "<<i;

      for(int t=1;t<n;t++) cout<<"  "<<(i+t)%n;

      cout<<endl;

   }

}

int main(){

   while(cin>>n){

      if(casen>0) cout<<endl;

      computing();

      casen++;

   }

   return 0;

}

【输入】:

  6 3

【输出】:


实验二、字符和数字运算实验

一、实验目的  

1、重点把握各种内部数据类型、数值和逻辑运算,各种表达式、函数声明、定义和调用。

2、掌握过程控制编程方法,正确编制多重循环过程,对简单问题能够临场加以解决。

3、学会使用简单的c++标准库;

4、学习良好的编程习惯和形成自己的编程风格。

二、实验设备与环境

装有C++语言工具软件 (Vs2008)的计算机。

三、实验内容

a)        P.44,3.6.1,逆反01串;

b)        P.44,3.6.2,倒杨辉三角形;

c)        P.45,3.6.3,“顺”序列;

d)        P.46,3.6.4,数字和。

四、实验过程及结果

2.1逆反01串

【输入描述】:输入数据含有不多于50个的01串,每个字串的长度不大于200.

【输出描述】:按输入的01串输入对应的10串,每个字串单独占一行。

【程序代码】:

#include<iostream>

using namespace std;

int main()

{

    string s;

    int i,m=1;

    for(;cin>>s;m++)

    {

        if(s.length()<=200)

        {

         for(i=0;i<s.length();i++)

         {

            if(s.substr(i,1)=="1")

            cout<<"0";

            else  cout<<"1";

         }

        }

         else   break;

         cout<<endl;

       if(m>50)  break;

    }

}

【输入】:

0110100100100

1000000010000000000

【输出】:

2.2 倒杨辉三角形

【输入描述】:输入数据中包含了不多于50个的整数n(1<=n<=10).

【输出描述】:以n为行数,其打印出的倒杨辉三角形(每个数据占三个字符),每个倒三角形之间没有空行,见样本输出。

【程序代码】:

#include <iostream>

using namespace std;

const int maxn=10;

int a[maxn+10][maxn+10],n;

void ini(){

   for(int i=1;i<=maxn;i++){

      a[i][i]=1;a[i][1]=1;

   }

   for(int i=3;i<=maxn;i++){

      for(int j=2;j<i;j++){

         a[i][j]=a[i-1][j-1]+a[i-1][j];

      }

   }

}

int main(){

   ini();

   while(cin>>n){

      for(int i=n;i>=1;i--){

         for(int j=i;j<n;j++) cout<<" ";

         for(int j=1;j<=i;j++){

            cout<<a[i][j]<<" ";

         }

         cout<<endl;

      }

   }

   return 0;

}

【输入】:

5

3

【输出】:

2.3“顺”序列

【输入描述】:输入中第一行为一个整数n(1<=n<=10),描述后面一共有n组卡片,每组卡片的第一个数m(1<=m<=100),表示后面会出现m张卡片。

【输出描述】:输入每组卡片,判断是否能构成“顺”序列。如果能构成“顺”序列,则输出yes,否则就输出no。每个结果应分别不同行显示。

【程序代码】:

#include<iostream>

#include<string>

using namespace std;

bool compute(int *a,int m)

{

    int i,j,max=0;

    for(i=0;i<m;i++){

        if(a[i]>max)

            max=a[i];

    }

    for(i=0;i<m;i++){

        for(j=0;j<m;j++){

        if(a[i]+1==a[j] || a[i]==max)

            break;

    }

    if(j>=m)

        return false;

    }

    return true;

}

int main()

{

    int *a;

    int n=0;

    int m=0;

    string *b;

    int i,j;

    int rsize=0;

    cout<<"请输入一个整数n:";

    cin>>n;

    b=new string[n];

    j=0;

    while(j<n){

    cout<<"请输入整数m:";

    cin>>m;

    a=new int[m];

    cout<<"请输入一连串数据:"<<endl;

    for(i=0;i<m;i++)

        cin>>a[i];

    if(compute(a,m))

        b[j]="Yes";

    else

        b[j]="No";

    delete[] a;

    j++;

    }

    cout<<"输出:"<<endl;

    for(i=0;i<n;i++)

        cout<<b[i]<<endl;

    delete[] b;

    return 0;

}

【输入】:

2

4 5 7 6 8

8 1 7 3 2 8 12 78 3

【输出】:

2.4 数字和

【输入描述】:输入数据中包含了不多于50个的正整数n

【输出描述】:每个正整数都应输出一个各位数字和,并独占一行。

【程序代码】:

#include <iostream>

#include <string>

using namespace std;

int main(){

   string st;

   while(getline(cin,st)){

      int ans=0;

      for(int i=0;i<st.length();i++){

         if(st[i]>='0' && st[i]<='9') ans+=st[i]-'0';

      }

      cout<<ans<<endl;

   }

   return 0;

}

【输入】:

12345

56123

82

【输出】:

五、实验小结:

     本次试验重点学习了各种数据类型,逻辑运算,函数的声明,定义和调用。在过程控制过程中,熟练地使用多重循环,同时应养成良好的编程习惯和形成自己的编程风格,一边为日后的学习打下坚实的基础。

实验三、加密和解密算法实验

一、实验目的  

1、重视数学方法,提高数学推算和编程表的转换能力。

2、拓展编程表达的方法,熟练运用函数等手段进行计算模块的分离计算。

3、进一步学会使用c++标准库;

4、在保证编程程序正确的条件下,关注数据结构和算法,改进效率。

二、实验设备与环境

装有C++语言工具软件 (Vs2008)的计算机。

三、实验内容

a)        P.98,7.2.1,密钥加密;

b)        P.99,7.2.2,密钥解密;

四、实验过程及结果

3.1 密钥加密

【实验代码】:

#include <iostream>

#include<string.h>

using namespace std;

int main()

{   while(1){

   char key[100],data[101];

   cin.getline(key,100);

   cin.getline(data,100);

   cout<<key;

    int i=0,j=0;

    for(i=0;i<strlen(data);i++){

        for(j=0;j<strlen(key);j++){

            if(i>=strlen(data))

                break;

            data[i]+=key[j]-'0';

            if(data[i]>122)

                data[i]=data[i]-123+32;

            i++;

        }

        i-=1;

    }

    cout<<data<<endl;

    }

    return 0;

}

【输入】:

4972863

The result of 3 and 2 is not 8

123

Hello world

【输出】:

3.2 密钥解密

【实验代码】:

#include <iostream>

#include<string.h>

using namespace std;

int main()

{

   while(1){

   char key[100],data[101];

   cin.getline(key,100);

   cin.getline(data,100);

   cout<<key<<"\n";

    cout<<data<<"\n";

    int i=0,j=0;

    for(i=0;i<strlen(data);i++){

        for(j=0;j<strlen(key);j++){

            if(i>=strlen(data))

                break;

            data[i]-=key[j]-'0';

            if(data[i]<32)

                data[i]=data[i]-32+123;

            i++;

        }

        i-=1;

    }

    cout<<data<<endl;

   }

    return 0;

}

【输入】

4972863

xql”zkvyu “wl#7)hpl”5$rx”vuw$A

123

Igomq#Xqumf

【输出】:

五,实验小结:

    通过本次实验,对加密解密有一定的了解,密钥加密就是将密钥数字串值循环加到明文上,使得明文不可阅读,解密就是加密的反过程。实验中,遇到一些问题,字符串的读入和输出以及循环表达式的设计,通过查阅资料和上网查阅,最后算是解决问题。

实验四、数字算法实验

一、实验目的  

1、重视数学方法,提高数学推算和编程表的转换能力。

2、拓展编程表达的方法,熟练运用函数等手段进行计算模块的分离计算。

3、进一步学会使用c++标准库;

4、在保证编程程序正确的条件下,关注数据结构和算法,改进效率。

二、实验设备与环境

装有C++语言工具软件 (Vs2008)的计算机。

三、实验内容

a)        P.102,7.3.1,n!的位数;

b)        P.103,7.3.2,排列对称串;

c)        P.103,7.3.3,勒让德多项式表;

d)        P.104,7.3.4,立方数和连续奇数和;

四、实验过程及结果

4.1  n!的位数

【基本描述】:针对每个非负整数n,计算n!的位数

【输入描述】:输入数据中含有一些整数n(0<=n<10^7)

【输出描述】:根据每个整数n,输出n!的位数,每个数占独立一行。

【主要代码】:                  

#include <iostream>

#include <cmath>

using namespace std;

int main()

{

double N,logV;

int i;

while(cout<<"输入N的值:" && cin>>i)

{

N=i;

for(i=1,logV=0;i<=N;i++)

{

logV+=log(1.0*i);

}

logV/=log(10.0);

cout<<N<<"!的位数:"<<(int)(logV+1)<<endl;

}

return 0;

}

【输入】:

5  6

【输出】:

4.2 排列对称串

【基本描述】:一些字串,有些是对称的,有些是不对称的。请将那些对称的字串按从小到大的顺序输出。字串先以长度论大小,如果长度相同,再以ASCII码值大小为标准。

【输入描述】:输入数据中含有一些字串(1<=串长<=256)

【输出描述】:根据每个字串,输出对称的那些串,并且要求按从小到大的顺序输出。

【代码如下】:

#include <fstream>

#include <iostream>

#include <string>

#include <vector>

#include <algorithm>

using namespace std;

bool Comp(const string &s1,const string &s2)

{

    return s1.length()!=s2.length()?s1.length()<s2.length():s1<s2;

}

int main(int argc,char * argv[])

{

    vector<string> v;

    string t,s;

    while(cin>>s)

    {

        t=s;

        reverse(t.begin(),t.end());

        if(t==s)

        {

            v.push_back(s);

        }

        if(cin.get()=='\n')

        {

            break;

        }

    }

    sort(v.begin(),v.end(),Comp);

    for(int i=0;i<v.size();i++)

    {

        cout<<v[i]<<endl;

    }

    system("pause");

    return 0;

}

【输入】:

123321

123

321

sdfsdfd

121212

\\dd\\

【输出】:

4.3 勒让德多项式表

【基本描述】:数学poly函数的展开式也称关于x的n阶勒让德多项式,它的递推公式为:

给定x,请计算n阶勒让德多项式的值。

【输入描述】:输入数据中含有一些浮点数x(0<x<1)

【输出描述】:对于每个x,分别计算2阶,3阶,4阶,5阶,6阶的勒让德多项式的值,其每个值的精度为6位小数。输出时,先列出x的值,保留3位小数精度,然后每输出一个阶值之前,都空出2格,由此一字排开,形成一张多项式表

【代码如下】:

#include <iostream>

#include<iomanip>

using namespace std;

double poly(int n,double x);

int main()

{   int i=0;

    for(double x;cin>>x;){

        if(i==0){

            cout<<"   x     p2(x)      p3(x)       p4(x)     p5(x)     p6(x)"<<endl;

            i=1;

        }

        cout<<fixed<<setprecision(3)<<x<<setprecision(6);

        for(int i=2;i<=6;i++){

            cout<<setw(11)<<poly(i,x);

        }

        cout<<endl;

    }

}

double poly(int n,double x){

    if(n==0)

        return 1;

    if(n==1)

        return x;

    return ((2*n-1)*x*poly(n-1,x)-(n-1)*poly(n-2,x))/n;

}

【输入】:

0.2  0.3  0.35

【输出】:

4.4  立方数与连续奇数和

【基本描述】:一个整数的立方数,可以表示为连续奇数的和,例如:

3^3=7+9+11

4^3=13+15+17+19

针对每个正整数n,输出表示其立方数的连续奇数和

【输入描述】:输入数据中含有一些整数n(1<=n<=100)

【输出描述】:根据每个整数n,输出其值等于n^3的连续奇数和

【代码如下】:

#include <iostream>  

using namespace std; 

int main() { 

int i,n,j,a[5]; 

   cin>>n; 

   for(i=0;i<n;i++) { 

       cin>>a[i]; 

   for(i=0;i<n;i++) { 

       int m=a[i]*a[i]-a[i]+1; 

       for(j=0;j<a[i];j++) { 

           cout<<m<<" "; 

           m+=2; 

       cout<<endl; 

   } 

   return 0; 

【输入】:

3 4 8

【输出】:

4.5 斐波那契数

【基本描述】:根据输入数据中的n,输出第n项斐波那契数。

【输入描述】:输入数据中含有一些整数n(0<=n<=46)

【输出描述】:根据每个整数n,输出其第n项斐波那契数,每个数独占一行。

【代码如下】:

#include <iostream>

#include <vector>

using namespace std;

int main(){

    int n;

    vector<int> v;

    v.push_back(0);

    v.push_back(1);

     for(int k = 2; k <= 46; ++k)

         v.push_back(v[k-1] + v[k-2]);

    while(cin >> n)

        cout << v[n] << endl;

    return 0;

 }

【输入】:

5 6 7 8 9 40

【输出】:

五,实验小结:

     本次试验第一,三,五题均使用递归算法,即程序自己调用自己的编程技巧。在使用递归时,要有递归边界条件,递归前进段和递归返回段。当边界条件不满足时,递归前进,当边界条件满足时,递归返回。应该熟练掌握递归算法的用法。第二题中,排序比较函数的具体方法是,判断参与比较的没两个字符串的长度是否相等,若不相等则按长度从小到大的顺序返回;若相等则以ASCII码值为排序标准,即按字符串从小到大排序。第四题中,立方数表示为连续的奇数和。n个连续的奇数,假设第一个奇数为x,那么第n个奇数就是x+(2n-2) 。n个连续奇数的和就等于x+(x+2)+...+(x+(2n-2)) = (x+n-1)*n 。正整数n的立方可以表示为n个连续奇数的和 

就可以变成 n*n*n = (x+n-1)*n -> n*n = x+n-1 -> x=n*n-n+1 。

实验五、大数运算算法实验

一、实验目的  

1、重视数学方法,提高数学推算和编程表的转换能力。

2、拓展编程表达的方法,熟练运用函数等手段进行计算模块的分离计算。

3、进一步学会使用c++标准库;

4、在保证编程程序正确的条件下,关注数据结构和算法,改进效率。

二、实验设备与环境

装有C++语言工具软件 (Vs2008)的计算机。

三、实验内容

a)        P.106,7.4.2,大数加;

b)        P.107,7.4.3,大数和;

c)        P.109,7.5.1,大数乘;

四、实验过程及结果

5.1大数加

【基本描述】:给定一些大数,把它们加起来。

【输入描述】:输入数据中含有一些数据组(数量<=100),每组数据由一个整数n(n<=100)领衔,后跟n个大整数(0<=大数,大数位数<=200),若n=0则表示输入结束。

【输出描述】:输出每组数据所计算的大数和,每个结果但独占一行。

【主要代码】:

#include <iostream>

using namespace std;

void add(string &a,const string &s)

{

    int temp=0;

    for(int ai=0,si=s.length()-1;si>=0||temp;++ai,--si)

    {

        temp+=a[ai]-'0'+(si>=0?s[si]-'0':0);

        a[ai]=temp%10+'0';

        temp=temp/10;

    }

}

int main()

{

    const int bitnum=205;

   for(int num;cin>>num&&num;)

   {

       string a(bitnum,'0');

       for(string s;num--&&cin>>s;)

        add(a,s);

       reverse(a.begin(),a.end());

       cout<<a.substr(a.find_first_not_of('0'))<<"\n";

   }

   return 0;

}

【输入】:

5

5

79

0

【输出】:

5652057111507

【测试结果】:

5.2 大数和

【基本描述】:给定一些大数,有正有负,请计算其和。

【输入描述】:输入数据中含有一些数据组(数量<=100),每组数据由一个整数n(n<=100)领衔,后跟n个大数(大数位数<=200),若n=0则表示输入结束。

【输出描述】:输出每组数据所计算的大数和,每个结果单独占一行。

【主要代码】:

#include <iostream>

using namespace std;

void comple(string &s)

{

    for(int i=0;i<s.length();++i)

    s[i]='9'-s[i]+'0';

    for(int i=s.length()-1;i>=0;i--)

    if(s[i]=='9')

    s[i]='0';

    else

    {

        s[i]++;

        break;

    }

}

void add(string &a,const string &s)

{

    int temp=0;

    for(int ai=0,si=s.length()-1;si>=0||temp;++ai,--si)

    {

        temp+=a[ai]-'0'+(si>=0?s[si]-'0':0);

        a[ai]=temp%10+'0';

        temp=temp/10;

    }

}

int main()

{

   const int bitnum=205;

   for(int num;cin>>num&&num;)

   {

       string a(bitnum,'0');

       for(string s;num--&&cin>>s;)

       {

           if(s[0]=='-')

           {

               s=s.substr(1);

               s=string(bitnum-s.length(),'0')+s;

               comple(s);

           }

           else

           s=string(bitnum-s.length(),'0')+s;

           add(a,s);

       }

       reverse(a.begin(),a.end());

       if(a[0]=='9')

       {

           comple(a);

           cout<<"-";

       }

       int pos=a.find_first_not_of('0');

       if(pos==string::npos)

       cout<<"0\n";

       else

       cout<<a.substr(pos)<<"\n";

   }

   return 0;

}

【输入】:

2

-2

2

0

【输出】:

123xxxxxxxxxxxx23xxxxxxxxxxxx21

42007774688021

【测试结果】:

5.3大数乘

【基本描述】:给定一些大数,请计算其积。

【输入描述】:输入数据中含有一些整数对(对数<=1000),若某对整数n(整数位数<=200)的值为0 0,则表示输入结束。

【输出描述】:每对整数对应一个乘法计算结果,输出该结果,每个结果输出完后应回车。

【主要代码】:

#include <iostream>

using namespace std;

string multi(const string &a,const string &b)

{

    if(a=="0"||b=="0")

    return "0";

    string aa(a[0]=='-'? a.substr(1):a);

    string bb(b[0]=='-'? b.substr(1):b);

    string sign=((a[0]=='-')+(b[0]=='-')==1?"-":"");

    string s(aa.length()+bb.length(),'0');

    reverse(aa.begin(),aa.end());

    reverse(bb.begin(),bb.end());

    for(int j=0;j<bb.length();++j)

    {

        if(bb[j]=='0')

        continue;

        int temp=0;

        for(int i=0;i<aa.length();++i)

        {

            temp=temp+(aa[i]-'0')*(bb[j]-'0')+(s[j+i]-'0');

            s[j+i]=temp%10+'0';

            temp=temp/10;

        }

        s[aa.length()+j]+=temp;

    }

    reverse(s.begin(),s.end());

    return sign+s.substr(s.find_first_not_of('0'));

}

int main()

{

    for(string a,b;cin>>a>>b&&(a!="0"||b!="0");)

    cout<<multi(a,b)<<"\n";

   return 0;

}

【输入】:

2 3

12 34

0 0

【输出】:

6

408

【测试结果】;

五,实验小结:

     本次试验主要进行了大数运算,在编程时应注意运算的结果不能溢出,以及熟练的掌握函数的应用,在实验过程中遇到一些困难,通过网络和书籍,使得问题得到解决。

实验六、日期处理算法实验

一、实验目的  

1、掌握从上到下的程序结构化设计,以主函数为驱动,层层调用其他函数的框架结构。

2、掌握界面设计原理,学会编制作为界面的头文件。

3、合理组织程序的各个模块;

4、熟悉类型设计和类型实现的模块结构,熟悉自定义类型嵌入应用程序的基本方法。

二、实验设备与环境

装有C++语言工具软件 (Vs2008)的计算机。

三、实验内容

a)        P.167,11.2, 日期处理;

四、实验过程及结果

【主要代码】

//天数date.h

#ifndef DATE_HEADER

#define DATE_HEADER

#include<iostream>

using namespace std;

class Date

{

   int _absDay;

   void _ymd2i(int y, int m, int d);

   void _i2ymd(int &y ,int &m,int &d)const;

   bool _isLeapYear(int y)const//判断是否为闰年

   {

      return y%4==0 && y%100 || y%400==0;

   }

    static const int tians[];

   static const char *week[];

public:

   enum

   {

      YYMD ,

      MDYY,

      YMD,

      MDY

   };//枚举日期的输出格式

   Date(const string &s);

   Date(int n=1) : _absDay(n){}

   Date(int y,int m,int d){ _ymd2i(y,m,d); }

   Date operator +(int n)const

   {

      return Date(_absDay + n);

   }

   Date &operator +=(int n)

   {

      _absDay +=n;

      return *this;

   }

   Date& operator ++()

   {

      _absDay++;

      return *this;

   }

    Date &operator --()

   {

      _absDay--;

      return *this;

   }//定义运算

    bool operator ==(const Date &d )const

   {

      return _absDay==d._absDay;

   }

    bool operator !=(const Date &d )const

   {

      return _absDay!=d._absDay;

   }

    bool operator <(const Date &d )const

   {

      return _absDay<d._absDay;

   }//定义操作符

   void print(ostream &out ,int type)const;//输出的方法

   int operator-(Date &d)const

   {

      return _absDay-d._absDay;

   }

    Date operator-(int n)const

   {

      return Date(_absDay-n);

   }

    Date &operator-=(int n)

   {

      _absDay-=n;

      return *this;

   }

   bool isLeapYear()const;

   const char * getWeekDay()const

   {

      return week[_absDay%7];

   }

   int getAbsDay()const

   {

      return _absDay;

   }

   friend istream & operator>>(istream & i,Date &d);

   friend ostream & operator<<(ostream &o,const Date &d);

};

#endif

//datePro.h

#include<iostream>

using namespace std;

void pr302A(istream &cin,ostream &cout);//统计天数

void pr302B(istream &cin,ostream &cout);//推排日期

void pr302C(istream &cin,ostream &cout);//确定天数

void pr302D(istream &cin,ostream &cout);//星期几

void pr302E(istream &cin,ostream &cout);//安排会议

//供菜单驱动程序(dateApp.cpp)使用

//异常处理的头文件myExcept.h

#ifndef MYEXCEPT_HEADER

#define MYEXCEPT_HEADER

class MyExcept

{

public:

   virtual char* getWhat() =0;

};

class MyFormatError :public MyExcept

{

public :

   char * getWhat()

   {

      return "Format Error.";

   }

};//格式错误

class MyIllegal :public MyExcept

{

public :

   char * getWhat()

   {

      return "Illegal.";

   }

};//非法

#endif

//天数版date.cpp

#include"date.h"

#include"myExcept.h"

#include<iostream>

#include<iomanip>

using namespace std;

const int Date::tians[]={0,31,59,90,120,151,181,212,243,273,304,334,365};//月份相加的天数,用来统计天数

const char* Date::week[]={"Sun.","Mon.","Tue.","Wed.","Thu.","Fri.","Sat."};//定义一周的时间

Date::Date(const string &s)

{

   int y=1000*(s[0]-'0')+100*(s[1]-'0')+10*(s[2]-'0')+s[3]-'0';//年

   int m=10*(s[5]-'0')+s[6]-'0';//月

   int d=10*(s[8]-'0')+s[9]-'0';//日

   _ymd2i(y,m,d);

}

void Date::_ymd2i(int y,int m,int d)

{

   if(y<=0||y>9999)

      throw MyIllegal();

   if(m<=0||m>12)

      throw MyIllegal();

   if(d<=0||d>tians[m]-tians[m-1] + m == 2 && _isLeapYear(y) )

      throw MyIllegal();                 //如果年、月、日超出限制,就跳出非法

   int ny=(y-1)*365+(y-1)/4-(y-1)/100+(y-1)/400;

   _absDay=ny+tians[m-1]+d+(m>2 && _isLeapYear(y));//判断是不是闰年,总共的天数

}

void Date::_i2ymd(int &y,int &m,int &d)const

{

   int n400 =_absDay/146097;//400年的个数

   int y400 =_absDay%146097;

   int n100 =y400/36524;//100年的个数

    int y100 =y400%36524;

   int n4 =y100/1461;//4年的个数

   int y4 =y100%1461;

   int n1=y4/365;//1年的个数

   int y1=y4%365;

   y=n400 *400 +n100*100+n4*4+n1+(y1!=0);

   m=12;

   if(y1==0)//年底

      d=30+(n1!=4);//若n1==4,则年底差一天

   else

   {

      while(y1<=(n1==3 && m>=2)+tians[m])

         m--;//n1==3为闰年

      d=y1-tians[m]-(n1==3 && m>=2);

      m++;

   }

}

void Date::print(ostream & o,int type)const

{

   int y,m,d;

   _i2ymd(y,m,d);

   o<<right<<setfill('0');

   switch(type)

   {

   case YMD: o<<setw(2)<<y%100<<"-"<<setw(2)<<m<<"-"<<setw(2)<<d;

      break;

   case MDY: o<<setw(2)<<m<<"-"<<setw(2)<<d<<"-"<<setw(2)<<y%100;

      break;

    case YYMD: o<<setw(4)<<y<<"-"<<setw(2)<<m<<"-"<<setw(2)<<d;

      break;

   case MDYY:o<<setw(2)<<m<<"-"<<setw(2)<<d<<"-"<<setw(4)<<y;

      break;

   default:throw MyFormatError();

   }

   o<<setfill(' ');

}//几种形式输出的格式

bool Date::isLeapYear()const

{

   int y,m,d;

   _i2ymd(y,m,d);

   return _isLeapYear(y);

}

istream &operator>>(istream &i,Date &d)

{

   string s;

   if(i>>s)

      d=Date(s);

   return i;

}

ostream &operator<<(ostream &o,const Date &d)

{

   d.print(o,d.YYMD);

   return o;

}

//datePro.cpp

#include"date.h"

#include"datePro.h"

#include<iostream>

#include<map>

#include<iomanip>

#include<vector>

#include<algorithm>

#include<sstream>

using namespace std;

void Pr302A(istream &cin,ostream &cout){cout<<"pr302A"<<endl;}

void Pr302B(istream &cin,ostream &cout){cout<<"pr302B"<<endl;}

void Pr302C(istream &cin,ostream &cout){cout<<"pr302C"<<endl;}

void Pr302D(istream &cin,ostream &cout){cout<<"pr302D"<<endl;}

void Pr302E(istream &cin,ostream &cout){cout<<"pr302E"<<endl;}//函数声明

void Pr302A(istream &cin,ostream &cout)

{

   map<string,int> sd;

   string n,fs;

   for(Date d;cin>>n>>d>>fs;)

      sd[n]=d.getAbsDay() + (fs=="Out" ? 0 : 1 - sd[n]);//得到日期,和出去或回来的标记

   cout<<"统计天数"<<endl;

   for(map<string,int>::const_iterator it=sd.begin() ; it!=sd.end(); ++it)//iterator:迭代器

      cout<<left<<setw(10)<<it->first<<right<setw(5)<<it->second<<endl;

}//统计天数

struct NameNum{

   NameNum(const string &s,const Date &d):name(s),num(d.getAbsDay()){}

   NameNum(const string &s,int n):name(s),num(n){}

   string name;

   int num;

};//用于pr302B,pr302C,结构体

bool operator<(const NameNum &n1,const NameNum &n2)

{

   return n1.num==n2.num?(n1.name<n2.name):(n1.num<n2.num);

}//姓名排序输出

void pr302B(istream &cin,ostream &cout)

{

   vector<NameNum> nd;

   Date curDay;

   cin>>curDay;//输入当前日期

   int n;vector // 完成当前工作需要的时间

   for(string s;cin>>s>>n;)

      nd.push_back(NameNum(s,curDay+n)); //向后推迟时间,计算出有空的时间

   sort(nd.begin(),nd.end()); //整理

   cout<<"推排日期:\n";

   for(int i=0;i<nd.size();++i)

      cout<<left<<setw(11)<<nd[i].name<<Date(nd[i].num)<<endl;

}//推排时间

void pr302C(istream &cin,ostream &cout)

{

   vector<NameNum> nd;

   Date curDay ,d;

   cin>>curDay;// 输入当前日期

   for(string s;cin>>s>>d; )

      nd.push_back(NameNum(s,d-curDay));//向后推迟天数

   sort(nd.begin(),nd.end());//整理

   cout<<"确定天数:\n";

   for(int i=0;i<nd.size();++i)

   cout<<nd[i].name<<" "<<nd[i].num<<endl;

} //  确定天数

void pr302D(istream &cin,ostream &cout)

{

   cout<<"星期几:\n";

   for(Date d;cin>>d;) //  输入天数

      cout<<d.getWeekDay()<<endl;// 调用d.getWeekDay()

}// 星期几

void pr302E(istream &cin, ostream& cout)

{

   Date a,b,d,mD;

   int n,maxd=0;

   cin>>a>>b>>n;//输入会议想要召开的时间段和需要的天数

   cin.ignore();//cin.ignore()的含义是把缓冲区内从当前字符开始知道的字符忽略掉

   for(string s,t;getline(cin,s);a=d+1)

   {

      istringstream sin(s);

         sin>>d;

      if(d-a>maxd) maxd=d-a,mD=a;  //时间间隔为后一个时间减去前一个时间,最大的一个时间段

      sin>>d;

   }

   if(b-a+1>maxd) maxd=b-a+1,mD=a;//取出最大时间段

   d=mD+(maxd-n)/2;// 开始的时间+(最大的时间段-会议需要的时间)/2得到安排会议最佳的开始的时间

   cout<<"安排会议:\n";

   d.print(cout,d.MDYY);//按MDYY的格式输出

   cout<<endl;

}// 安排会议

//日期处理DateApp.cpp

#include "datePro.h"

#include "myExcept.h"

#include<conio.h> //用于getch()

#include<fstream>

#include<iostream>

#include<stdlib.h>//用于clrscr()

using namespace std;

typedef void(*PF)(istream &cin,ostream & cout);

char *iFile[]={"A32.txt","B32.txt","C32.txt","D32.txt","E32.txt"};

char *oFile[]={"A32.out","B32.out","C32.out","D32.out","E32.out"};//输入与输出

PF func[] ={pr302A,pr302B,pr302C,pr302D,pr302E};//5个函数

int main()

{

   for(int choice =1;choice;)

   {

      system("cls");

      if(choice>5)

         cout<<"You may enter a wrong key ,try again .\n\n";

      cout<<"1-----统计天数<<endl";

      cout<<"2-----推断日期<<endl";

      cout<<"3-----确定天数<<endl";

      cout<<"4-----星期几<<endl";

      cout<<"5-----安排会议<<endl";

      cout<<"0-----退出系统<<endl";

      cout<<"Enter your choice:";

      cin>>choice;//输出格式

      if(choice>=1 && choice<=5)

      {

         ifstream cin(iFile[choice-1]);

         ofstream cout(oFile[choice-1]);

         try{

            func[choice-1](cin ,cout);//调用各个函数

         }catch(MyExcept &e){

            cerr<<e.getWhat()<<endl;

         }

         cerr<<"press any key ...";

         getch();//接收键盘输入的

      }

   }

}

五,实验小结:

     本次试验主要为日期的处理,内容比较复杂,有比较大的难度,上网查阅资料,查阅书籍等都没有解决问题。说明自己在平时的学习中还存在很多的漏洞没有解决。在日后的学习中应该更加注重编程能力和分析问题解决问题的能力,以争取有所进步。

相关推荐