由于本人在学习算法时理论基础与编程能力过于不匹配(理论基础差,编程能力——没有),经常会犯各种各样脑残的错误,写出各种各样丑陋的代码(比我还丑),故开此长更博客,希望能帮到自己,也希望提醒大家不要犯类似错误,否则智商就会变成我这种水平。
最后更新: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这么多年的老玩家,我第一次感觉到玩够了……
没啥说的,请移步我的独立博文