Thursday 6 August 2020

Install Ubuntu 20.04 in Hyper-v

Install Hyper-V on Windows 10: 

https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/quick-start/enable-hyper-v 

Select Turn Windows Features on or off
Select Hyper-V and click OK
Windows programs and features dialogue box
Restart PC. During restart, RDP might lose connection.

Create Virutal Switch:

In external network, choose the physical ethernet network driver
"realtek pcie gbe family controller"

Establish Ubuntu VM:

Image download link: 
https://releases.ubuntu.com/20.04/ubuntu-20.04-live-server-amd64.iso


Setup Static IP address:
Subnet: 172.19.11.0/24
IP address: 172.19.11.91
Gateway: 172.19.11.1
Nameservers: 172.16.100.100
Domain: can leave as empty

This is how to setup static IP in Ubuntu
# vim 50-cloud-init.yaml
network:
    ethernets:
        eth0:
            addresses:
            - 172.19.11.XXX/24
            gateway4: 172.19.11.1
            nameservers:
                addresses:
                - 172.16.100.100
    version: 2



Tuesday 21 July 2020

Convert Time from MySQL, Angular(cli), and Go(srv)

Convert time zone in MySQL, Angular, and Go
MySQL:

#SELECT userTimezone FROM USER_PREFERENCE WHERE uid = 1;

SELECT
UploadFileID
, UserID
, Filename AS OrigFilename
, CONCAT(Filename, ' <=== this is my filename') AS Filename
, FilenameHashed
#, CreateTime AS OrigCreateTime
, CONCAT(CreateTime + INTERVAL +8 HOUR, ' UTC') AS CreateTime
FROM UploadFile
ORDER BY UploadFileID DESC
Angular(Client side): Do it in display side. Convert rawdata is usually not a good practice.

export class MyruleUploadGridComponent implements OnInit {
    // Global variables
    private gridApi;
    private gridColumnApi;

    public columnDefs = [
        {
            field: 'UploadFileID',
            headerName: 'UploadFileID',
            sortable: true,
            sortingOrder: ['asc', 'desc'],
            headerTooltip: 'asdf',
        },
        {
            field: 'UserID',
            headerName: 'UserID',
        },
        {
            field: 'Filename',
            headerName: 'Filename',
        },
        {
            field: 'CreateTime',
            headerName: 'CreateTime',
            cellRenderer: (params) => {
                return new DatePipe('en-Us').transform(params.value + ' UTC', 'short', 'locale')
            },
        },
    ];
}
Go(backend):
Method1:

var t time.Time
if t, err = TimeIn(colDef.CreateTime, "Canada/Pacific"); err != nil {
 fmt.Printf("err: %v\n", err)
}

colDef.CreateTime = t.String()

func TimeIn(inputTime string, name string) (time.Time, error) {
 var t time.Time
 var err error
 layout := "2006-01-02 15:04:05"
 if t, err = time.Parse(layout, inputTime); err != nil {
  fmt.Printf("err:%v\n", err)
 }
 loc, err := time.LoadLocation(name)
 if err == nil {
  t = t.In(loc)
 }
 return t, err
}
Method2:

package main

import (
 "fmt"
 "time"
)

func main() {

 d1 := "2020-07-29 21:47:11"
 newT1 := AddHour(d1, 51)
 fmt.Printf("Adding 1 hour\n: %s\n", newT1)
}

func AddHour(d string, numOfHour int) time.Time {
 t, _ := ConvStrToTime(d)

 newT := t.Add(time.Hour * time.Duration(numOfHour))
 return newT
}

func ConvStrToTime(str string) (time.Time, error) {
 layout := "2006-01-02 15:04:05" // Mon Jan 2 15:04:05 -0700 MST 2006
 return time.Parse(layout, str)
}

Wednesday 20 February 2019

How to solve Xampp MySQL Error # 2002 - No connection could be made because the target machine actively refused it

1. Go to the data folder of MySQL

To solve this problem, you need to locate the mysql folder in your xampp installation. This is usually just one version, so you may find it (with a default installation path) in C:\xampp\mysql\data. This folder contains mainly logs and all the databases on MySQL.

2. Backup Log files and delete them

Create a copy of the log files of mysql, namely the files ib_logfile0 and ib_logfile1. These files are log files created during the runtime for InnoDB. Normally, removing them will solve your issue as they will be created later, however create a security copy of those files somewhere else, so in case that it doesn't work, you can still restore them and leaving xampp as it was from the beginning.
Once you have a copy of those files somewhere else (other directory), delete them from the original directory and proceed with the next step.

3. Restart MySQL and Apache

As final step restart the MySQL and Apache services in case they are running with the xampp control panel. After restarting those services, try to access again PHPMyAdmin at the URL http://localhost/phpmyadmin and you should be able to use PHPMyAdmin again.

Wednesday 6 February 2019

C++ Function Overloading

#include <iostream>
using namespace std;
class CStudent {
public: int nAge;
};
ostream&operator<<(ostream& o, const CStudent &s) {
 o << s.nAge;
 return o;
}
int main() {
 CStudent s;
 s.nAge = 5;
 cout << s << "hello";
 return 0; 
}
 — — — — — — — — — 
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
class Complex {
 double real, image;
public:
 Complex(double r = 0, double i= 0) :real(r), image(i) {};
 friend ostream & operator<<(ostream & os, const Complex&c);
 friend istream & operator>>(istream & is, Complex&c);
};
ostream & operator<<(ostream & os, const Complex & c) {
 os << c.real << "+" << c.image << "i";
 return os;
}
istream & operator>>(istream & is, Complex & c) {
 string s;
 is >> s;
 int pos = s.find("+", 0);
 string sTmp = s.substr(0, pos);
 c.real = atof(sTmp.c_str());
 sTmp = s.substr(pos + 1, s.length() - pos - 2);
 c.image = atof(sTmp.c_str());
 return is;
}
int main() {
 Complex c;
 int n;
 cin >> c >> n;
 cout << c << "," << n;
 return 0; 
}

String &String::operator = (const String & s) {
 if (str == str.str) return *this;
 if (str) delete[]str;
 if(s.str){
  str = new char[strlen(s.str) + 1];
  strcpy(str, s.str);
 }
 else
  str = NULL;
 return *this;
}
为了避免两个指针指向同一string,重复释放内存的问题,我们用strcpy。
复制构造函数也一样
String::String(String & s) {
 if (s.str) {
  str = new char[strlen(s.str) + 1];
  strcpy(str, s.str);
 }
 else
  str = NULL;
}

C++ Adjustable Length Array

#include <iostream>
using namespace std;
class CArray {
 int size; //数组元素的个数
 int *ptr; //指向动态分配的数组
public:
 CArray(int s = 0); //s代表数组元素的个数
 CArray(CArray&a);
 ~CArray();
 void push_back(int v); //用于在数组尾部添加一个元素v
 CArray&operator=(const CArray&a);
 //用于数组对象间的赋值
 int length() { return size; } //返回数组元素个数
 int& CArray::operator[](int i) {
  //用以支持根据下标访问数组元素,如n=a[i]和a[i]=4;
  return ptr[i]; //非引用的返回值不可以作为左值使用,所以这里用 int& 引用
 }
};
CArray::CArray(int s) :size(s) {
 if (s == 0)
  ptr = NULL;
 else
  ptr = new int[s];
}
CArray::CArray(CArray &a) {
 if (!a.ptr) {
  ptr = NULL;
  size = 0;
  return;
 }
 ptr = new int[a.size];
 memcpy(ptr, a.ptr, sizeof(int)*a.size);
 size = a.size;
}
CArray::~CArray() {
 if (ptr) delete[]ptr;
}
CArray&CArray::operator=(const CArray&a) {
 if (ptr == a.ptr) //防止a=a这样的赋值导致错误
  return *this;
 if (a.ptr == NULL) {
  if (ptr) delete[]ptr;
  ptr = NULL;
  size = 0;
  return *this;
 }
 if (size < a.size) {//如果原有空间够大,就不用分配新空间
  if (ptr)
   delete[]ptr;
  ptr = new int[a.size];
 }
 memcpy(ptr, a.ptr, sizeof(int)*a.size);
 size = a.size;
 return *this;
}
void CArray::push_back(int v) {
 if (ptr) {
  int *tmpPtr = new int[size + 1];
  memcpy(tmpPtr, ptr, sizeof(int)*size);
  delete[]ptr;
  ptr = tmpPtr;
 }
 else
  ptr = new int[1];
 ptr[size++] = v;
}
int main() { //要编写可变长整型数组类,使之能如下使用:
 CArray a; //开始的数组是空的
 for (int i = 0; i < 5; ++i)
  a.push_back(i); //要用动态分配的内存来存放数组元素,需要一个指针成员变量
 CArray a2, a3;
 a2 = a; //重载运算符“="
 for (int i = 0; i < a.length(); ++i)
  cout << a2[i] << " ";
 a2 = a3; //a2是空的
 for (int i = 0; i < a2.length(); ++i)//a2.length()返回()
  cout << a2[i] << " "; //重载运算符“[]”
 cout << endl;
 a[3] = 100;
 CArray a4(a);
 for (int i = 0; i < a4.length(); i++)
  cout << a4[i] << " ";
 return 0; 
}

C++ drived Class

派生类引用:
class CStudent {
private: 
 string sName; 
 int nAge; 
public: bool IsThreeGood() { }; 
  void SetName(const string & name) { sName = name; } 
};
class CUndergraduateStudent: public CStudent { 
private: 
 int nDepartment; 
public: 
 bool IsThreeGood() {}; //覆盖
 bool CanBaoYan() {}; 
};
// 派生类的写法是:类名: public 基类名
派生类拥有基类的全部成员函数和成员变量,不论是private、protected、public.
在派生类的各个成员函数中,不能访问基类中的private成员。
派生类对象的体积,等于基类对象的体积,再加上派生类对象自己的成员变量的体积。在派生类对象中,包含着基类对象,而且基类对象的存储位置位于派生类对象新增的成员变量之前。
#include <iostream>
#include <string>
using namespace std;
class CStudent {
private:
 string name;
 string id;
 char gender;
 int age;
public:
 void PrintInfo();
 void SetInfor(const string&name_, const string &id_, int age_, char gender_);
 string GetName() { return name; }
};
class CUndergraduateStudent :public CStudent {
//本科生类,继承了CStudent类
private:
 string department; //学生所属的系的名字
public:
 void QualifiedForBaoYan() { //给予保研资格
  cout << "qualified for baoyan" << endl;
 }
 void PrintInfo() {
  CStudent::PrintInfo();//调用基类的PrintInfo
  cout << "Department:" << department << endl;
 }
 void SetInfor(const string&name_, const string&id_, int age_, char gender_, const string & deparment_) {
  CStudent::SetInfor(name_, id_, age_, gender_);//调用基类的SetInfo
  department = deparment_;
 }
};
void CStudent::PrintInfo() {
 cout << "Name:" << name << endl;
 cout << "ID" << id << endl;
 cout << "Age:" << age << endl;
 cout << "Gender:" << gender << endl;
}
void CStudent::SetInfor(const string&name_, const string & id_, int age_, char gender_) {
 name = name_;
 id = id_;
 age = age_;
 gender = gender_;
}
int main() {
 CUndergraduateStudent s2;
 s2.SetInfor("Harry Potter", "118829212", 19, 'M', "Computer Science");
 cout << s2.GetName() << " ";
 s2.QualifiedForBaoYan();
 s2.PrintInfo();
 return 0;
}
复合关系的使用:
class CMaster;
class CDog{CMaster *pm};
class CMaster{CDog * dogs[10];};
//利用pointer指定关系
访问范围说明符
基类的private成员: 可以被下列函数访问
  • 基类的成员函数
  • 基类的友员函数 
基类的public成员: 可以被下列函数访问
•基类的成员函数
•基类的友员函数
•派生类的成员函数
•派生类的友员函数
  • 其他的函数
基类的protected成员: 可以被下列函数访问
•基类的成员函数
•基类的友员函数
  • 派生类的成员函数可以访问当前对象的基类的保护成员
class Father {
private: int nPrivate; //私有成员
public: int nPublic; //公有成员
protected: int nProtected; // 保护成员
};
class Son : public Father {
 void AccessFather() {
  nPublic = 1; // ok;
  nPrivate = 1; // wrong
  nProtected = 1; // OK, 访问从基类继承的protected成员
  Son f;
  f.nProtected = 1; //wrong, f不是当前对象
 }
};
int main() {
 Father f;
 Son s;
 f.nPublic = 1; // Ok
 s.nPublic = 1; // Ok
 f.nProtected = 1; // error
 f.nPrivate = 1; // error
 s.nProtected = 1; //error
 s.nPrivate = 1; // error
 return 0;
}
派生类的构造函数
派生类对象 包含 基类对象 执行派生类构造函数之前, 先执行基类的构造函数 派生类交代基类初始化, 具体形式:
构造函数名(形参表): 基类名(基类构造函数实参表)
{
}
class Bug {
private:
 int nLegs; int nColor;
public:
 int nType;
 Bug(int legs, int color);
 void PrintBug() { };
};
class FlyBug : public Bug { // FlyBug是Bug的派生类
 int nWings;
public:
 FlyBug(int legs, int color, int wings);
};
Bug::Bug(int legs, int color) {
 nLegs = legs;
 nColor = color;
}
//错误的FlyBug构造函数:
FlyBug::FlyBug(int legs, int color, int wings) {
 nLegs = legs; // 不能访问
 nColor = color; // 不能访问
 nType = 1; // ok
 nWings = wings;
}
//正确的FlyBug构造函数:
FlyBug::FlyBug(int legs, int color, int wings) :Bug(legs, color) {
 nWings = wings;
}
int main() {
 FlyBug fb(2, 3, 4);
 fb.PrintBug();
 fb.nType = 1;
 fb.nLegs = 2; // error.nLegs is private
 return 0;
}
public继承的赋值兼容规则:
class base { }; 
class derived : public base { }; 
base b; 
derived d;
1) 派生类的对象可以赋值给基类对象
b = d;
2) 派生类对象可以初始化基类引用
base & br = d;
3) 派生类对象的地址可以赋值给基类指针
base * pb = & d;
如果派生方式是 private或protected,则上述三条不可行。

C++ 多态和虚函数

在类的定义中,前面有virtual关键字的成员函数就是虚函数。
class base{
      virtual int get();
};
int base::get(){}
virtual关键字只用在类定义里的函数声明中,写函数体时不用。
多态一:
派生类的指针可以赋给基类指针,通过基类指针调用基类和派生类中的同名虚函数时:
  1. 若该指针指向一个基类的对象,那么被调用是基类的虚函数;
  2. 若该指针指向一个派生类的对象,那么被调用是派生类的虚函数
class CBase {
public:
 virtual void SomeVirtualFunction(){}
};
class CDerived :public CBase {
 public:
 virtual void SomeVirtualFunction(){}
};
int main() {
 CDerived ODerived;
 CBase *p = &ODerived;
 p->SomeVirtualFunction();
 return 0;
}
多态二:
派生类的对象可以赋给基类引用,通过基类指针调用基类和派生类中的同名虚函数时:
  1. 若该引用引用的是一个基类的对象,那么被调用是基类的虚函数;
  2. 若该引用引用的是一个派生类的对象,那么被调用是派生类的虚函数
class CBase {
public:
 virtual void SomeVirtualFunction(){}
};
class CDerived :public CBase {
 public:
 virtual void SomeVirtualFunction(){}
};
int main() {
 CDerived ODerived;
 CBase &r = ODerived;
 r.SomeVirtualFunction();
 return 0;
}
多态例一:
#include <iostream>
#include <stdlib.h>
#include <math.h>
using namespace std;
class CShape {
public:
 virtual double Area() = 0; //纯虚函数
 virtual void PrintInfo() = 0;
};
class CRectangle :public CShape {
public:
 int w, h;
 virtual double Area();
 virtual void PrintInfo();
};
double CRectangle::Area() {
 return w*h;
}
void CRectangle::PrintInfo() {
 cout << "Rectangle:" << Area() << endl;
}
class CCircle :public CShape {
public:
 int r;
 virtual double Area();
 virtual void PrintInfo();
};
double CCircle::Area() {
 return 3.14*r*r;
}
void CCircle::PrintInfo() {
 cout << "Circle:" << Area() << endl;
}
class CTriangle :public CShape {
public:
 int a,b,c;
 virtual double Area();
 virtual void PrintInfo();
};
double CTriangle::Area() {
 double p = (a + b + c) / 2.0;
 return sqrt(p * (p - a)*(p - b)*(p - c));
}
void CTriangle::PrintInfo() {
 cout << "Triangle:" << Area() << endl;
}
CShape *pShapes[100];
int MyCompare(const void *s1, const void *s2);
int main() {
 int i; int n;
 CRectangle *pr; CCircle *pc; CTriangle *pt;
 cin >> n;
 for (i = 0; i < n; i++) {
  char c;
  cin >> c;
  switch (c) {
  case'R':
   pr = new CRectangle();
   cin >> pr->w >> pr->h;
   pShapes[i] = pr;
   break;
  case'C':
   pc = new CCircle();
   cin >> pc->r;
   pShapes[i] = pc;
   break;
  case 'T':
   pt = new CTriangle();
   cin >> pt->a >> pt->b >> pt->c;
   pShapes[i] = pt;
   break;
  }
 }
 qsort(pShapes, n, sizeof(CShape*), MyCompare);
 for (i = 0; i < n; i++)
  pShapes[i]->PrintInfo();
 return 0;
}
int MyCompare(const void * s1, const void * s2)
{
 double a1, a2;
 CShape * * p1; // s1,s2 是 void * ,不可写 “* s1”来取得s1指向的内容
 CShape * * p2;
 p1 = (CShape * *)s1; //s1,s2指向pShapes数组中的元素,数组元素的类型是CShape *
 p2 = (CShape * *)s2; // 故 p1,p2都是指向指针的指针,类型为 CShape **
 a1 = (*p1)->Area(); // * p1 的类型是 Cshape * ,是基类指针,故此句为多态
 a2 = (*p2)->Area();
 if (a1 < a2)
  return -1;
 else if (a2 < a1)
  return 1;
 else
  return 0;
}
 多态实现的原理:
每一个有虚函数的类(或有虚函数的类的派生类)都有一个虚函数表,该类的任何对象中都放着虚函数表的指针。虚函数表中列出了该类的虚函数地址。多出来的4个字节就是用来放虚函数表的地址的。
纯虚函数:没有函数体的虚函数
class A{
private:
  int a;
public:
  virtual void Print()=0;
  void fun(){cout<<"fun";}
};
抽象类:包括纯虚函数的类
  1. 只能作为基类来派生新类使用
  2. 不能创建抽象类的对象
  3. 抽象类的指针和引用
class A {
 public:
 virtual void f() = 0; //纯虚函数
 void g( ) { this->f( ); } //ok
 A( ){ }   //f( ); // 错误
};
class B : public A{
 public:
 void f(){ cout<<"B: f()"<<endl; }
};
int main(){
B b;
b.g();
return 0;
}
抽象类中,
  1. 在成员函数内可以调用纯虚函数
  2. 在构造函数/析构函数内部不能调用纯虚函数
如果一个类从抽象类派生而来,它实现了基类中的所以纯虚函数,才能成为非抽象类。

C++ Program Design

类class:
class Box
{
   public:
      double length;      // 长度
      double breadth;     // 宽度
      double height;      // 高度
   
      double getVolume(void)
      {
         return length * breadth * height;
      }
}; // Define function inside of class
double Box::getVolume(void)
{
    return length * breadth * height;
}// Define function outside of class   范围解析运算符::
Box myBox;          // 创建一个对象
 
myBox.getVolume();  // 调用该对象的成员函数
实际操作中,我们一般会在私有区域定义数据,在公有区域定义相关的函数,以便在类的外部也可以调用这些函数,如下所示:
#include <iostream>
 
using namespace std;
 
class Box
{
   public:
      double length;
      void setWidth( double wid );
      double getWidth( void );
 
   private:
      double width;
};
 
// 成员函数定义
double Box::getWidth(void)
{
    return width ;
}
 
void Box::setWidth( double wid )
{
    width = wid;
}
 
// 程序的主函数
int main( )
{
   Box box;
 
   // 不使用成员函数设置长度
   box.length = 10.0; // OK: 因为 length 是公有的
   cout << "Length of box : " << box.length <<endl;
 
   // 不使用成员函数设置宽度
   // box.width = 10.0; // Error: 因为 width 是私有的
   box.setWidth(10.0);  // 使用成员函数设置宽度
   cout << "Width of box : " << box.getWidth() <<endl;
 
   return 0;
}

保护(protected)成员

保护成员变量或函数与私有成员十分相似,但有一点不同,保护成员在派生类(即子类)中是可访问的。
在下一个章节中,您将学习到派生类和继承的知识。现在您可以看到下面的实例中,我们从父类 Box 派生了一个子类 smallBox
下面的实例与前面的实例类似,在这里 width 成员可被派生类 smallBox 的任何成员函数访问。
#include <iostream>
using namespace std;
 
class Box
{
   protected:
      double width;
};
 
class SmallBox:Box // SmallBox 是派生类
{
   public:
      void setSmallWidth( double wid );
      double getSmallWidth( void );
};
 
// 子类的成员函数
double SmallBox::getSmallWidth(void)
{
    return width ;
}
 
void SmallBox::setSmallWidth( double wid )
{
    width = wid;
}
 
// 程序的主函数
int main( )
{
   SmallBox box;
 
   // 使用成员函数设置宽度
   box.setSmallWidth(5.0);
   cout << "Width of box : "<< box.getSmallWidth() << endl;
 
   return 0;
}

继承中的特点

有public, protected, private三种继承方式,它们相应地改变了基类成员的访问属性。
  • 1.public 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:public, protected, private
  • 2.protected 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:protected, protected, private
  • 3.private 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:private, private, private
但无论哪种继承方式,上面两点都没有改变:
  • 1.private 成员只能被本类成员(类内)和友元访问,不能被派生类访问;
  • 2.protected 成员可以被派生类访问。
int i = 3;
int j = 5;
const int * p= &i;
则:
p = &j; /* 正确,p可以被重新赋值 */
*p = j; /* 错误,因为他改变的是p所指向的变量的值。*/
常量指针与指针常量vi
常量指针表示一个指针指向的变量为常量及带有const属性(e.x. const int *p) , 而指针常量表示一个指针本身为常量及指针本身带有const属性(e.x. int *const p), 常量指针指向的对象由于有const属性, 无法直接改变, 但是指针本身值(及指针指向的内存地址)可以改变, 而指针常量则是指针本身有const属性, 指针的值(及指针指向的内存地址)无法直接改变, 而该地址内的变量可以改变。
例子:
const char *p = “Hello, World”; //表示指针p是一个常量字符串的首地址, 指针p为常量指针
char a[20] = “Hello, World”;
char *const p = a; //表示指针p本身为常量, 它将一直指向该内存区域直到它被释放, 指针p为指针常量。(注意: 此时p的值虽然无法改变, 但是a的值可以改变。)
指针常量一般常用于当一个指针由始至终都指向一个对象时使用。
动态内存分配:
用new运算符实现动态内存分配:
P=new T;
T是任意类型名,P是类型为T*的指针。动态分配出一片大小为sizeof(T)字节的内存空间,并且将该内存空间的起始地址赋值给P。比如:
int *pn;
pn=new int;
*pn =5;
P=new T[N];//N*sizeof(T)
int *pn;
int i = 5;
pn=new int[i*20];
pn[0] = 20;
pn[100] = 30;//error
new T;
new T[n];
这两个表达式返回值的类型都是 T *
用“new”动态分配的内存空间,需要用“delete”运算符进行释放;
int *p = new int;
*p = 5;
delete p;
delete p;//shows error: p only can be deleted for one time
 — — — — — — — — — — — — — — — — — — 
int *p = new int[20];
p[0] = 1;
delete []p;
内联函数:
函数调用是有时间开销的。如果函数本身只有几条语句,执行非常快,而且函数被反复执行很多次,相比之下调用函数所产生的这个开销就会显得比较大。
为了减少函数调用的开销,引入了内联函数机制。编译器处理对内联函数的调用语句时,是将整个函数的代码插入到调用语句处,而不会产生调用函数 的语句。
inline int Max(int a, int b){
if(a>b) return a;
return b;
}
 函数重载:
(1) int Max(double f1, double f2){}
(2) int Max(int n1, int n2){}
(3) int Max(int n1, int n2, int n3){}
Max(3.4,2.5); //1
Max(2,4); //2
Max(1,2,3); //3
Max(3,2.4); //error
函数的缺省参数:
void func(int x1, int x2 = 2, int x3 = 3) {}
func(10); //equal to func(10,2,3)
func(10, 8); //equal to func(10,8,3)
func(10, , 8); //error. Only continuous right side parameters missing
构造函数
class Complex {
private:
 double real, imag;
public:
 Complex(double r, double i = 0);
};
Complex::Complex(double r, double i) {
 real = r; imag = i;
}
Complex c1; //error,缺少构造函数的参数
Complex *pc = new Complex; //error,没有参数
Complex c1(2);//ok
Complex c1(2, 4), c2(3, 5);
Complex *pc = new Complex(3, 4);
 — — — — — — — — — — — — — 
可以有多个构造函数,参数个数或类型不同
class Complex {
private:
 double real, imag;
public:
 void Set(double r, double i);
 Complex(double r, double i);
 Complex(double r);
 Complex(Complex c1, Complex c2);
};
Complex::Complex(double r, double i) {
 real = r; imag = i;
}
Complex::Complex(double r) {
 real = r; imag = 0;
}
Complex::Complex(Complex c1, Complex c2) {
 real = c1.real + c2.real;
 imag = c1.imag + c2.imag;
}
Complex c1(3), c2(1, 0), c3(c1, c2);
// c1 = {3, 0}, c2 = {1, 0}, c3 = {4, 0};
构造函数最好是public的,private构造函数不能直接用来初始化对象
#include <iostream>
using namespace std;
class CSample {
 int x;
public:
 CSample() {
  cout << "Constructor 1 Called" << endl;
 }
 CSample(int n) {
  x = n;
  cout << "Constructor 2 Called" << endl;
 }
};
int main() {
 CSample array1[2];  //Constructor 1 Called    Constructor 1 Called
 cout << "step1" << endl;  //step1
 CSample array2[2] = { 4,5 }; //Constructor 2 Called  Constructor 2 Called
 cout << "step2" << endl; //step2
 CSample array3[2] = { 3 };//Constructor 2 Called  Constructor 1 Called
 cout << "step3" << endl; //step3
 CSample *array4 = new CSample[2]; //Constructor 1 Called    Constructor 1 Called
 delete[]array4;
 return 0;
}
构造函数在数组中的使用:
class Test {
public:
 Test(int n) {}       //1
 Test(int n,int m){}  //2
 Test(){}             //3
};
Test array1[3] = { 1,Test(1,2) }; //1,2,3
Test array2[3] = { Test(2,3),Test(1,2),1 }; //2,2,1
Test *pArray[3] = { new Test(4),new Test(1,2) };//1,2

C程序设计进阶

Week2
r = sqrt(100.0);
k = pow(x,y);
i = strlen(str1);
v = strcmp(str1,str2);
n = atoi(str1);
数组的名字 = 数组的地址
int a[2];
cout << a <<endl;  //a is the address of a array
Week4 Pointer note:
取地址运算符:“&”
int c = 76;
cout<<&c<<endl;
cout<<sizeof(&c)<<endl; //4 bytes
 — — — — — 
int c = 76;
int *pointer; //定义名字为pointer的指针变量
pointer = &c; //将变量c的地址赋值给指针变量pointer
              //赋值后,称指针变量pointer指向了变量c
 — — — — — — — — — — — — — 
int c = 76;
int *pointer = &c;
*pointer:所指向的存储单元的内容:变量c
 — — — — — — — — — — — — 
#include<iostream>
using namespace std;
int main() {
int iCount = 18;
int *iPtr = &iCount;
*iPtr = 58;
cout << iCount << endl;
cout << iPtr << endl;
cout << &iCount << endl;
cout << *iPtr << endl;
cout << &iPtr << endl;
return 0;
}
 — — — — — — 
#include<iostream>
using namespace std;
int main() {
int a = 0, b = 0, temp;
int *p1 = NULL, *p2 = NULL;
cin >> a >> b;
p1 = &a;
p2 = &b;
if (*p1 < *p2)
{
temp = *p1; *p1 = *p2; *p2 = temp;
}
cout << "max= " << *p1 << ",min= " << *p2 << endl;
return 0;
}
 — — — — — — — 
运算符优先级:后置++ -- 高于 (前置++-- 逻辑非 (!)* & ) 从右到左
#include<iostream>
using namespace std;
int main() {
int a[5] = { 1,2,3,4,5 };
int *p = &a[3];
cout << *p << endl;
*p = 100;
cout << a[3] << endl;
return 0;
}
 — — — — — — — — — — — 
#include<iostream>
using namespace std;
int main() {
 int a[5] = { 1,2,3,4,5 };
 cout << a << endl;
 cout << *a << endl;
 cout << &a[0] << endl;
 cout << a[0] << endl;
 return 0;
}
#include<iostream>
#include<iomanip>
using namespace std;
int main() {
 int a[10], *p = NULL, *q = NULL, temp;
 for (p = a; p < a + 10; p++)
  cin >> *p;
 for (p = a, q = a + 9; p < q; p++, q--) {
  temp = *p; *p = *q; *q = temp;
 }
 for (p = a; p < a + 10; p++)
  cout << setw(3) << *p;
 return 0;
}
 — — — — — — — — — 
#include<iostream>
using namespace std;
int main() {
 int a[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
 int(*p)[4], i, j;
 p = a;
 cin >> i >> j;
 cout << *(*(p + i) + j) << endl; .
return 0;
}
Week5: 
char c[6]={'h','e','l','l','o','\0'}
char *pc = c;
cout<<c<<endl;  //hello
cout<<pc<<endl; //hello
cout<<static_cast<void*>(c)<<endl;  //address
cout<<static_cast<void*>(pc)<<endl; //address
 — — — — — — — — — 
#include<iostream>
using namespace std;
int main() {
 char buffer[10] = "ABC";
 char *pc;
 pc = "hello";
 cout << pc << endl;
 pc++;
 cout << pc << endl;
 cout << *pc << endl;
 pc = buffer;
 cout << pc;
 return 0;
}
output:
hello
ello
e
ABC

Week 7:
Struct: 结构体数据类型的特性与普通数据类型的特性是一致的。
#include<iostream>
using namespace std;
struct student {
 int id_num;
 char name[10];
};
void renew(student *one) {
 one->id_num = 20130000 + one->id_num; //one->id_num is equivalent to (*one).id_num
 for (int i = 0; one->name[i] != '\0'; i++)
  one->name[i] = toupper(one->name[i]);
}
int main() {
 student mike = { 123,{'m','i','k','e','\0'} };
 renew(&mike);
 cout << mike.id_num << " " << mike.name;
 return 0;
}
 — — — — — — — — — — 
#include<iostream>
using namespace std;
struct student {
 int id_num;
 char name[10];
};
int main() {
 student myclass[3] =
 { 123,{'m','i','k','e','\0'},
   133,{'t','o','m','\0'},
   143,{'j','a','c','k','\0'} };
 student *one = myclass;
 cout << (*one).id_num << " " << (*one).name << endl;
 one++;
 cout << one->id_num << " " << one->name << endl;
 return 0;
}
 — — — — — — — — — — — — — 
LinkedList: 
Creation:
#include<iostream>
using namespace std;
struct student {
 int id;
 student *next;
};
student *create() {
 student *head, *temp; int num, n = 0;
 head = new student;
 temp = head;
 cin >> num;
 while (num != -1) {
  n++;
  temp->id = num;
  temp->next = new student;
  temp = temp->next;
  cin >> num;
 }
 if (n == 0)head = NULL; else temp->next = NULL;
 return head;
}
int main() {
 return 0;
}
 — — — — — — — — — — — — — — — 
Delete
student *dele(student *head, int n) {
 student *temp, *follow;
 temp = head;
 if (head == NULL) {
  return head;
 }
 if (head-> num == n) {
  head = head->next;
  delete temp;
  return(head);
 }
 while (temp != NULL&&temp->num != n) {
  follow = temp;
  temp = temp->next;
 }
 if (temp == NULL)
  cout << "not found";
 else {
  follow->next = temp->next;
  delete temp;
 }
 return head;
 — — — — — — — — — — 
Insert:
#include<iostream>
using namespace std;
struct student {
 int id,num;
 student *next;
};
student *create() {
 student *head, *temp; int num, n = 0;
 head = new student;
 temp = head;
 cin >> num;
 while (num != -1) {
  n++;
  temp->id = num;
  temp->next = new student;
  temp = temp->next;
  cin >> num;
 }
 if (n == 0)head = NULL; else temp->next = NULL;
 return head;
}
student *dele(student *head, int n) {
 student *temp, *follow;
 temp = head;
 if (head == NULL) {
  return head;
 }
 if (head-> num == n) {
  head = head->next;
  delete temp;
  return(head);
 }
 while (temp != NULL&&temp->num != n) {
  follow = temp;
  temp = temp->next;
 }
 if (temp == NULL)
  cout << "not found";
 else {
  follow->next = temp->next;
  delete temp;
 }
 return head;
}
student *insert(student *head, int n) {
 student *temp, *unit, *follow;
 temp = head; unit = new student;
 unit->num = n; unit->next = NULL;
 if (head == NULL) {
  head = unit;
  return(head);
 }
 while ((temp->next != NULL) && (temp->num < n)) {
  follow = temp; temp = temp->next;
 }
 if (temp == head) {
  unit->next = head; head = unit;
 }
 else {
  if (temp->next == NULL)temp->next = unit;
  else {
   follow->next = unit; unit->next=temp;
  }
 }
 return(head);
}
int main() {
 student *pointer = create();
 while (pointer->next!=NULL)
 {
  cout << pointer->id << endl;
  pointer = pointer->next;
 }
 return 0;
}
#include <iostream>
#include <cstring>
using namespace std;
int m, n;//n行m列
char map[101][101];//地图矩阵
int already[101][101];//已走地图记忆
int min_count = 0;
void cross(int u, int v, int i, int j)
{
 int t = already[u][v];
 if (u == i && v == j)//起点即为到达终点
 {
  min_count = t;
 }
 t++;
if (v < m - 1 && map[u][v + 1] != '#'  && already[u][v + 1]>t)//在迷宫内、右侧非墙且此点没有走过
 {
  already[u][v + 1] = t;//标记此点为第t步
  cross(u, v + 1, i, j);//以此点为起点继续走
 }
 if (u > 0 && map[u - 1][v] != '#'  && already[u - 1][v]>t)
 {
  already[u - 1][v] = t;
  cross(u - 1, v, i, j);
 }
 if (v > 0 && map[u][v - 1] != '#'  && already[u][v - 1]>t)
 {
  already[u][v - 1] = t;
  cross(u, v - 1, i, j);
 }
 if (u < n - 1 && map[u + 1][v] != '#' && already[u + 1][v]>t)
 {
  already[u + 1][v] = t;
  cross(u + 1, v, i, j);
 }
}
int main() {
 int startx, starty, endx, endy;
 cin >> n >> m;
 for (int i = 0; i<n; i++) {
  for (int j = 0; j<m; j++) {
   cin >> map[i][j];
   if (map[i][j] == 'S') {
    startx = i;
    starty = j;
   }
   if (map[i][j] == 'T') {
    endx = i;
    endy = j;
   }
  }
 }
 memset(already, 1, sizeof(already));
 already[startx][starty] = 0;
 cross(startx, starty, endx, endy);
 cout << min_count << endl;
 return 0;
}
C++ 引用 vs 指针
引用很容易与指针混淆,它们之间有三个主要的不同:
不存在空引用。引用必须连接到一块合法的内存。
一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。
引用必须在创建时被初始化。指针可以在任何时间被初始化。
#include <iostream>
 
using namespace std;
 
int main ()
{
   // 声明简单的变量
   int    i;
   double d;
 
   // 声明引用变量
   int&    r = i;
   double& s = d;
   
   i = 5;
   cout << "Value of i : " << i << endl;
   cout << "Value of i reference : " << r  << endl;
 
   d = 11.7;
   cout << "Value of d : " << d << endl;
   cout << "Value of d reference : " << s  << endl;
   
   return 0;
}

Sensors and Sensor Circuit Design

Introduction: instructor: Jay
Process sensors: petrochemical, pharmaceutical and semiconductor industries
Position sensors: vehicles and air crafts
Motion sensors: smartphone and security systems
Ergonomic sensors: tablets, PCs, and phones
Chemical sensors: protect from fire and toxic vapor hazards
Electrical sensors: lab instruments and security systems
The output of the ADC is typically 8, 12, 16, or 24 bits. Data from an 80C is usually converted to a serial format such as I2C, spy, or RS 232. 
Thermal sensors:
Thermocouple: up to 1800 degrees Celsius
RTD resistance temperature detector: the resistance of metal increases as the temperature increases. For platinum, all most linear. More precise. up to 800 degrees Celsius. 
Thermistor: entered semi-conductor or metal oxide particles
NTC thermistor: exhibit a large decrease in electrical resistance for a relatively small increase in temperature. Their small package size makes them ideal for measuring temperature in phones and computers.
Infrared sensor: the only non-contact temperature sensor.
Thermistor:
Why RTDs needs four-wire connection to keep accuracy?
For two-wire resistance measurements, the RTD’s lead wires’ resistance will affect the measurement accuracy. The value will be RTD + 2 x Rwire.
For three-wire resistance measurements, the return lead wire’s resistance will affect the accuracy of resistance measurement. The value would be RTD+Rreturn lead wire. Roughly reduces half error. 
For four-wire resistance measurements, there is no current through Rwire2&Rwire3. Therefore, the voltage measurement is accurate. Then, the resistance value of RTD is accurate.
To purchase list:
  1. CY8CKIT-059 PSoC 5LP Prototyping Kit: 
These are the part numbers typed out, so you can copy and paste them into the Digikey web site:
428–3390-ND
NHD-0216BZ-RN-YBW-ND
570–1229-ND
A105970CT-ND
Resistance calculation for RTD

NTC thermistors can also be characterised with the B (or β) parameterequation, which is essentially the Steinhart–Hartequation with , and , where the temperatures are in kelvins, and R0 is the resistance at temperature T0(25 °C = 298.15 K).

Rotary Sensor

Type1: Incremental encoder- generates pulses to measure angular speed. Used for motor speed, rate control, and cutting devices. Found in robots, grinders, drills, lathes, and mixing equipment.
Note: good for measuring speed, not for absolute position
Type2: Absolute encloder- generates multi-bit digital words that indicate actual position directly. Used for measuring and positioning. Found in milling machines, robots, plotters, ultrasonic welders and medical equipment.
Note: always know where it is during rotation and it can also keep track of total revolutions.
Type3: Resolvers- generates a voltage corresponding to absolute angular position, per the interaction of magnetic fields of a rotor and stator. Used for extreme temperature, shock, and vibration conditions in military, aerospace, and construction equipment.


计算导论与C语言基础

摩尔定律下的挑战:
晶体管大小限制
电泄露
散热
静态RAM的六管基本储存单元
Memory Type
RAM(random access memory): DRAM(dynamic), S(static)RAM
ROM(read only memory): ROM, P(programmable)ROM, E(erasable)PROM, E(electrical)EPROM, FLASH EPROM (USB)
EDO(extended data out) DRAM
S(synchronous)DRAM
DDR(double data rate SDRAM)
CPU的指令集:Intel X86, ARM
汇编语言--assembly language
小结:
程序必须要经过编译才能转换成CPU所能接受的指令;
一句程序有可能转换为多句指令;
在控制器的协调下连续、依次执行相应的指令;
程序执行过程是在内存中完成的;
程序在执行过程中,在内存中的不同区域,存放代码和相关的数据;
EX1:
// Example program
#include <iostream>
using namespace std;
int main()
{
 int x = 0, y = 0, z = 0, t1 = 0, t2 = 0;
 while (x < 34) {
  while (y < 51) {
   while (z < 101) {
    t1 = x + y + z;
    t2 = 2 * x + 4 * y + z;
    if (t1 == 100 && t2 == 200) {
     cout << x << " " << y << " " << z << endl;
    }
    z++;
   }
   y++;
  }
x++;
 }
 return 0;
}
EX2:
// Example program
#include <iostream>
using namespace std;
int main()
{
 int items[10]={4,2,7,1,6,9,5,3,8,3};
 int tmp=0;
 for(int i = 0;i<10;i++){
     cout<<items[i]<<" ";
     }
 for(int i=0;i<10;i++){
         for(int j = i; j<10;j++){
             if(items[i]<items[j]){
                     tmp = items[i];
                     items[i]=items[j];
                     items[j]=tmp;
                 }
             }
     
     }
 cout<<endl;
 for(int i = 0; i<10;i++){
     cout<<items[i]<<" ";
     }
 return 0;
}
学习一门程序设计语言
数据成分:有哪些数据类型?如何使用?
运算成分:有哪些运算符号?如何使用?
控制成分:三种类型的控制语句是如何写的?
传输成分:在程序中如何输入和输出数据?
// Example program
#include <iostream>
using namespace std;
int main()
{
 cout<<"sizeof(short int)="<<sizeof(short int)<<endl;
 cout<<"sizeof(int)="<<sizeof(int)<<endl;
 cout<<"sizeof(long int)="<<sizeof(long int)<<endl;
 return 0;
}
赋值运算总结:
两边类型不用:自动完成类型转换
常数赋给短数:截取长数的低位送给短数
短数赋给长数:保持不变
符号位的赋值处理:直接赋值,不管符号位还是数字位
定义数组的长度
#include <iostream>
using namespace std;
#define N 4
int main() {
int a[N] = { 1,2,3,4 };
for (int i = 0; i < N; i++) {
cout << a[i] << endl;
}
return 0;
}
允许定义:
int a[] = {1,2,3,4};
都一样:
int a[4] = {0};
 — — — — — — — — — 
cout << setw(3) <<a[i][j];   //输出占三个字符位
 — — — — — — — — — 
#include <iostream>
#include <cmath>
using namespace std;
int main() {
int sum = 0, a[100] = { 0 };
for (int i = 2; i < sqrt(100.0); i++) {
sum = i;
if (a[sum] == 0) {
while (sum < 100) {
sum = sum + i;
if (sum < 100)a[sum] = 1;
}
}
}
for (int i = 2; i < 100; i++) {
if (a[i] == 0)cout << i << " ";
}
return 0;
}
 — — — — — — — — — — — — — — — 
#include <iostream>
using namespace std;
int main()
{   
    char a;
    while(cin>>a)
        cout << a;
    return 0;
    
}
 — — — — — — — — — — — — — — — — — 
#include <iostream>
using namespace std;
int main()
{   
    char a;
    while((a = cin.get())!=EOF)
        cout << a;
    return 0;
}
 — — — — — — — — — — — — — — — — — 
#include <iostream>
using namespace std;
int main()
{   
    char a;
    while(cin.get(a))
        cout << a;
    return 0;
}
 — — — — — — — — — — — — — — — — — — — 
#include <iostream>
using namespace std;
int main()
{   
    char c;
    while(c = getchar())
        cout << c;
    return 0;
}
 — — — — — — — — — — — — 
#include <iostream>
using namespace std;
int main()
{   
    char a[10] = "Computer";
    cout << a;
    return 0;
}
 — — — — — — — — — — — — 
#include <iostream>
using namespace std;
int main()
{   
    char a[2][2] = {"aa","bb","cc","dd"};
    for(int i =0; i < 7; i++)
        cout << a[i] <<endl;
    return 0;
}
 — — — — — — — — — — — — 
#include <iostream>
using namespace std;
int main()
{   
    char str[10];
    while(cin>>str)
        cout << str <<endl;
    return 0;
}
 — — — — — — — — — — 
#include <iostream>
using namespace std;
int main()
{   
    char ch[20];
    cin.get(ch,10,'o');
    cout << ch << endl;
    return 0;
}
 — — — — — — — — — — 
#include <iostream>
using namespace std;
int main()
{   
    char ch[20];
    cin.getline(ch,10,'o');
    cout << ch << endl;
    return 0;
}
#include <iostream>
using namespace std;
int main()
{   
    char a[10][10];
    int n = 0;
    cin >> n;
    cin.get(); //read n first
    for(int i = 0; i < n; i++)
        cin.getline(a[i],10);
    for(int i = 0; i < n; i++)
        cout << a[i] << endl;
    return 0;
}

C++ Convert String to Int

There are two common methods to convert strings to numbers:
Using stringstream class or sscanf()
stringstream() : This is an easy way to convert strings of digits into ints, floats or doubles. Following is a sample program using a stringstream to convert string to int.

// A program to demonstrate the use of stringstream 
#include <iostream> 
#include <sstream> 
using namespace std; 
  
int main() 
{ 
    string s = "12345"; 
  
    // object from the class stringstream 
    stringstream geek(s); 
  
    // The object has the value 12345 and stream 
    // it to the integer x 
    int x = 0; 
    geek >> x; 
  
    // Now the variable x holds the value 12345 
    cout << "Value of x : " << x; 
  
    return 0; 
}
 — — — — — — — — — — 
#include<stdio.h> 
int main() 
{ 
    const char *str = "12345"; 
    int x; 
    sscanf(str, "%d", &x); 
    printf("\nThe value of x : %d", x); 
    return 0; 
}
 — — — — — — — — — — 
// C++ program to demonstrate working of stoi() 
// Work only if compiler supports C++11 or above. 
#include <iostream> 
#include <string> 
using namespace std; 
  
int main() 
{ 
    string str1 = "45"; 
    string str2 = "3.14159"; 
    string str3 = "31337 geek"; 
  
    int myint1 = stoi(str1); 
    int myint2 = stoi(str2); 
    int myint3 = stoi(str3); 
  
    cout << "stoi(\"" << str1 << "\") is "
         << myint1 << '\n'; 
    cout << "stoi(\"" << str2 << "\") is "
         << myint2 << '\n'; 
    cout << "stoi(\"" << str3 << "\") is "
         << myint3 << '\n'; 
  
    return 0; 
}
 — — — — — — — — — — — 
// For C++11 above 
#include <iostream> 
#include <cstdlib> 
using namespace std; 
   
int main() 
{ 
    const char *str1 = "42"; 
    const char *str2 = "3.14159"; 
    const char *str3 = "31337 geek"; 
     
    int num1 = atoi(str1); 
    int num2 = atoi(str2); 
    int num3 = atoi(str3); 
    
    cout << "atoi(\"" << str1  
              << "\") is " << num1 << '\n'; 
    cout << "atoi(\"" << str2  
              << "\") is " << num2 << '\n'; 
    cout << "atoi(\"" << str3  
              << "\") is " << num3 << '\n'; 
     
   return 0; 
}

DC Motor Theory

Q1: When switch closes, the current initially register a large amount of current, then the current decay to a much lesser value over time as the motor speeds up. Why?
Motor current is inversely proportional to speed, due to the counter-EMF by the armature as it rotates.
Q2: 
  • Field: the portion of the motor creating the stationary magnetic field
  • Armature: the rotating portion of the motor
  • Commutator: copper strips where the armature coil leads terminate, usually located at one end of the shaft
  • Brush: a stationary carbon block designed to electrically contact the moving commutator bars
Q3: