c++primer notebook

一、基础

1. 循环读入数据

读取数量不定的输入数据

void test01() {
	int value = 0;
	while (cin >> value)
	{
// 当遇到文件结束符或遇到一个无效输入(比如读到的值不是一个整数),istream对象状态变为无效,条件为假
        cout << value << endl;
	}
}
2. 重定向

使用文件重定向连接标注你输入和标准输出

command < filename1 > filename2

Project4.exe < infile.txt > outfile.txt
  • 用double 而不是float
  • 无符号数的减法结果必须要确保为正,尤其小心死循环
  • \123 八进制字符 \x1234 十六进制字符
  • 列表初始化: int value{0}; 优点:用列表初始化如果初始值存在丢失信息的风险,编译器会报错
3. extern:声明

extern作用: 声明一个变量而非定义,用于分文件编译。

变量的定义只能出现在一个文件中,声明可以出现在多个文件中

extern int j; //声明i而非定义
int j; // 声明并定义j
extern int j = 10; //定义
4. constexpr:常量

常量表达式:值不改变并且在编译的时候就可以得到结果

constexpr作用:将变量声明为该类型以便有编译器来验证变量是否为常量表达式。声明为constexpr的变量一定是个常量,而且必须用常量表达式初始化,否则会报错

const int a =10; //Yes ,是常量表达式
const int a = getsize();//No,不是常量表达式

constexpr int a = 10; //a为常量
constexpr int a = getsize();//只有当getsize是个constexpr函数(在编译时就可以得到结果)时,才不报错

//如果constexpr声明中如果定义了指针,限定符只对指针有效
const int *p = nullptr;
constexpr int *q = nullptr; //
5. typedef :类型别名
typedef double wages; //wages是double的同义词
wages hourly, weekly;

typedef wages base, *p; // base是double的同义词,p是double*的同义词

using SI = Sales_item; // SI是Sales_item的同义词----新方法:别名声明
SI item;
6. auto : 类型说明符

auto : 编译器通过初始值分析表达式所属的类型

auto item = val1 + val2; // 自动根据val1和val2推断item类型
auto i=0, *p = &i; // 正确,i和*p是同一个类型
auto sz=0, pi = 3.14; //错误,auto在一条语句中声明多个变量时,要求类型一致
7. decltype : 类型说明符

decltype : 编译器分析表达式并得到其类型,但不实际计算表达式的值

decltype(f()) sum = x;  //sum的类型由f返回类型决定,但不调用函数
decltype(s.size()) index = 0;
8. 指针的引用
int i = 42;
//int *&r = &i; 报错,不能定义指向引用的指针

int *p;
int *&r = p;
p = &i;
cout << *r; //令i=0
9. 多文件常量共享

const声明和定义中都加入extern

// 文件1
extern const int bufsize = 10;
// 文件2
extern const int bufsize;
10. 常量引用
int i = 42;
const int &r1 = i; //Yes,但是不可以通过r1修改i的值
const int &r2 = 42; //Yes 常量引用可绑定非常量对象、字面值和表达式
11. 常量指针和指针常量
//指针常量,值是常量
const double p = 3.14;
double *p1 = &p; //No
const double *p2 = &p; //Yes,但不能通过p2改p

//常量指针,地址是常量
int a = 0;
int const *p3 = &a;
12. for (declaration: expression) statement
for(declaration : expression) statement
for(元素:序列) 操作 //遍历每个元素,并对序列中的每个值执行操作
string c{"hello"};
for(auto &i:c){cout << i;}
13. 迭代器类型
vector<int>::iterator it1;       // it1可读写vector元素
vector<int>::consti_iterator it2;// it2只能读vector元素
auto it3 = v.cbegin();  //it3类型为vector<int>::consti_iterator,只读操作最好用常量类型

for(auto it = text.cbegin();it != text.cend() && !it->empty();++it}{
    cout << *it << endl;
}
14. 复杂数组声明
int a[10];
int * p1[10];         // 存放10个指针的数组
int (*p2)[10];        // p是指针,指向存放10个int的数组
int(&r)[10] = a;      // r是引用,引用含有10个int的数组
int *(&arr)[10] = p1; //arr是引用,引用一个数组,该数组是存放10个指针的数组。
15. 数组索引类型

数组下标类型size_t,无符号类型,足够大,可以表示内存中任意对象的大小

int scores[10] = {};
for (auto i: scores){
	cout << typeid(i).name()<< " " <<i << endl;
}
16. 标准库函数 begin, end

需要包含头文件 #include

int arr[] = {0,1,2,3,4,5,6};
int *beg = begin(arr);
int *last = end(arr); // 指向尾元素的下一个位置
cout << *beg; 
cout << *(last-1);
17. 指针下标的表示
int a[] = {1,2,3,4,5,6};
int *p=a+1;
cout << p[0];
18. 标准库函数string

尽量还是使用string对象,而不是标准库函数,因为常常会出现越界的情况

char a[] = "hello";
char b[] = "areyouok";
strlen(a);    // 返回字符串的长度
strcmp(a,b);  // 比较两个字符换是否相等a>b返回正
strcat(a, b); // 拼接字符串,返回a
strcpy(a, b); // 将b拷贝给a,返回a	
// 混用数组字符串和string对象
string a("areyouok");
const char *str = a.c_str();
char b[] = { 1,2,3,4,5 };
vector<char> vec(begin(b), end(b));
19. 多维数组
int a[3][4] = {
	{1,2,3,4},
	{2,3,4,5},
	{3,4,5,6}
};

int (&b)[4] = a[1];   // b 为四元数组的引用
int(*c)[4] = &a[1];   // c 为指向四元数组的指针
int(*d)[4] = a;       // d 为指向四元数组的指针

// 用for循环处理多维数组,必须用到引用类型,否则无法通过编译
for (auto &row :a){
	for (auto &col : row){
		cout << col << " ";
	}
	cout << endl;
}

for (auto &row:a){
	for(auto col:row)
		cout << col << " ";
	cout << endl;
}

// 指针和多维数组
for (auto p=a;p!=a+3;p++){   // p是指向四个元素的数组,
	for (auto q = begin(*p);q!=end(*p);q++){  // q是指向
		cout << *q;
	}
	cout << endl;
}	
20. 运算符
  • 递增递减运算符

    优先使用++a,而不是a++型

*p++; // *(p++) 将p值+1后,返回p指向的初始值
cout << *it++ << endl;
  • 成员访问运算符

    string s = "hello", *p = &s;
    auto n = s.size();
    n = (*p).size();
    n = p->size();
    
  • 条件运算符

    注意: 当其他表达式子里有条件运算符出现时,通常需要加上括号

    int  grade = 75;
    string finalgrade = (grade > 90) ? "great": ((grade > 60)?"good" : "bad");	
    
  • sizeof运算符

    int a;
    sizeof(int);
    sizeof a;
    
21. 异常处理
throw runtime_error("Data must be equal");
try{
    //
}catch(runtime_error err){
    cout << err.what();
}

二、函数

1. 局部静态对象

有些时候,有必要令局部变量的声明周期贯穿函数调用之后的时间,可以将局部变量定义成static类

size_t count_calls() {
	static size_t count=0;
	return ++count;
}

int main(int argc, char ** argv) {
	for (size_t i = 0; i < 10; i++)	{
		cout << count_calls() << endl;
	}
}
2. 指针形参传递
void reset(int *p) { // 当调用函数时,形参p指针拷贝了原来的指针的地址,是两个不同的指针
	*p = 10;          // 修改形参p指向的值,会修改原来指针的值
	p = nullptr;     // 修改形参p的指向,不会对原来的指针造成影响
}

int main(int argc, char ** argv) {
	int i = 42;
	reset(&i);
	cout << "i=" << i << endl;
	system("pause");
	return 0;
}
3. 引用形参传递

值传递和引用传递都可以作为函数的形参。

当某种类型不支持拷贝操作时,比如IO,函数只能通过引用形参访问该类型对象。

当函数无须修改引用形参的值时,最好用常量引用。

bool isShorter(const string &s1, const string &s2){
	return s1.size()+s2.size();
}

函数如何返回多个信息?

方法一:定义一个新的数据类型,让它包含多个成员

方法二:给函数传入额外的引用实参,令其保存需要的信息

4. const形参和实参
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章