1. c++常见字符函数
头文件:<cctype>
isdigit(ch):数字判读
isalpha(ch):字母判断
isalnum(ch):数字或字母判断
islower(ch):小写字母判断
isupper(ch):大写字母判断
isspace(ch):空格判断
tolower(ch):返回小写形式
toupper(ch):返回大写形式
2. string对象的简单函数
头文件:<string>
length():返回字符个数
size():同length()
at(index):返回指定位置字符,从0开始.
3. 连接字符串
string s3 = s1+s2
s2 += s1
string s3 = "AB" + "CD" 是错误的;
string s3 = s1 + "AB" + "CD" 是可以的;
string s2 = "AB" + s1是可以的。
4. 读取字符串
cin >> string >> endl; 遇到空白字符结束
getline(cin, string, delimitCharacter); 遇到delimitCharacter结束
getline(cin, string); 默认终止字符是'\n'
对比 读取C字符串/字符数组
cin.getline(char array[], int size, char delimitChar) ;
cin.getline(char array[], int size) ; // 默认终止字符是‘\n’
最后一个字符是空终结符'\0'
5. 格式化控制台输出(流操作)
头文件:<iomanip>
setpecision(n):设置浮点数精度,n是小数点前后总位数,会四舍五入,如果后面是0会省略
持续性的,直到下一次精度改变之前一直有效。
fixed:显示指定小数位数的浮点数(避免科学计数法)
若setpresion(n)之前有fixed,n表示小数点之后的位数
showpoint:以零补足小数位数
setw(width>:指定打印字段宽度,包括小数点; 一次性的,只影响下一次输出
left:调整输出到左边
right:调整输出到右边(默认方式); 持续性的
6. 简单文件输入输出
头文件:<fstream>
*写入文件
// detail omitted
ofstream output;
output.open("filename.txt");
// 如果可选择, 也可用以下方式
// ofstream output("filename.txt");
outputt << "ABC" << " " << "CD" << endl;
output.close; // 必要的,保证程序退出之前数据已写入文件
**读取文件
// detail omitted
ifstream input;
input.open("faliname.txt");
// 如果可选择,可使用以下方式
// ifstream input("filename.txt");
input >> var1;
input >> var2 >> var3;
input.close();
***eof()
eof()返回true时表示已经读取到文档末尾;
7. 随机数srand()
头文件:<cstdlib>(for rand and srand functions); <ctime>(for time function)
RAND_MAX: 平台决定的整数;
rand()生成0~RAND_MAX之间的随机整数;
srand(seed)改变种子值;
一般用srand(time(0));
8. 命名常量
const关键字
const double PI = 3.14159; // 默认
const float PI = 3.14159f; // float型, F/f
const long double PI =3.14159L ; // long double型, L/l
9. 循环控制
计数控制循环(counter-controlled loop)
用户确认控制(confirmation)
标记值控制(sentinel value)
不要在循环继续条件中使用浮点数的相等性进行判定。
10. 输入输出重定向
输入:SentinelValue.exe < input.txt
输出:SentinrlValue.exe > output.txt
从输入到输出:SentinelValue.exe < input.txt > output.txt
11. 缺省参数
带缺省的参数值应该放在参数列表的末尾;
void func(int x, int y = 1, int z = 2); // 合法
void func(int x =1, int y, int z = 2); // 非法
调用函数时,若一个参数未给出,那么其之后的也不应该给出。
对 void func(int x, int y = 1, int z = 2)
func(1); // 合法,其后参数y和z分别是1,2
func(1, 3); // 合法, 其后参数z为缺省2
func(1, , 4); // 非法
12. 引用传递和值传递
对对象来说,引用传递比值传递更有效,因为对象可能占据大量内存;
对int和double类型来说,两者区别是微不足道的。
对对象来说,可以使用常量引用参数来提高效率:如 int max(const string& s1);
13. 函数抽象
函数抽象(function abstraction)就是将函数的使用和实现分离。实现细节被封装在函数内,对调用函数的用户隐藏,这就是信息隐藏(information hiding)或者封装(encapsulation)。
14. 逐步求精
编写大程时,使用分治(divide and conquer)策略或者逐步求精(stepwise refinement),即将问题分成若干子问题。子问题还可以进一步分解为更小、更易处理的问题。
15. 防止函数修改传递参数的数组
void p(const int list[], int arraySize);
如果函数f1中定义了一个const变量,在这个参数又被传递给了另一个函数f2,那么f2中声明的对应参数也必须为const类型,确保一致性。否则编译器会报错。
16. 数组作为函数值返回
向函数传递一个专门用于返回的数组;事实上,不需要return,调用函数内的数组自身会改变,因为传入的是地址,且没有const。
void reverse (const int list[], int newList[], int arraySize);
17. C字符串函数
头文件<cstring>; size_t是一个C++类型,一般相当于unsigned int
size_t strlen(char s[])
strcpy(char s1[], const s2[]); //s2必须有零终止符
strncpy(char s1[], const char s2[], size_t n)
strcat(char s1[], const char s2[]); //s2必须有零终止符
strncat(char s1[], const char s2[], size_t n)
int strcmp(char s1[], const char s2[])
int strncmp(char s1[], const char s2[], size_t n)
头文件<cstdlib>
int atoi(char s[])
double atof(char s[])
long atol(char s[])
void itoa(int value, char s[], int radix) ; // radix是基数, 为10表示十进制
18. 数组不会自动初始化。当前面的进行初始化之后,后面的自动变为0。
19. string 类
* 构造字符串
string s = "Hello";
string s("Hello");
string s; //空
char s1[] = "Hello"; string s(s1);
* 追加字符串
append(string s);
append(string s, int index, int n);
append(string s, int n);
appeng(int n, char ch);
s, index, n, ch
s1.copy(string s2, int n, int index); // 从s1的index开始复制n个字符到s2,有多少覆盖s2多少,s2未被覆盖的不变
* 字符串赋值
assign(char s[]);
assign(string s);
assign(string s, int index, int n);
assign(string s, int n);
assign(int n, char ch);
* 函数at,clear, erase, empty
at(int index); // 返回char
clear(); // 清空
erase(int index, int n); // 删除指定部分
empty(); // 返回bool
* 函数length, size, capacity, c_str, data
length()、size(): 返回字符数
capacity(): 返回分配空间大小
c_str(), data():返回c字符串
* 字符串比较
compare(string s);
compare(int index, int n, string s);
* 获取子串
substr(int index, int n);
substr(int index);
* 字符串搜索
find(char ch);
find(char ch, int index);
find(string s);
find(string s, int index);
* 字符串插入和替换
insert(int index, string s);
insert(int index, int n, char ch);
replace(int index, int n, string s);
* 字符串运算符
[]
=
+
+=
<<
>>
==, !=, <, <=, >, >=
* 数字转字符串
头文件 <cstdlib>
itoa(int value, char s[], int radix);
头文件 <sstream>
stringstream ss;
ss<<3.1415
string s = ss.str()
* 字符串分割
头文件 <sstream>
string text("welcome to c++");
stringstream ss(text);
string s1, s2, s3;
ss>>s1>>s2>>s3;
20. 静态变量/类变量, 静态函数
static int numberOfObjects;
static int getNumbrOfObjects();
静态变量和函数可以通过任意类对象访问,也可以通过类名访问;
circle1.getNumberOfObjects();
Circle::getNumberOfObjects();
Circle::numberOfObjects;
21. const再总结
int function(const class& object); // 常量引用参数
int function() const; // 只读成员函数,只有实例成员函数才能被定义为只读成员函数
void a(const Class&c){
cout<<c.getNum()<<endl;
} // getNum()必须定义为const, 即只读成员函数
22. 有用的数组函数
头文件 <algorithm>
int list[] = {4, 2, 3, 6, 5, 1};
min_element(list, list+6);
max_element(list, list+6);
sort(list, list+6); // 排序
random_shuffle; // 随机洗牌
find(list, list+6, key); // 未找到返回最后元素后一个位置的指针
注意: 这些函数返回值是指针
23. const int 和 int const
修饰变量
//没有区别
const int p = 1; //p不能被修改
p = 0; //编译出错
int const q = 2; //q不能被修改
q = 0; //编译出错
修饰指针
const int a = 1;
const int b = 2;
const int c = 3;
const int *p = &a; //*p不能被修改
*p = b; //编译出错
int* const q = &b; //q不能被修改
q = &c; //编译出错
int const *r = &c; //*r不能被修改
*r = a; //编译出错
24. c++ 命名空间
在c++中,名称(name)可以是符号常量、变量、函数、结构、枚举、类和对象等等。工程越大,名称互相冲突性的可能性越大。另外使用多个厂商的类库时,也可能导致名称冲突。为了避免,在大规模程序的设计中,以及在程序员使用各种各样的C++库时,这些标识符的命名发生冲突,标准C++引入关键字namespace(命名空间/名字空间/名称空间),可以更好地控制标识符的作用域。
* 命名空间的定义 关键字namespace
namespace A {
int a = 100;
}
namespace B {
int a = 200;
}
* 命名空间只能在全局范围内定义
// 这是错误的
void test(){
namespace A{
int a = 100;
}
}
* 命名空间可以嵌套
namespace A {
int a = 1000;
namespace B {
int a = 2000;
}
}
void test()
{
cout<<"A中的a = "<<A::a<<endl; //1000
cout<<"B中的a = "<<A::B::a<<endl; //2000
}
* 命名空间是开放的,可以随时把新的成员加入已有的命名空间中
namespace A {
int a = 100;
int b = 200;
}
//将c添加到已有的命名空间A中
namespace A {
int c = 300;
}
* 命名空间 可以存放 变量 和 函数
namespace A {
int a=100;//变量
void func()//函数
{
cout<<"func遍历a = "<<a<<endl;
}
}
void test()
{
//变量的使用
cout<<"A中的a = "<<A::a<<endl;
//函数的使用
A::func();
}
* 命名空间中的函数 可以在“命名空间”外 定义
namespace A {
int a=100;//变量
void func();
}
void A::func()//成员函数 在外部定义的时候 记得加作用域
{
//访问命名空间的数据不用加作用域
cout<<"func遍历a = "<<a<<endl;
}
void funb()//普通函数
{
cout<<"funb遍历a = "<<A::a<<endl;
}
void test()
{
A::func();
funb();
}
* 无名命名空间,意味着命名空间中的标识符只能在本文件内访问,相当于给这个标识符加上了static,使得其可以作为内部连接(了解)
namespace{
int a = 10;
void func(){
cout<<"hello namespace"<<endl;
}
}
void test(){
//只能在当前源文件直接访问a 或 func
cout<<"a = "<<a<<endl;
func();
}
* 命名空间别名
namespace supercalifragilistic {
void f();
}
namespace short = supercalifragilistic;
short::f();
25. 对象数组调用析构函数顺序
如果定义了一个数组arr[5], 存储对象,则调用析构函数的顺序是从后往前一个个调用,这里便是先调用arr[4]的析构函数,再调用arr[3]的析构函数……
有如下代码:
#include<iostream>
using namespace std;
class TEST
{
int num;
public:
TEST( int num=0);
void increment( ) ;
void set(int i){
num = i;
}
~TEST( );
};
TEST::TEST(int num) : num(num)
{
cout << num << endl;
}
void TEST::increment()
{
num++;
}
TEST::~TEST( )
{
cout << num << endl;
}
int main( )
{
TEST array[2];
array[1]. set(2);
cout << "以下是会调用析构函数,会先调用array[1]的" << endl;
array[0].increment();
array[1].increment();
return 0;
}
运行结果:
26. 总是定义虚析构函数是一个好习惯!