C++学习笔记(1)
C++学习笔记(1)
泛型模板排序
template<typename T> //定义一个泛型类型T
/// <summary>
/// 定义一个模板方法
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="a"></param>
/// <param name="b"></param>
void mySwap(T& a, T& b)
{
T temp = a;
a = b;
b = temp;
}
template<class T>
void mySort(T arry[], int len)
{
for (int i = 0; i < len; i++)
{
int max = i;
for (int j = i + 1; j < len; j++)
{
if (arry[max] < arry[j]) { max = j; }
}
if (max != i)mySwap(arry[max], arry[i]);
}
}
template<class T>
void mySort2(T arry[], int len)
{
for (int i = 0; i < len; i++)
{
int min = i;
for (int j = i + 1; j < len; j++)
{
if (arry[min] > arry[j]) { min = j; }
}
if (min != i)mySwap(arry[min], arry[i]);
}
}
#include<iomanip>
void test5()
{
char ca[] = "adkblnvg";
int len = sizeof(ca) / sizeof(ca[0]) - 1;
cout << setw(20) << "排序前 " << ca << endl;
mySort(ca,len);
cout << setw(20) <<"从大到小排序后 " << ca << endl;
mySort2(ca, len);
cout << setw(20) << "从小到大排序后 " << ca << endl;
cout << "----------------------------------------\n";
int ai[] = {1,5,9,6,3,4,7,2,8,0};
len = sizeof(ai) / sizeof(ai[0]) - 1;
cout << setw(20) << "排序前 " ;
for (size_t i = 0; i < len; i++)
{
cout << ai[i] << ",";
}
cout << endl;
mySort(ai, len);
cout << setw(20) << "从大到小排序后 " ;
for (size_t i = 0; i < len; i++)
{
cout << ai[i] << ",";
}
cout << endl;
mySort2(ai, len);
cout << setw(20) << "从小到大排序后 " ;
for (size_t i = 0; i < len; i++)
{
cout << ai[i] << ",";
}
cout << endl;
}
运行结果
模板和泛型template
template<typename T> //定义一个泛型类型T
/// <summary>
/// 定义一个模板方法
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="a"></param>
/// <param name="b"></param>
void mySwap(T &a,T &b)
{
T temp=a;
a = b;
b = temp;
}
//模板测试
void test4()
{
char a = 'A',b='B';
mySwap(a, b);//隐式类型推导
cout << "a=" << a << " b=" << b << endl;
string s1 = "黑马程序员";
string s2 = "C++教程从0到1入门编程";
mySwap(s1,s2);//隐式类型推导
cout << "s1=" << s1 << " s2=" << s2 << endl;
double b1 = 3.14, b2 = 5.678;
mySwap<double>(b1, b2);//显式指定类型<T>
cout << "b1=" << b1 << " b2=" << b2 << endl;
}
运行结果
模板定义:将类型参数化,提高代码复用性;模板关键字template,
模板使用方法:1自动类型推导2显式指定类型
模板注意事项:
- 自动类型推导,必须推导出一致的数据类型T,才可以使用模板;
- 模板必须确定出T的类型,才可以使用;
-------------------------------------------------------------
参数传递的三种方式
- 值传递
- 引用传递
- 指针传递
void test14()
{
int a = 666, b = 888;
cout << "数值交换前" << " a=" << a << " b=" << b << endl;
swapv(a, b);
cout<<"数值交换后" << " a=" << a << " b=" << b << endl;
cout << "-----------------------------" << endl;
int* pa = &a; int* pb = &b;
cout << "指针交换前" << " a=" << a << " b=" << b << endl;
swapp(pa,pb);
cout << "指针交换后" << " a=" << a << " b=" << b << endl;
cout << "-----------------------------" << endl;
int& ra = a; int& rb = b;
cout << "引用交换前" << " a=" << a << " b=" << b << endl;
swapr(ra,rb);
cout << "引用交换后" << " a=" << a << " b=" << b << endl;
}
运行结果
引用&测试
void test13()
{
int a = 100;
int& b = a;
cout << "b=" << b << " a=" << a << endl;
cout << "(int)&b=" << (int)&b << " (int)&a=" << (int)&a << endl;
//b = 100 a = 100
//(int)&b = 13629100 (int)&a = 13629100
a++;
cout << "b=" << b << " a=" << a << endl;
cout << "(int)&b=" << (int)&b << " (int)&a=" << (int)&a << endl;
b++;
cout << "b=" << b << " a=" << a << endl;
cout << "(int)&b=" << (int)&b << " (int)&a=" << (int)&a << endl;
int* p = &a;
(*p)++;
cout << "b=" << b << " a=" << a << endl;
cout << "(int)&b=" << (int)&b << " (int)&a=" << (int)&a << endl;
//int& c;//错误,引用不可以先声明,再赋值
//int* p1;//正确,指针可以先声明,再赋值
int c = 66;
b = c;
cout << "b=" << b << " a=" << a << " c=" << c << endl;
cout << "(int)&b=" << (int)&b << " (int)&a=" << (int)&a << " (int)&c=" << (int)&c << endl;
}
运行结果
b虽然被赋值成了c,但是b的地址依然指向第一次赋值的a,只是把c的值复制过来了;
可见引用的地址不可改变,相当于指针常量int * const p;
指针常量可以更改指针所指向的值,而不可以更改指针的指向(地址);
编译器自动类型转换int--double--int
void cheers(uint n)
{
for (size_t i = 0; i < n; i++)
{
cout << "Cheers!" << endl;
}
}
double cube(double side)
{
return side * side * side;
}
void test12()
{
//编译器:首先将int类型2转换为double类型2.0,以匹配cube函数的类型要求
//编译器:将cube(2)的double类型返回值8.0转换为usigned int类型8,以匹配cheers函数的类型要求;
cheers(cube(2));
}
运行结果
数组的替代选项---模板类vector、array
void test11()
{
unsigned short n = 10;
const unsigned short m =10;
vector<int> vi;
vector<double>vd(n);
array<int, 5> ai;
//m必须是常量,而不能是变量,可以是一个数值10,或者const unsigned int类型的变量
array<double, m> ad = { 1.0,2.0,3.0,4.0 };
//-------------------------------------
double a1[4] = { 1.1,2.2,3.3,4.4 };//静态数组,必须在定义时指定长度
//a1[-1] = -1.0;//错误,索引值超出索引范围0-3
//double a2[];//错误,静态数组必须在定义时指定长度
//double a2[4]=a1;//错误,应该使用{}初始化聚合对象
//a2 = a1;//错误,应该使用{}初始化聚合对象
vector<double> vd1={ 2.22,3.25,5.65,6.74 };
vector<double>vd2{ 2.22,3.25,5.65,6.74 };//可以省略等号进行便捷初始化
vector<double> vd3(4);//不能直接初始化
vd3= { 2.22,3.25,5.65,6.74 };
vector<double>vd4(3);
vd4[0] = 1.23;
vd4[1] = 3.22;
cout << "vd4[0] " << vd4[0] << endl;
cout << "vd4[1] " << vd4[1] << endl;
cout << "vd4[2] " << vd4[2] << endl;
cout << "-------------------------" << endl;
vector<double> vd5 = vd4;
cout << "&vd4[i] " << "&vd5[i]" << endl;
cout << &vd4[0] <<" " << &vd5[0] << endl;
cout << &vd4[1] << " " << &vd5[1] << endl;
cout << &vd4[2] << " " << &vd5[2] << endl;
array<double, 4> arr1{ 5.0,6.0,7.0,8.0 };
//array<double, 5> arr2=arr1;//错误,必须长度相等才可以赋值
//array<long double, 4>arr3 = arr1;//错误,必须类型相同才可以赋值
array<double, 4>arr4 = arr1;
cout << "-------------------------" << endl;
cout << "&arr4[i] " << "&arr1[i]" << endl;
cout << &arr4[0] << " " << &arr1[0] << endl;
cout << &arr4[1] << " " << &arr1[1] << endl;
cout << &arr4[2] << " " << &arr1[2] << endl;
}
运行结果
vector之间可以直接=赋值,赋值后的vector是原vector的一个拷贝;
array之间可以直接=赋值,必须满足两个条件
1、array长度必须相等;
2、元素类型必须完全相同;
赋值后的array是原array的一个拷贝;
指向指针的指针
struct years
{
int year;
bool isLeepYear;
};
void test10()
{
years y1, y2, y3;
y1.year = 1998; //成员运算符,用变量名访问成员
years* py = &y2;
py->year = 1999; //间接成员运算符,用指针访问成员
years arry[3]; //结构体数组
arry[0].year = 2003; arry[1].year = 2004; arry[2].year = 2005;
cout<<"arry->year " << arry->year << endl;
cout << "arry[1].year " << arry[1].year << endl;
cout << "arry->year " << arry->year << endl;
cout << "-------------------------"<<endl;
years* arryp[3] = { &y1,&y2,&y3 };//结构体指针数组
cout << "arryp[1]->year " << arryp[1]->year << endl;
//数组元素本身是指针(指向结构体),
//而数组名也是指针(指向数组的第一个元素),
//所以这里的数组名是指向指针的指针years**
years** ppa = arryp;
auto ppb = arryp;
cout << "-------------------------" << endl;
cout << "(*ppa)->year " << (*ppa)->year << endl;
cout << "(*(ppb + 1))->year " << (*(ppb + 1))->year << endl;
}
运行结果
字符串测试
typedef unsigned int uint;
char* getname()
{
char temp[80];
cout << "Enter name (less than 80 characters)" << endl;
cin >> temp;
uint len = strlen(temp);
cout << "len=" << len << endl;
//通过一个小的内存空间来存放输入,以节省内存
char* pc = new char[len + 1];
//len表示字符串中字符的个数,而没有包含字符串结束标识"\0"
//字符串所占字节数应当包含结束标识"\0",所以为len+1
//strcpy已过时弃用,这里使用更加安全的strcpy_s
//第一个参数表示拷贝的目标指针,char*类型
//第二个参数表示需要拷贝的字节数,包含结束标识"\0",所以为len+1,
// rsize_t类型,rsize_t类型属于size_t类型,而size_t类型属于unsigned int类型
// rsize_t类型实际就是unsigned int类型,二者等效
//第三个参数表示需要拷贝的数据源const char*类型
strcpy_s(pc, len+1, temp);
return pc;
}
void test9()
{
char* name;
name = getname();
cout << "name=" << name << " name at=" << (int*)name << endl;
//只能释放new的资源
delete name;
name = getname();
cout << "name=" << name << " name at=" << (int*)name << endl;
//只能释放new的资源
delete name;
}
运行结果
打开文件是否成功的测试
void test2()
{
ifstream instream;
instream.open("in.dat");
string s = instream.fail() ? "fail" : "succeed";
cout <<"instream.fail()? " << instream.fail() << endl;
cout << "instream.fail()? " << s << endl;
if (!instream.fail())instream.close();
instream.open("inFile.dat");
s = instream.fail() ? "fail" : "succeed";
cout << "instream.fail()? " << instream.fail() << endl;
cout << "instream.fail()? " << s << endl;
if (!instream.fail())instream.close();
}
运行结果
文件流测试
#include<iostream>
#include <fstream>
using namespace std;
void test1()
{
ifstream inStream;
ofstream outStream;
inStream.open("inFile.dat");
outStream.open("outFile.dat");
int first, second, third;
inStream >> first >> second >> third;
cout << "first=" << first << " second=" << second << " third=" << third << endl;
cout << "sum=" << first + second + third << endl;
outStream << "first=" << first << " second=" << second << " third=" << third << endl;
outStream << "sum=" << first + second + third << endl;
inStream.close();
outStream.close();
}
运行结果