2018《程序设计实习》错误集锦

      由于本人在学习算法时理论基础与编程能力过于不匹配(理论基础差,编程能力——没有),经常会犯各种各样脑残的错误,写出各种各样丑陋的代码(比我还丑),故开此长更博客,希望能帮到自己,也希望提醒大家不要犯类似错误,否则智商就会变成我这种水平。

        最后更新:04月05日

       1:C++ 变量名不能以数字开头    报错关键词:expecting unqualified … (此映射非单射,即还有其他原因也会这样报错)

       2:凡是出现不给定保留位数的浮点数输出要求,一律用cout,慢点就慢点。(%g的功能听说不只是舍去无用0那么简单)

       3:苹果

Apple Fun(const Apple & a) {
    	a.PrintTotal();
    	return a;//第二个数是5而不是6是因为此处返回时会二进制复制创建一个对象之后析构,不调用构造函数
    }

Apple(){cout<<"construct"<<endl;nTotalNumber++;}
	~Apple(){cout<<"destruct"<<endl;nTotalNumber--;}//改一下代码跑一下就能看出来
construct
construct
construct
construct
4
destruct
construct
construct
5
destruct
destruct
destruct
destruct
1
destruct
destruct


4:Big and Base

Big(int n): b(n),v(n) {}
Big(const Big &a): b(a.b.k),v(a.v) {} //一个类的对象作为另一个的成员变量,务必使用列表式初始化

5:奇怪的构造函数

int main()
    {
        Sample a(5);//转换
    //cout<<a.v<<endl;
        Sample b = a;//复制
    //cout<<b.v<<endl;
        PrintAndDouble(b);//在这里还使用了一次复制构造函数
        Sample c = 20;//转换
        PrintAndDouble(c);//复制
        Sample d;
        d = a;//什么也没调用,直接二进制复制
        cout << d.v;
        return 0;
    }

6:MyString

MyString(const MyString &a){//务必深拷贝,否则会出现神秘的内存泄漏
	if(a.p){
		p = new char[strlen(a.p)+1];
		strcpy(p,a.p);
	}else
		p = NULL;
}
MyString &operator = (const MyString &a){//这里也是,务必深拷贝
        if(p) delete [] p;
        if(a.p == NULL) p = NULL;
        else{
            p = new char[strlen(a.p) + 1];
            strcpy(p,a.p);
        }
 }//总而言之,出现了指针,迅速写好深拷贝的复制构造函数以及等号的重载,别自己到草纸上猜指针都指到哪里。我替你猜了,它们指向了远方。
friend ostream &operator << (ostream &s, const MyString &a){
        s<<a.p;
        return s;
    }//流运算符必须记为友元函数

7:神秘的输出

    #include <iostream>
    using namespace std;
    class A {
    public:
    	int val;

    	A(int a) {this->val = a;}
	A &GetObj(){
		return *this;
	}
	A(){this->val = 123;}
    };
    int main()
    {
    	int m,n;
    	A a;
    	cout << a.val << endl;
    	while(cin >> m >> n) {
    		a.GetObj() = m;
    		cout << a.val << endl;
    		a.GetObj() = A(n);//总结:凡是出现神秘的给一个函数赋值,通常都是返回了一个引用。(神秘啊)
    		cout << a.val<< endl;
    	}
    	return 0;
    }

8:重载加号
include <iostream> 
    using namespace std;
    class MyInt 
    { 
    	int nVal; 
    	public: 
    	MyInt( int n) { cout<<"num_construct"<<endl;nVal = n ;}
	MyInt( const MyInt &source) {cout<<"copy_construct"<<endl; this->nVal = source.nVal;}
	operator int() const{ return nVal; }
	MyInt &operator - (const int &a){
		nVal -= a;
		return *this;
	}
    }; 
    int Inc(int n) {
    	return n + 1;
    }
    int main () { 
    	int n;
    	while(cin >>n) {
    		MyInt objInt(n); 
    		objInt-2-1-3; 
    		cout << Inc(objInt);
    		cout <<","; 
    		objInt-2-1; 
    		cout << Inc(objInt) << endl;
    	}
    	return 0;
    }//重载运算符,如果想修改调用它的函数,同时还想连加连减,就务必返回个引用。我把源码改了改,就能更好地看出连加连减时的工作细节。20
-----------------------------这是加了引用的输出---------------------------
num_construct
15,12
-----------------------------这是没加引用的输出---------------------------
20
num_construct
copy_construct
copy_construct
copy_construct
19,copy_construct
copy_construct
17


9:BigInt

    #include <iostream> 
    #include <cstring> 
    #include <cstdlib> 
    #include <cstdio> 
    using namespace std;
    const int MAX = 110; 
    class CHugeInt {
	public:
		int len;
		char *p;
		CHugeInt(){p=NULL;}
		CHugeInt(const char* s){
			this->len = strlen(s);
			p = new char[this->len];
			for(int i=0; i<this->len; i++){
				*(p+i) = *(s+len-i-1);
			}
			*(p+len) = '\0';//可要注意类型转换构造函数里已经完成了翻转
		}
		CHugeInt(const int &n){
			char tmp[100];
			sprintf(tmp,"%d",n);
			this->len = strlen(tmp);
			p = new char[this->len];
			for(int i=0; i<this->len; i++){
				*(p+i) = tmp[len-i-1];
			}
			*(p+len) = '\0';//可要注意类型转换构造函数里已经完成了翻转
		}
		CHugeInt(const CHugeInt &a){
			this->len = a.len;
			p = new char[this->len];
			for(int i=0; i<this->len; i++){
				*(p+i) = *(a.p+i);
			}
			*(p+len) = '\0';
		} 
		~CHugeInt(){
			delete []p;
			p = NULL;
		}
		int min(const CHugeInt &b){
			if(this->len < b.len) return this->len;
			else return b.len;
		}
		int max(const CHugeInt &b){
			if(this->len > b.len) return this->len;
			else return b.len;
		}
		CHugeInt operator + (const CHugeInt &a){
			int tmp[220];
			char temp[220];
			int tmpl;
			memset(tmp,0,sizeof(tmp));
			for(int i=0; i<min(a); i++){
				tmp[i] += (int) ((this->p[i]) + a.p[i] - 2 * '0'); 
				tmp[i+1] += tmp[i] / 10;
				tmp[i] = tmp[i] % 10;
			}
			if(min(a)==this->len){
				for(int i=this->len; i<a.len; i++){
					tmp[i] += (int)(a.p[i] - '0');
					tmp[i+1] += tmp[i] / 10;
					tmp[i] = tmp[i] % 10;
				}
			}else{
				for(int i=a.len; i<this->len; i++){
					tmp[i] += (int)(this->p[i] - '0');
					tmp[i+1] = tmp[i] / 10;
					tmp[i] = tmp[i] % 10;
				}
			}
			if(tmp[max(a)] == 0) tmpl = max(a);
			else tmpl = max(a) + 1;
			for(int i=0; i<tmpl; i++) temp[i] = (char)tmp[tmpl-i-1] + '0';
			temp[tmpl] = '\0';
			CHugeInt ret(temp);
			return ret;
		}
		CHugeInt &operator = (const CHugeInt &a){
			if(this->p) delete []this->p;
			this->len = a.len;
			p = new char[a.len];
			for(int i=0;i<this->len;i++) this->p[i] = a.p[i];
			*(p+len) = '\0';
			return *this;
		}
		friend ostream &operator << (ostream &s, CHugeInt a){
			char tmp[220];
			for(int i=0;i<a.len;i++)
				tmp[i] = a.p[a.len-i-1];
			tmp[a.len]='\0';//凡是后面出乱码的都是没加‘\0';
			s<<tmp;
			return s;
		} 
		friend CHugeInt operator + (const int &n, const CHugeInt &a){
			CHugeInt ret = CHugeInt(n) + a;
			return ret;
		} 
		CHugeInt operator + (const int &n){
			CHugeInt ret = CHugeInt(n) + *this;
			return ret;
		}
		CHugeInt &operator += (const int &n){
			CHugeInt ret = *this + n;
			*this = ret;
			return *this;
		}
		CHugeInt &operator ++ (){
			*this = *this + 1;
			return *this;
		}
		CHugeInt operator ++ (int rub){//传回局部变量pre时千万不能用引用,一定要深拷贝后返回这些值,因为传回的引用所指向的那个位置在函数运行结束后就被释放掉了
			CHugeInt pre(*this);
			*this = *this + 1;
			return pre;
		} 
    };
    int  main() 
    { 
    	char s[210];
    	int n;

    	while (cin >> s >> n) {
    		CHugeInt a(s);
    		CHugeInt b(n);
    		cout << a + b << endl;
		cout << n + a << endl;
		cout << a + n << endl;
		b += n;
		cout  << ++ b << endl;
		cout << b++ << endl;
		cout << b << endl;
    	}
    	return 0;
    }//有一个要点:想给指针做一些变动的话,一定要注意是不是需要先清空原先指向的东西。
    //牢记指针四部曲:delete掉原来的空间,指向NULL,申请新空间,指向新空间。要注意指针被Delete之后还会指向被释放的空间,这种指针叫野指针,在析构的时候会发生段错误(Segment Fault)
    //所以在delete空间之后一定要指针一定要纪律性指向NULL,不管之后要不要赋值,这是个好习惯。还有,这题的加号重载有点多,其实只要重载好对象+对象,剩下的套用一下就好了。注意一下构造函数的细节。



3月23日

手写string类:有了前一次大整数的基础,这次就顺利很多了。

    #include <cstdlib>
    #include <iostream>
    using namespace std;
    int strlen(const char * s)
    {	int i = 0;
    	for(; s[i]; ++i);
    	return i;
    }
    void strcpy(char * d,const char * s)
    {
    	int i = 0;
    	for( i = 0; s[i]; ++i)
    		d[i] = s[i];
    	d[i] = 0;

    }
    int strcmp(const char * s1,const char * s2)
    {
    	for(int i = 0; s1[i] && s2[i] ; ++i) {
    		if( s1[i] < s2[i] )
    			return -1;
    		else if( s1[i] > s2[i])
    			return 1;
    	}
    	return 0;
    }
    void strcat(char * d,const char * s)
    {
    	int len = strlen(d);
    	strcpy(d+len,s);
    }
    class MyString
   {
    private:
    	char *p;
    	int l;
    public:
    	char *sub;
    	int lsub;
    	void init(){
    		if(l!=0) delete []p;//如果之前没手动让p指向什么乱七八糟的东西,就不要调用这个函数。如果简单地问p是否指向空指针,在第一次使用p时会报错。
    		p = NULL;
    		l = 0;
    	}
    	MyString(){
    		p = NULL;
    		sub = NULL;
    		l = 0;
    		lsub = 0;
    	}
    	MyString(const char *s){
    		p = NULL;
    		sub = NULL;
    		l = 0;
    		lsub = 0;
    		this->l = strlen(s);
    		if(this->l!=0){
    			this->p = new char(this->l+1);
    			for(int i=0;i<this->l;i++) *(this->p+i) = *(s+i);
    			*(this->p+l) = '\0'; //very important
    		}
    	}
    	MyString(const MyString &a){
    		p = NULL;
    		sub = NULL;
    		l = 0;
    		lsub = 0;
    		this->l = a.l;
    		if(this->l!=0){
    			this->p = new char(this->l+1);
    			for(int i=0;i<this->l;i++) *(this->p+i) = *(a.p+i);
    			*(this->p+l) = '\0';
    		}
    	}
    	~MyString(){
    		init();
    	}
    	MyString &operator = (const MyString &a){//必须有返回值。等号的显式表达尚待探讨
    		init();
    		this->l = a.l;
    		if(this->l!=0){
    			this->p = new char(this->l+1);
    			for(int i=0;i<this->l;i++) *(this->p+i) = *(a.p+i);
    			*(this->p+l) = '\0';
    		}
    		return *this;
    	}
    	friend ostream &operator << (ostream &s, MyString &tmp){
    		if(tmp.p==NULL) s<<"";//非常重要,否则流会间断
    		else s<<tmp.p;
    		return s;
    	}
    	friend MyString operator + (const MyString &a, const MyString &b){
    		MyString ret;
    		ret.l = a.l + b.l;
    		if(ret.l!=0) ret.p = new char(ret.l+1);
    		for(int i=0;i<a.l;i++) *(ret.p+i) = *(a.p+i);
    		for(int i=0;i<b.l;i++) *(ret.p+a.l+i) = *(b.p+i);
    		*(ret.p+ret.l) = '\0';
    		return ret;
    	}
    	char &operator [] (int idx){
    		return *(this->p+idx);
    	}
    	MyString &operator += (const MyString &a){
    		*(this) = *(this) + a;
    		return *(this);
    	}
    	friend MyString operator + (const char *s, const MyString &a){
    		MyString ret(s);
    		ret = ret + a;
    		return ret;
    	}
    	friend MyString operator + (const MyString &a, const char *s){
    		MyString ret(s);
    	    ret = a + ret;
    		return ret;
    	}
    	friend bool operator == (const MyString &a, const MyString &b){
    		int tmp = strcmp(a.p, b.p);
    		if(tmp==0) return true;
    		else return false;
    	}
    	friend bool operator < (const MyString &a, const MyString &b){
    		int tmp = strcmp(a.p, b.p);
    		if(tmp==-1) return true;
    		else return false;
    	}
    	friend bool operator > (const MyString &a, const MyString &b){
    		int tmp = strcmp(a.p, b.p);
    		if(tmp==1) return true;
    		else return false;
    	}
    	char *operator () (const int s_idx, const int s_len){//传整数的过程是什么样的呢
    		if(lsub!=0){
    			lsub = 0;
    			sub = NULL;
    		}
    		lsub = s_len;
    		sub = new char(lsub+1);
    		for(int i=0;i<lsub;i++)
    			*(sub+i) = *(p+s_idx+i);
    		*(sub+lsub) = '\0';
    		return sub;
    	}
    };


    int CompareString( const void * e1, const void * e2)
    {
    	MyString * s1 = (MyString * ) e1;
    	MyString * s2 = (MyString * ) e2;
    	if( * s1 < *s2 )
    	return -1;
    	else if( *s1 == *s2)
    	return 0;
    	else if( *s1 > *s2 )
    	return 1;
    }
    int main()
    {
    	MyString s1("abcd-"),s2,s3("efgh-"),s4(s1);
    	MyString SArray[4] = {"big","me","about","take"};
    	cout << "1. " << s1 << s2 << s3<< s4<< endl;
    	s4 = s3;
        s3 = s1 + s3;
    	cout << "2. " << s1 << endl;
    	cout << "3. " << s2 << endl;
    	cout << "4. " << s3 << endl;
    	cout << "5. " << s4 << endl;
    	cout << "6. " << s1[2] << endl;
    	s2 = s1;
    	s1 = "ijkl-";
    	s1[2] = 'A' ;
    	cout << "7. " << s2 << endl;
    	cout << "8. " << s1 << endl;
    	s1 += "mnop";
    	cout << "9. " << s1 << endl;
    	s4 = "qrst-" + s2;
    	cout << "10. " << s4 << endl;
    	s1 = s2 + s4 + " uvw " + "xyz";
    	cout << "11. " << s1 << endl;
    	qsort(SArray,4,sizeof(MyString),CompareString);
    	for( int i = 0;i < 4;i ++ )
    	cout << SArray[i] << endl;
    	//s1的从下标0开始长度为4的子串
    	cout << s1(0,4) << endl;
    	//s1的从下标5开始长度为10的子串
    	cout << s1(5,10) << endl;
    	return 0;
    }

4月5日

在清明的早晨的03:22,我终于肝完了魔兽……作为War3这么多年的老玩家,我第一次感觉到玩够了……

没啥说的,请移步我的独立博文

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值