需要更好的阅读的体验请移步 小牛肉的个人博客
class Point{
public:
Point(float xx = 0,float yy = 0):x(xx),y(yy){ }
float getX() const {return x;}
float getY() const {return y;}
private:
float x,y;
};
//直线线性拟合,number为点数
float lineFit(const Point points[], int number){
float avgx = 0, avgy = 0;
float lxx = 0,lyy = 0, lxy = 0;
for(int i =0;i<number;i++){
avgx += points[i].getX()/number;
avgy += points[i].getY()/number;
}
for(int i = 0;i<number;i++){
lxy += (points[i].getX() - avgx) * (points[i].getY() - avgy);
lyy += (points[i].getY() - avgy) * (points[i].getY() - avgy);
lxx += (points[i].getX() - avgx) * (points[i].getX() - avgx);
}
cout<<"This line can be fitted by y=ax+b."<<endl;
//输出回归系数a,b
cout<<"a = "<<lxy/lxx<<" "<<"b = "<<avgy-lxy*avgx/lxx<<endl;
return (float)(lxy/sqrt(lxx*lyy)); //线性相关的密切程度
}
int main(){
Point points[10] = {Point(6,10),Point(14,20),Point(26,30),Point(33,40),
Point(46,50),Point(54,60),Point(67,70),Point(75,80),
Point(84,90),Point(100,100)};
float r = lineFit(points,10);
cout<<"Line coefficient r = "<<r<<endl;
}
*
称为指针运算符,也称解析;&
称为取地址运算符;为什么需要用指针做参数?
引用和指针有何区别?何时只能用指针而不能使用引用
若函数的返回值是指针,该函数就是指针类型的函数
int * function(){
}
即指向函数的指针
定义:数据类型 (* 函数指针名)(形参表)
int (*func)(int, int)
含义:函数指针指向的是程序代码存储区。
#include
using namespace std;
int compute(int a, int b, int (*func)(int, int))
{
return func(a, b);
}
int max(int a, int b) // 求最大值
{11
return ((a > b) ? a : b);
}
int min(int a, int b) // 求最小值
{
return ((a < b) ? a : b);
}
int sum(int a, int b) // 求和
{
return a + b;
}
int main()
{
int a, b, res;
cout << "请输入整数a:";
cin >> a;
cout << "请输入整数b:";
cin >> b;
res = compute(a, b, &max);
cout << "Max of " << a << " and " << b << " is " << res << endl;
res = compute(a, b, &min);
cout << "Min of " << a << " and " << b << " is " << res << endl;
res = compute(a, b, &sum);
cout << "Sum of " << a << " and " << b << " is " << res << endl;
}
定义形式:类名 *对象指针名
Point *ptr;
Point a(5,10);
ptr = &a;
对象指针通过 ->
访问对象成员
ptr->getx()
相当于 (*ptr).getx();
首先我们需要分清几个概念
int *point = new int(5); //用5初始化
int *point = new int(); //用0初始化
int *point = new int; //不分配初值
int *point = new int[5] //表示为该指针分配包含十个元素的地址空间
同一个程序有可能会处理很大的数据,有时处理很小,若总是以最大的空间内存分配,难免会造成浪费。
malloc
进行动态内存分配;new
语句动态分配一个变量
p = new T; //T代表int,double,float等等
//p类型为T*的指针
//该语句动态分配了一片大小为 sizeof(T) 字节的内存空间,并将起始地址赋给了p
int *pn;
pn = new int;
*pn = 5; //往刚开辟的空间中写入了数据5
动态分配一个数组
p = new T[N];
//动态分配了一片大小为 sizeof(T)*N 字节的内存空间,并将起始地址赋给了p
int *pn;
int i = 5;
pn = new int[i*20]; //100个元素,最大合法下标为99
pn[0] = 20;
pn[100] = 30; // 编译没问题,运行时数组越界
注:new运算符返回值类型都是 T*
delete总是和new成对出现 :即动态分配的内存一定要释放掉,否则占用的内存就会越来越多。
delete指针
该指针必须指向new出来的空间
int *p = new int;
*p = 5;
delete p;
delete p; //wrong; 同一片空间不能被delete两次
delete [ ]指针
int *p = new int[20];
p[0] = 1;
delete []p; //若delete p 则只删除了一部分,没有删干净
为什么需要vector
vector对象的定义
vector<元素类型> 数组对象名(数组长度)
vector arr(5)
建立大小为5的int数组vector arr(5,2)
大小为5的int类型数组,所有元素用2初始化vector对象的使用
ArrayOfPoints pointsArray2(pointsArray1); //创建副本
详见第一章 【C++复习总结回顾】—— 【一】基础知识+字符串/string类
设计一个字符串类MyString,具有构造函数、析构函数、复制构造函数、并重载运算符 +、=、+=、[ ],尽可能的完善它,使之能满足各种需要。
#include
#include
using namespace std;
class Mystring{
private:
char* mystring; //字符指针
int len; //字符串长度
Mystring(int clen){ //私有构造,防止其他类进行调用创建实例,只使用一次(在+重载)
mystring = new char[clen + 1];
for (int i = 0; i < clen; i++)
mystring[i] = '\0';
len = clen;
}
public:
Mystring(); //无参构造
Mystring(const char* const cmystring); //带参构造
Mystring(const Mystring& rhs); //复制构造
~Mystring(); //析构
int getLen() const{ //获取长度
return this->len;
}
const char *GetMyString() const{ //获取字符串
return mystring;
}
char & operator[](int offset); //重载下标运算符,作为左值可被修改,需返回引用
char operator [](int offset) const; //重载下标运算符,作为右值仅能访问
Mystring operator +(const Mystring& rhs); //a+b a的值并不会被修改,不需要返回引用
void operator +=(const Mystring& rhs); //a+=b 无返回值
Mystring& operator =(const Mystring& rhs); //a=b a的值会被修改,需要返回引用
};
//无参构造
Mystring::Mystring(){
mystring = new char[1];
mystring[0] = '\0';
len = 0;
}
//带参构造
Mystring::Mystring(const char* const cmystring){
len = strlen(cmystring);
mystring = new char[len+1];
for(int i = 0; i<len; i++)
mystring[i] = cmystring[i];
mystring[len] = '\0';
}
//复制构造
Mystring::Mystring(const Mystring& rhs){
len = rhs.getLen();
mystring = new char[len+1];
for(int i = 0; i<len;i++)
mystring[i] = rhs[i];
mystring[len] = '\0';
}
//析构
Mystring::~Mystring(){
delete[] mystring;
len = 0;
}
char& Mystring::operator[](int offset){
if(offset>len) //若超出最大长度,返回最后一位字符
return mystring[len-1];
else
return mystring[offset];
}
char Mystring::operator[](int offset) const
{
if (offset > len) //若超出最大长度,返回最后一位字符
return mystring[len - 1];
else
return mystring[offset];
}
//字符串连接+重载
Mystring Mystring :: operator +(const Mystring& rhs){
int totallen = len + rhs.getLen();
Mystring str(totallen);
int i = 0;
for(;i<len;i++)
str[i] = mystring[i];
for(int j = 0;j<rhs.getLen();i++,j++)
str[i] = rhs[j];
str[totallen] = '\0';
return str;
}
void Mystring::operator+=(const Mystring& rhs){
int totallen = len + rhs.getLen();
Mystring str(totallen);
int i = 0;
for(;i<len;i++)
str[i] = mystring[i];
for (int j = 0; j < rhs.getLen(); i++, j++)
str[i] = rhs[j];
str[totallen] = '\0';
*this = str;
}
Mystring &Mystring ::operator=(const Mystring &rhs)
{
delete[] mystring;
len = rhs.getLen();
mystring = new char[len + 1];
for (int i = 0; i < len; i++)
mystring[i] = rhs[i];
mystring[len] = '\0';
return *this;
}
测试:
int main()
{
Mystring s1("initial test");
cout << "S1:\t" << s1.GetMyString() << endl;
char *temp = "Hello World";
s1 = temp;
cout << "Now,S1 is replaced by Hello World" << endl;
cout << "S1:\t" << s1.GetMyString() << endl;
char s2[20];
strcpy(s2, "; I like you!");
cout << "S2:\t" << s2 << endl;
s1 += s2;
cout << "S1+S2:\t" << s1.GetMyString() << endl;
cout << "S1[4]:\t" << s1[4] << endl;
s1[4] = 'x';
cout<<"now s1[4] is repalced by x"<<endl;
cout << "S1:\t" << s1.GetMyString() << endl;
cout << "S1[999]:\t" << s1[999] << endl;
Mystring s3(" Another myString");
cout << "S3:\t" << s3.GetMyString() << endl;
Mystring s4;
s4 = s1 + s3;
cout << "S1+S3:\t" << s4.GetMyString() << endl;
return 0;
}