Effective C++ Item 12: Prefer initialization to assignment in constructors

When you write the NamedPtr constructor, you have to transfer the values of the parameters to the corresponding
data members. There are two ways to do this. The first is to use the member initialization list:

template<class T>
NamedPtr<t>::NamedPtr(const string& initName, T *initPtr )
: name(initName), ptr(initPtr)
{}

The second is to make assignments in the constructor body:

template<class T>
NamedPtr<t>::NamedPtr(const string& initName, T *initPtr)
{
    name = initName;
    ptr = initPtr;
}

There are important differences between these two approaches.
From a purely pragmatic point of view, there are times when the initialization list must be used. In particular,
const and reference members may only be initialized, never assigned. So, if you decided that a NamedPtr
object could never change its name or its pointer, you might follow the advice of Item 21 and declare the
members const:

template<class T>
class NamedPtr {
public:
    NamedPtr(const string& initName, T *initPtr);
...
private:
    const string name;
    T * const ptr;
};

This class definition requires that you use a member initialization list, because const members may only be
initialized, never assigned.
You’d obtain very different behavior if you decided that a NamedPtr object should contain a reference to an
existing name. Even so, you’d still have to initialize the reference on your constructors’ member initialization
lists. Of course, you could also combine the two, yielding NamedPtr objects with read-only access to names
that might be modified outside the class:

template<class T>
class NamedPtr {
public:
    NamedPtr(const string& initName, T *initPtr);
...
private:
    const string& name; // must be initialized via
    // initializer list
    T * const ptr; // must be initialized via
    // initializer list
};

The original class template, however, contains no const or reference members. Even so, using a member
initialization list is still preferable to performing assignments inside the constructor. This time the reason is
efficiency. When a member initialization list is used, only a single string member function is called. When
assignment inside the constructor is used, two are called. To understand why, consider what happens when you
declare a NamedPtr object.
Construction of objects proceeds in two phases:
1. Initialization of data members. (See also Item 13.)
2. Execution of the body of the constructor that was called.
(For objects with base classes, base class member initialization and constructor body execution occurs prior to
that for derived classes.)

Overload the Logical Operators to Sort Strings Alphabetically

Overload the Logical Operators to Sort Strings Alphabetically

In c++, we have function like strcmp(const char* c1,const char* c2) to help us decide which is alphabetically before the other. Yet we still want to use a more easy-going function as a bool operator < or something else like other logical operators.

And here we have a customized user-define class String, which is incomplete due this is only for demonstration of overloading operators.

#include <iostream>
#include <iomanip>
using namespace std;

class String{

	char* chars;

public:

	int length;

	String String::operator =(const char* r){
		length=strlen(r);
		chars=(char*)malloc((length+1)*sizeof(char));
		for(int i=0;i<=length;i++){
			this->chars[i]=r[i];
		}
		return *this;
	}

	String String::operator =(String r){
		length=r.length;
		chars=(char*)malloc((length+1)*sizeof(char));
		for(int i=0;i<=length;i++){
			this->chars[i]=r[i];
		}
		return *this;
	}

	char &String::operator [](int idx){
		return chars[idx];
	}

	bool operator <(String r)
	{
		for(int idx=0;idx<=(length<r.length?length:r.length);idx++)
		{
			if(tolower(chars[idx])<tolower(r[idx]))
				return true;
			else
				if(tolower(chars[idx])>tolower(r[idx]))
					return false;
				else
					continue;
		}
		return false;
	}

	bool operator >(String r)
	{
		return r<*this;
	}

	bool operator ==(String r)
	{
		return !(*this>r)&&!(*this<r);
	}

	bool operator !=(String r)
	{
		return !(*this==r);
	}

	bool operator <=(String r)
	{
		return !(*this>r);
	}

	bool operator >=(String r)
	{
		return !(*this<r);
	}

	friend ostream&operator <<(ostream &os,String &right);

	friend istream&operator <<(istream &is,String &right);

	String(int n){
		length=n;
		chars=new char[length];
	}

	String (){
		length=0;
	}

	String (const char* cs){
		*this=cs;
	}

};

ostream & operator<<(ostream &os,  String &right)
{
	for(int i=0;i<=right.length;i++)
	{
		os<<right[i];
	}

	return os;
}

istream & operator>>(istream &is,String &right)
{
	int idx=2;
	char* tmpcs=new char[idx];
	char c;
	int i=0;
	for(;;i++)
	{
		c=is.get();
		if(c!='n')
		{
			if(i>=idx)
			{
				idx=i+1;
				tmpcs=(char*)realloc(tmpcs,idx*sizeof(char));
			}
			if(isalpha(c))
			{
				tmpcs[i]=c;
			}

		}
		else
		{
			if(i>=idx)
			{
				idx=i+1;
				tmpcs=(char*)realloc(tmpcs,idx*sizeof(char));
			}
			tmpcs[i]='';
			break;
		}
	}
	right=tmpcs;
	return is;

}

template <typename T>
void sort(T *source,int startidx,int endidx)
{
	for(int i=startidx+1;i<=endidx;i++)
	{
		for(int j=startidx;j<i;j++)
		{
			if(source[i]<source[j])
			{
				T key=source[i];
				for(int k=i;k>j;k--)
				{
					source[k]=source[k-1];
				}
				source[j]=key;
				break;
			}
		}
	}
}
int main()
{
	String group[5];

	cout<<"Please input 5 words"<<endl;
	for(int i=0;i<5;i++)
	{
		cin>>group[i];
	}
	sort(group,0,4);
	cout<<"after the sorting"<<endl;
	for(int i=0;i<5;i++)
	{
		cout<<group[i]<<endl;
	}
	system("pause");
	return 0;
}

Microsoft Excel Add-In Updated

Today I got this small add-in updated.
Add-in page at APP Page

This update including several main changes as following:

1, Change UI from Office Ribbon to Windows Form which is more organized.

2, Title insertion adds a new function and now users can get the range by a simple click rather than brain taken inputs.

3, Adds a function that can compare data in two ranges.

Get Excel Selected Range via VSTO with C#

These days I have been working on the development of an Excel Add-in and learnt a way to get the currently selected range in Excel.
Take it for example that your Project namespace is ExcelAddIn. Firstly, you should refer the interop by following code:

using Microsoft.Office.Interop.Excel;

and you can get a string consistent with the Range you selected by following code:

ExcelAddIn.Globals.ThisAddIn.Application.Selection.Address;

which would return a string in format like “$A$1:$B$2″ for rectangles,”$1:$2” for rows and “$A:$B” for columns.

Dynamic Pointer and Dynamic Memory Allocation in C++

Days ago a mate asked me a favor in his code and I got trouble in dynamic pointer and dynamic memory allocation.
Well, one-dimensional pointer is easy to use, and you can easily expand it’s occupied memory size by using realloc() as following:

#include <iostream>
using namespace std;
int n=2,* pint;
void Initialization()
{
	pint=new int[n];
}
void DoSomething(){}
int main()
{
	Initialization();
	DoSomething();
	pint=(int*)realloc(pint,(++n)*sizeof(int));
	pint[n-1]=123456;
	cout<<pint[n-1]<<endl;
	return 0;
}
</pre>
But when it comes to the two-dimensional pointer, it nolonger works if you write some code like this:
<pre lang="cpp" line="1" file="code2.cpp" colla="+">
#include <iostream>
using namespace std;
int n=2,len=20;
char** ppchar;
void Initialization(){
	ppchar=new char*[n];
	for(int i=0;i<n;i++){
		ppchar[i]=new char[len];
	}
}
void DoSomething(){}
int main()
{
	Initialization();
	DoSomething();
	ppchar=(char**)realloc(ppchar,(++n)*len*sizeof(char));
	ppchar[n-1]="this is a new one";
	cout<<ppchar[n-1]<<endl;
	return 0;
}

That is because you failed to notify the system, or in other words declare the address of ppchar[n-1].
And here is a correct version of the same function by adding a statement between line 16 and 17:

ppchar[n-1]=new char[len];

Calculate the Determinant of A Square Matrix

This is a code that I wrote weeks ago, mainly to calculate the determinant of a squae matrix.

It’s written in c++. Enjoy it!

 #include <iostream>
using namespace std;
template<typename T>
class Matrix{
	T **m;
	int n;
	void rot90(){
		T ** tmp=new T*[n];
		for(int i=0;i<n;i++){
			tmp[i]=new T[n];
			for(int j=0;j<n;j++){
				tmp[i][j]=m[i][j];
			}
		}
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				m[i][j]=tmp[n-1-j][i];
			}
		}
	}
	Matrix<t> M(int i,int j){//get the matrix corresponds with specific minor Mij
		Matrix<t> TMP(n-1);
		for(int a=0;a<n-1;a++){
			for(int b=0;b<n-1;b++){
				int c=0,d=0;
				if(a<i) c=a;
				else c=a+1;
				if(b<j) d=b;
				else d=b+1;
				TMP.m[a][b]=m[c][d];
			}
		}
		return TMP;
	}
	T C(int i,int j){//get cofactor Cij
		if((i+j)%2==0) return M(i,j).Det();
		else return -1*M(i,j).Det();
	}
	T A(int i,int j){
		return m[i][j]*C(i,j);
	}
public :

	Matrix(int para){
		n=para;
		m=new T*[n];
		for(int i=0;i<n;i++){
			m[i]=new T[n];
			for(int j=0;j<n;j++) m[i][j]=0;
		}
	}
	Matrix(){
		int itmp=0;
		do{
			cout<<"Please input the square matrix's  n, and n has to be larger than 1"<<endl;
			cin>>itmp;
		}
		while(itmp<2);
		n=itmp;
		m=new T*[n];
		for(int i=0;i<n;i++){
			m[i]=new T[n];
			for(int j=0;j<n;j++) m[i][j]=0;
		}
	}
	void Input(){
		cout<<"Please initialize the matrix"<<endl;
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++) cin>>m[i][j];
		}
		cout<<"Initialization done"<<endl;
	}
	void Display(){
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				cout<<m[i][j];
				if(j!=n-1) cout<<" ";
			}
			cout<<endl;
		}
	}
	void Display(int w){
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				cout<<setw(w)<<m[i][j];
			}
			cout<<endl;
		}
	}
	void Display(int i,int j){
		cout<<m[i][j]<<endl;
	}
	void Rotation(int times=1){
		for(;times>3;times-=4){}
		for(;times<0;times+=4){}
		if(times!=0){
			if(times==1) rot90();
			else{
				rot90();
				Rotation(times-1);
			}
		}
	}
	T Det(){
		if(n==2) return m[0][0]*m[1][1]-m[0][1]*m[1][0];
		else{
			T sum=0;
			for(int i=0;i<n;i++) sum+=A(0,i);
			return sum;
		}
	}
}; 

Find the Perfect Number

First of all, we have the conclusion from Euclid that define an integer n, and if 2^n – 1 is a prime, the number 2^(n-1)*(2^n – 1) must be a Perfect Number.

Here follows my source code on finding 5 the smallest Perfect Number.It’s written by C++.

using namespace std;
bool IsPrime (long long s)
{
	for(long long i=2;i<sqrt((long double)s);i++)
	{
		if(s%i==0) return false;
	}
	return true;
}
long long Power(int n)
{
	if(n!=0) return 2*Power(n-1);
	else return 1;
}
int main()
{
	int cnt=0;
	for(int i=2;cnt<9;i++)
	{
		if(IsPrime(Power(i)-1)) cout<<++cnt<<") "<<power(i-1)*(Power(i)-1)<<endl;
	}
	return 0;
}