记录一些C++的语法方便日后查看。
1.C++初始化语法
C++中新增加了两种初始化语法,其中大括号初始化器需要C++11以上的实现,使用时可以加等号,也可以不加,而且大括号中可以不包含任何东西,这种情况下变量被初始化为0。
int x(100); int y = { 100 }; int z{ 100 }; int w{};//set w to 0
2.sizeof运算符和climits头文件
C++的数据类型的长度在不同系统和实现中可能有所区别,比如int类型通常为32位,但在某些系统中int为16位,通过sizeof运算符和climits头文件中的符号常量可以得到系统中各数据类型的长度和该类型能存储的最大与最小值。
sizeof可对类型名和变量名使用,对类型名使用时应将名称放在括号中,对变量名使用则不需要。
int n; //sizeof cout << sizeof(int) << endl; cout << sizeof n << endl; //climits cout << INT_MAX << endl;// output max of int cout << LLONG_MIN << endl; cout << USHRT_MAX << endl;
3.cout控制输出格式
输出不同进制:
int n = 23; cout << dec << n;//十进制 cout << oct << n;//八进制 cout << hex << n;//十六进制
控制输出位数和小数位数(需引入iomanip头文件)
double n = 243.56298; cout << setprecision(5) << n;//保留5位有效数字 cout << fixed << setprecision(2) << n;//保留小数点后2位
4.原始字符串
原始字符串中,字符表示的就是自己,忽略转义序列和单双引号的意义,将其作为字符串一部分,原始字符串以R为前缀,将"(和")作为界符。
如果需要在字符串中包含"(或)",可以在界符的双引号和括号间加入任意字符作为标记,这样结尾也必须加入这些字符。
cout << R"(asdfsd\''"\t\nsds)" << endl; cout << R"abc(sdasd")asds)abc" << endl;
5.结构位字段和共用体
C++可以指定使用特定位数存储的结构成员,还可以使用没有名称的字段提供间距。
struct Stu { int id : 4;//4 bits for id int : 4;//4 bits unused char sex : 1; };
共用体可以存储不同的数据类型,但同时只能存储其中一种,共用体的长度为其最大成员的长度。
union val { int IntVal; double DoubleVal; long LongVal; };
使用时在不同时间使用不同变量即可,共用体的好处是当数据项使用多种类型表示时,可以节省内存,用同一块内存存储不同类型变量。
val v; v.IntVal = 12;//store int cout << v.IntVal; v.DoubleVal = 34.55;//store double cout << v.DoubleVal;
可以把结构体和共用体结合使用,如果有一个结构成员需要使用不同的类型,可以在结构中使用匿名共用体。
访问时使用stu.id_num或stu.id_char即可。
struct Stu { string name; char sex; union //anonymous union { int id_num; char id_char[10]; }; };
6.Delete释放内存
int* pt = new int; int* ps = new int[10]; delete pt; delete[] ps;
(1)不要用delete释放不是new分配的内存
(2)不要用delete释放同一内存块2次
(3)如果用new为一个实体分配内存,使用delete释放,如果用new[ ]为数组分配内存,用delete[ ]释放。
(4)对空指针使用delete是安全的。
7.计时
使用头文件ctime实现计时,clock函数返回程序开始执行后所用的系统时间单位数,类型为clock_t,CLOCKS_PER_SEC常量表示每秒钟包含的系统单位时间数,将系统时间除以这个值即为秒数,将秒数乘以这个值,即为对应的系统单位时间数。据此可以编写如下指定时间的延时程序。
float second; cin >> second; clock_t Delay = second * CLOCKS_PER_SEC;//Get Clock Ticks To Delay clock_t Start = clock(); while (clock() - Start < Delay);//Delay Loop cout << "end" << endl;
8.cctype头文件
cctype头文件中有很多用于判断字符类型的函数
isalnum() 如果参数是字母数字,即字母或者数字,函数返回true
isalpha() 如果参数是字母,函数返回true
iscntrl() 如果参数是控制字符,函数返回true
isdigit() 如果参数是数字(0-9),函数返回true
isgraph() 如果参数是除空格之外的打印字符,函数返回true
islower() 如果参数是小写字母,函数返回true
isprint() 如果参数是打印字符(包括空格),函数返回true
ispunct() 如果参数是标点符号,函数返回true
isspace() 如果参数是标准空白字符,如空格、换行符、水平或垂直制表符,函数返回true
isupper() 如果参数是大写字母,函数返回true
isxdigit() 如果参数是十六进制数字,即0-9、a-f、A-F,函数返回true
tolower() 如果参数是大写字符,返回其小写,否则返回该参数
toupper() 如果参数是小写字符,返回其大写,否则返回该参数
9.输入类型不匹配时怎么办
int n; cin >> n;
如果程序接收一个整型输入,但用户输入了一个字符,会发生什么呢?
(1)n的值不变。
(2)不匹配的输入留在输入队列中。
(3)cin对象中的错误标记被设置
(4)对cin的调用返回false(被转为bool类型时)
当出现这种情况时,需要使用cin.clear()重置错误标记并清空错误输入,然后才能让用户重新输入。
while (!(cin >> n)) { cin.clear();//reset input while (cin.get() != '\n')continue;//get bad input cout << "Please Enter a number:"; }
10.简单文件IO
需包含头文件fstream
ofstream fout; fout.open("test.txt");//open file if (!fout.is_open())//Check Open { exit(EXIT_FAILURE); } fout << 12 << endl;//write 12 to file fout.close();//close file ifstream fin; fin.open("test.txt"); int n; fin >> n;//read a int to n fin.close();
要循环读取文件可以使用good()函数判断读取状态
int n; fin >> n; while (fin.good()) { fin >> n; }
11.函数指针
若目标函数原型为:const double* f1(const double a[], int n); 则要创建指向该函数的指针,只需将函数名替换为(*pa),使用auto可以更简单地创建,之后可以使用指针调用函数。
const double* (*p1)(const double*, int) = f1; auto p2 = f1; cout << *p1(a, 4) << endl; cout << *p2(a, 3) << endl;
要创建一个包含三个函数指针的数组如下:
const double* (*pa[3])(const double*, int) = {f1,f2,f3};
12.函数模板
template<typename Any>//You can Use Class instead of typename void Swap(Any& a, Any& b) { Any temp; temp = a; a = b; b = temp; }
可以针对某个类型提供具体的函数定义——称为显式具体化,编译器将使用该定义而不再寻找模板。
template<> void Swap<int>(int& a, int& b)//<int> can be ignored { cout << "This is Int Swap"; }
在编写模板函数时,有时并不知道在声明中应使用哪种类型,可以使用decltype关键字声明和括号内表达式相同类型的变量。
template<class T1,class T2> void fun(T1 x,T2 y) { decltype(x + y) sum = x + y;//The type of sum is same as x+y }
但如果返回值是x+y类型怎么办呢,由于确定返回值时未声明x和y,所以无法使用decltype解决,C++新增了使用auto用于函数定义的方法,可将返回类型移到参数声明后面,称为后置返回类型。
auto fun1(int x, float y)->double;
通过这种语法结合decltype,就可以解决返回值类型未知的问题:
template<class T1,class T2> auto fun(T1 x,T2 y)->decltype(x+y) { decltype(x + y) sum = x + y; return sum; }