当前位置:   article > 正文

[Icarus]北大《C++程序设计》week4编程代码_#include

#include

本周的课程作业量有点儿大,比较不好写的是后两题。倒数第二题参考了网上很多人的代码,最后选了一个我觉得比较好的写法,即用指针的指针(而不是仅仅用指针)来实现这个二维数组,这样写下来逻辑就顺畅多了。。。同理,也可以使用指针的指针的指针来实现三维数组,不过构造析构会比较麻烦。


此次交作业,同样要注意的是本周的填空代码如果在Coursera上提交的话只需提交空缺部分即可,不然会通不过。


最后的这个大整数类折磨了我好几天(是我基础比较薄弱大哭),刚开始的时候看别人的代码没看懂,然后果断找来晴神宝典细细研读了大整数(又称高精度整数)运算的内容(《算法笔记》第5章-数学问题-5.6),无奈乘除法部分只介绍了高精度与低精度的乘除,上面的原话是“至于高精度与高精度的乘法和除法,考试一般不会涉及,因此留给有兴趣的读者自行了解。”再去翻王道的机试指南,比较郁闷的是发现情况也是一样的,都是高精度整数与普通整数的乘除。


太TM应试了。


不过想到了自己也是因为应试的原因才做的这个作业,我缓缓地放下了想要摔书的手。


只能自己想办法解决了。看了好几个大神的代码,虽然没太看懂,但是大概掌握了一点儿解决乘除法的思想,试着自己写了代码。说白了原理其实挺简单,乘法就是一个数不断累加,除法就是一个数能被除数减掉多少次那个次数就是商。当然,具体解决的算法不是这样,这个需要自己动手演算一下才能明白。


上代码:

编程题 #1

注意: 总时间限制: 1000ms 内存限制: 65536kB

描述

下面程序的输出是:

3+4i

5+6i

请补足Complex类的成员函数。不能加成员变量。

#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;
class Complex {
private:    
    double r,i;
public:    
    void Print() {
        cout << r << "+" << i << "i" << endl;
    }
// 在此处补充你的代码
};
int main() {
    Complex a;
    a = "3+4i"; a.Print();
    a = "5+6i"; a.Print();
    return 0;
}

输入

输出

3+4i

5+6i

样例输入

样例输出
3+4i
5+6i
参考代码:
  1. /*
  2. * week4 part1.cpp
  3. *
  4. * Created on: 2018年3月5日
  5. * Author: Arno
  6. */
  7. #include <iostream>
  8. #include <cstring>
  9. #include <cstdlib>
  10. using namespace std;
  11. class Complex {
  12. private:
  13. double r,i;
  14. public:
  15. void Print() {
  16. cout << r << "+" << i << "i" << endl;
  17. }
  18. //此处为补充代码
  19. Complex & operator=(const char* str){
  20. string s=str;
  21. int pos=s.find("+",0);//查找加号的位置
  22. string sTmp=s.substr(0,pos);//分离出代表实部的字符串
  23. r=atof(sTmp.c_str());//atof库函数能将const char*指针指向的内容转换成float
  24. sTmp=s.substr(pos+1,s.length()-pos-2);//分离出代表虚部的字符串
  25. i=atof(sTmp.c_str());
  26. return *this;
  27. }
  28. };
  29. int main() {
  30. Complex a;
  31. a = "3+4i"; a.Print();
  32. a = "5+6i"; a.Print();
  33. return 0;
  34. }

编程题 #2

注意: 总时间限制: 1000ms 内存限制: 65536kB

描述

下面的MyInt类只有一个成员变量。MyInt类内部的部分代码被隐藏了。假设下面的程序能编译通过,且输出结果是:

4,1

请写出被隐藏的部分。(您写的内容必须是能全部放进 MyInt类内部的,MyInt的成员函数里不允许使用静态变量)。

#include <iostream>
using namespace std;
class MyInt {
    int nVal;
    public:
        MyInt(int n) { nVal = n; }
        int ReturnVal() { return nVal; }
// 在此处补充你的代码
};
int main () {
    MyInt objInt(10);
    objInt-2-1-3;
    cout << objInt.ReturnVal();
    cout <<",";
    objInt-2-1;
    cout << objInt.ReturnVal();
    return 0;
}

输入

输出

4,1

样例输入

样例输出

4,1
参考代码:
  1. /*
  2. * week4 part2.cpp
  3. *
  4. * Created on: 2018年3月5日
  5. * Author: Arno
  6. */
  7. #include <iostream>
  8. using namespace std;
  9. class MyInt {
  10. int nVal;
  11. public:
  12. MyInt(int n) { nVal = n; }
  13. int ReturnVal() { return nVal; }
  14. //在此处补充你的代码
  15. MyInt & operator-(const int n){
  16. nVal-=n;
  17. return *this;
  18. }
  19. };
  20. int main () {
  21. MyInt objInt(10);
  22. objInt-2-1-3;
  23. cout << objInt.ReturnVal();
  24. cout <<",";
  25. objInt-2-1;
  26. cout << objInt.ReturnVal();
  27. return 0;
  28. }
编程题 #3

注意: 总时间限制: 1000ms 内存限制: 65536kB

描述

写一个二维数组类 Array2,使得下面程序的输出结果是:

0,1,2,3,

4,5,6,7,

8,9,10,11,

next

0,1,2,3,

4,5,6,7,

8,9,10,11,

程序:

#include <iostream>
#include <cstring>
using namespace std;
// 在此处补充你的代码
int main() {
    Array2 a(3,4);
    int i,j;
    for( i = 0;i < 3; ++i )
        for( j = 0; j < 4; j ++ )
            a[i][j] = i * 4 + j;
    for( i = 0;i < 3; ++i ) {
        for( j = 0; j < 4; j ++ ) {
            cout << a(i,j) << ",";
        }
        cout << endl;
    }
    cout << "next" << endl;
    Array2 b; b = a;
    for( i = 0;i < 3; ++i ) {
        for( j = 0; j < 4; j ++ ) {
            cout << b[i][j] << ",";
        }
        cout << endl;
    }
    return 0;
}

输入

输出

0,1,2,3,

4,5,6,7,

8,9,10,11,

next

0,1,2,3,

4,5,6,7,

8,9,10,11,

样例输入

样例输出
0,1,2,3,
4,5,6,7,
8,9,10,11,
next
0,1,2,3,
4,5,6,7,
8,9,10,11,
参考代码:
  1. /*
  2. * week4 part3.cpp
  3. *
  4. * Created on: 2018年3月5日
  5. * Author: Arno
  6. */
  7. #include <iostream>
  8. #include <cstring>
  9. using namespace std;
  10. //在此处补充你的代码
  11. class Array2 {
  12. int row,column;
  13. int **ptr;//因为是二维数组,所以定义一个指向指针的指针
  14. public:
  15. Array2(int i=0,int j=0);//构造函数
  16. Array2(Array2 & a);//复制构造函数
  17. ~Array2();//析构函数
  18. Array2 & operator=(const Array2 & a);//用于数组对象间的赋值
  19. int *& operator[](int i){
  20. return ptr[i];
  21. }//相当于只重载了第一个[],返回了(行)指针
  22. int & operator()(int i,int j){
  23. return ptr[i][j];//(行)指针再加上[],就可以直接定位数据了
  24. }//用于支持根据下标访问数组
  25. };
  26. Array2::Array2(int i,int j):row(i),column(j){
  27. if(i==0||j==0)
  28. ptr=NULL;//若行列中有一个为0,则置指针的指针为空
  29. else{
  30. ptr=new int*[i];//分配指向每行的指针,注意左右两边都是int**
  31. for(int k=0;k<i;++k){
  32. ptr[k]=new int[j];//给每个行指针分配对应的列空间
  33. }
  34. }
  35. }
  36. Array2::Array2(Array2 & a){
  37. row=a.row;
  38. column=a.column;//行和列的参数先拷贝一下
  39. if(!a.ptr){
  40. ptr=NULL;
  41. return;
  42. }
  43. ptr=new int*[a.row];//深拷贝
  44. for(int k=0;k<a.row;++k){
  45. ptr[k]=new int[a.column];
  46. memcpy(ptr[k],a.ptr[k],sizeof(int)*a.column);
  47. }
  48. }
  49. Array2::~Array2(){
  50. if(ptr){
  51. for(int k=0;k<row;++k){
  52. delete [] ptr[k];
  53. }
  54. delete [] ptr;//先释放列空间再释放行指针数组
  55. }
  56. }
  57. Array2 & Array2::operator=(const Array2 & a){
  58. if(ptr==a.ptr)//防止a=a这样的赋值导致错误
  59. return *this;
  60. row=a.row;
  61. column=a.column;//先拷贝行列数据
  62. if(ptr){
  63. for(int k=0;k<row;++k){
  64. delete [] ptr[k];
  65. }
  66. delete [] ptr;
  67. }//若ptr存在则先将其占用的所有内存空间释放掉
  68. if(a.ptr==NULL){
  69. ptr=NULL;
  70. return *this;//若a指针为空,则现在对象的指针也置为NULL
  71. }
  72. ptr=new int*[a.row];//分配行指针
  73. for(int k=0;k<a.row;++k){
  74. ptr[k]=new int[a.column];
  75. memcpy(ptr[k],a.ptr[k],sizeof(int)*a.column);//给每一行分配空间并拷贝
  76. }
  77. return *this;
  78. }
  79. int main() {
  80. Array2 a(3,4);
  81. int i,j;
  82. for( i = 0;i < 3; ++i )
  83. for( j = 0; j < 4; j ++ )
  84. a[i][j] = i * 4 + j;
  85. for( i = 0;i < 3; ++i ) {
  86. for( j = 0; j < 4; j ++ ) {
  87. cout << a(i,j) << ",";
  88. }
  89. cout << endl;
  90. }
  91. cout << "next" << endl;
  92. Array2 b;
  93. b = a;
  94. for( i = 0;i < 3; ++i ) {
  95. for( j = 0; j < 4; j ++ ) {
  96. cout << b[i][j] << ",";
  97. }
  98. cout << endl;
  99. }
  100. return 0;
  101. }

编程题#4:大整数的加减乘除

注意: 总时间限制: 1000ms 内存限制: 65536kB

描述

给出两个正整数以及四则运算操作符(+ - * /),求运算结果。

输入

第一行:正整数a,长度不超过100

第二行:四则运算符o,o是“+”,“-”,“*”,“/”中的某一个

第三行:正整数b,长度不超过100

保证输入不含多余的空格或其它字符

输出

一行:表达式“a o b”的值。

补充说明:

1. 减法结果有可能为负数

2. 除法结果向下取整

3. 输出符合日常书写习惯,不能有多余的0、空格或其它字符

样例输入

9876543210
+
9876543210

样例输出

19753086420
参考代码:
  1. /*
  2. * BigInt Calculation.cpp
  3. *
  4. * Created on: 2018年3月14日
  5. * Author: Arno
  6. */
  7. #include<cstdio>
  8. #include<cstring>
  9. using namespace std;
  10. class BigInt{
  11. int d[1000];//用作存储大整数的每一位数
  12. bool flag;//用作正负号
  13. int len;//大整数的数位长度
  14. public:
  15. BigInt(){
  16. memset(d,0,sizeof(d));
  17. flag=true;
  18. len=0;
  19. }//无参数时的构造函数
  20. BigInt(const char str[]);//有字符串参数的构造函数
  21. bool operator<(const BigInt & operand2);
  22. bool operator>(const BigInt & operand2);
  23. bool operator==(const BigInt & operand2);
  24. BigInt & operator=(const BigInt & operand);
  25. BigInt operator+(const BigInt & operand2);
  26. BigInt operator-(const BigInt & operand2);
  27. BigInt operator*(const BigInt & multiplier);
  28. BigInt operator/(const BigInt & divisor);
  29. void printBigInt();//打印大整数
  30. };
  31. BigInt::BigInt(const char str[]){
  32. flag=true;//由于输入的数据为正数,所以置为真
  33. len=strlen(str);//字符串长度即为数位长度
  34. for(int i=0;i<len;++i){
  35. d[i]=str[len-1-i]-'0';//逆着赋值,这样整数的低位存储在数组的低位
  36. }
  37. }
  38. bool BigInt::operator <(const BigInt & operand2){
  39. if(len<operand2.len)
  40. return true;//数的长度比后者小,则数小
  41. else if(len==operand2.len){
  42. for(int i=len-1;i>=0;--i){
  43. if(d[i]<operand2.d[i])
  44. return true;//从高位往低位比较,只要有一位小,则数小
  45. else if(d[i]>operand2.d[i])
  46. return false;
  47. }
  48. return false;//两数相等
  49. }else
  50. return false;//前面的数大
  51. }
  52. bool BigInt::operator >(const BigInt & operand2){
  53. if(len>operand2.len)
  54. return true;//数的长度比后者大,则数大
  55. else if(len==operand2.len){
  56. for(int i=len-1;i>=0;--i){
  57. if(d[i]>operand2.d[i])
  58. return true;//从高位往低位比较,只要有一位大,则数大
  59. else if(d[i]<operand2.d[i])
  60. return false;
  61. }
  62. return false;//两数相等
  63. }else
  64. return false;//前面的数小
  65. }
  66. bool BigInt::operator ==(const BigInt & operand2){
  67. if(len==operand2.len){
  68. for(int i=len-1;i>=0;--i){
  69. if(d[i]!=operand2.d[i])
  70. return false;//从高位往低位比较,只要有一位不等,则数不等
  71. }
  72. return true;//两数相等
  73. }else
  74. return false;
  75. }
  76. BigInt & BigInt::operator =(const BigInt & operand){
  77. if(operand.d==this->d)
  78. return *this;//防止a=a这样的情况
  79. this->len=operand.len;
  80. this->flag=operand.flag;
  81. for(int i=0;i<operand.len;++i){
  82. this->d[i]=operand.d[i];
  83. }
  84. return *this;
  85. }
  86. BigInt BigInt::operator +(const BigInt & operand2){
  87. BigInt result;
  88. int carry=0;//carry是进位
  89. for(int i=0;i<len||i<operand2.len;++i){//以较长的为界限
  90. int temp=carry+d[i]+operand2.d[i];//两个对应位与进位相加
  91. carry=temp/10;//去掉最后一位之后就是新的进位
  92. result.d[result.len++]=temp%10;//留下最后一位作为该位的结果
  93. }
  94. if(carry!=0)//若最后进位不为0,则直接赋给结果的最高位
  95. result.d[result.len++]=carry;
  96. return result;
  97. }
  98. BigInt BigInt::operator -(const BigInt & operand2){
  99. BigInt result;
  100. BigInt minuend;//被减数
  101. BigInt subtrahend;//减数
  102. if(*this<operand2){
  103. result.flag=false;
  104. minuend=operand2;
  105. subtrahend=*this;//如果被减数小于减数,则将结果置负并将两数对换
  106. }else{
  107. minuend=*this;
  108. subtrahend=operand2;
  109. }
  110. for(int i=0;i<minuend.len||i<subtrahend.len;++i){//以较长的为界限
  111. if(minuend.d[i]<subtrahend.d[i]){//如果不够减
  112. minuend.d[i+1]--;//向高位借位
  113. minuend.d[i]+=10;//当前位加10
  114. }
  115. result.d[result.len++]=minuend.d[i]-subtrahend.d[i];//减法结果为当前位结果
  116. }
  117. while(result.len-1>=1&&result.d[result.len-1]==0){
  118. result.len--;//去除高位的0,同时至少保留一位最低位
  119. }
  120. return result;
  121. }
  122. BigInt BigInt::operator *(const BigInt & multiplier){
  123. BigInt result;
  124. result.len=this->len+multiplier.len;//两数相乘乘积位数最大为两数位数之和
  125. for(int i=0;i<this->len;++i){
  126. for(int j=0;j<multiplier.len;++j){
  127. result.d[i+j]+=this->d[i]*multiplier.d[j];//关键算法,需要自己手动模拟一下
  128. result.d[i+j+1]+=result.d[i+j]/10;
  129. result.d[i+j]=result.d[i+j]%10;//简单来说就是a[i]*b[j]保存在c[i+j]上
  130. }
  131. }
  132. if(result.d[result.len-1]==0)
  133. result.len--;//两数相乘乘积位数最小为两数位数之和减掉1
  134. return result;
  135. }
  136. BigInt BigInt::operator /(const BigInt & divisor){
  137. BigInt quotient;//商
  138. BigInt remainder;//余数
  139. if(divisor.len==1&&divisor.d[0]==0){
  140. printf("除数不能为0!");
  141. return quotient;
  142. }
  143. if(*this<divisor){
  144. quotient.len=1;
  145. quotient.d[0]=0;//若除数比被除数大,则商为零
  146. }else{
  147. quotient.len=this->len-divisor.len +1;//商的位数最多为被除数位数减除数位数加1
  148. remainder.len=divisor.len-1;//给余数赋初值,取被除数的前“除数位数-1”位的数作为余数
  149. for(int i=remainder.len-1;i>=0;--i){
  150. remainder.d[i]=this->d[i+quotient.len];
  151. }//每一轮用余数去除除数,在该位上上一个商的值
  152. for(int i=quotient.len-1;i>=0;--i){//从商的高位开始
  153. remainder.len++;
  154. for(int j=remainder.len-1;j>0;--j){
  155. remainder.d[j]=remainder.d[j-1];
  156. }
  157. remainder.d[0]=this->d[i];//被除数当前的这位数和上一次遗留的余数组合
  158. if(remainder<divisor)
  159. quotient.d[i]=0;//若不够除,该位为0
  160. else{//够除
  161. int cnt=0;
  162. while(remainder>divisor||remainder==divisor){
  163. remainder=remainder-divisor;
  164. cnt++;
  165. }//够减几次,该位上商就是几,跳出循环时获得新的余数
  166. quotient.d[i]=cnt;
  167. }
  168. }
  169. if(quotient.d[quotient.len-1]==0)
  170. quotient.len--;//商的最高位若为0,则去掉
  171. }
  172. return quotient;
  173. }
  174. void BigInt::printBigInt(){
  175. if(flag==false)
  176. printf("-");
  177. for(int i=len-1;i>=0;--i){
  178. printf("%d",d[i]);
  179. }
  180. }
  181. int main(){
  182. char str1[1000];
  183. char op;
  184. char str2[1000];
  185. gets(str1);
  186. op=getchar();
  187. getchar();//吞掉回车符
  188. gets(str2);
  189. BigInt a(str1);
  190. BigInt b(str2);
  191. BigInt c;
  192. switch(op){
  193. case '+':c=a+b;break;
  194. case '-':c=a-b;break;
  195. case '*':c=a*b;break;
  196. case '/':c=a/b;break;
  197. default:break;
  198. }
  199. c.printBigInt();
  200. return 0;
  201. }
大整数我没用iostream,因为晴神宝典说cin和cout消耗的时间比scanf和printf多得多,为了效率我决定用C的输入输出试试手。在这里不得不吐槽一下,scanf果然不是那么好用的,主函数部分不知道为什么输入老是出问题,debug数次未果之后我给换成了gets和getchar才正常。还有一个收获就是,不断的WA之后浏览课程讨论区发现有人说POJ上可以看未通过的测试用例,更好地知道是哪里出了问题,于是去注册了一个,果然。这样以后debug的时候就会方便很多了。


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/806852
推荐阅读
相关标签