0
点赞
收藏
分享

微信扫一扫

c++ primer 书代码学习

路西法阁下 2022-01-06 阅读 106

#include <iostream>
#include <string>

using namespace std;
class Sales_item
{
	friend std::istream& operator>>(std::istream&, Sales_item& );
	friend std::ostream& operator<<(std::ostream&, const Sales_item&);
	friend bool operator<(const Sales_item&,const Sales_item&);
	friend bool operator==(const Sales_item&,const Sales_item&);
public:
	Sales_item() = default;
	Sales_item(const std::string& book): bookNo(book){}
	Sales_item(std::istream& is){is >> *this; }
public:
	Sales_item& operator+=(const Sales_item&);
	std::string isbn() const { return bookNo; }
	double avg_price() const;
private:
	std::string bookNo;
	unsigned units_sold = 0;
	double revenue = 0.0; 
public:
};

inline bool compareIsbn(const Sales_item& lhs, const Sales_item& rhs)
{
	return lhs.isbn() == rhs.isbn();
}

Sales_item operator+(const Sales_item&,const Sales_item&);

inline bool operator==(const Sales_item& lhs,const Sales_item& rhs)
{
	return lhs.units_sold == rhs.units_sold && 
		   lhs.revenue == rhs.revenue && 
		   lhs.isbn() == rhs.isbn();
}

inline bool operator!=(const Sales_item& lhs,const Sales_item& rhs)
{
	return !(lhs == rhs);
}

Sales_item& Sales_item::operator+=(const Sales_item& rhs)
{
	units_sold += rhs.units_sold;
	revenue += rhs.revenue;
	return *this;
}

Sales_item operator+(const Sales_item& lhs,const Sales_item& rhs)
{
	Sales_item ret(lhs);
	ret += rhs;
	return ret;
}

std::istream& operator>>(std::istream& in, Sales_item& s)
{
	double price;
	in>>s.bookNo>>s.units_sold>>price;
	if(in)
		s.revenue = s.units_sold * price;
	else
		s = Sales_item();
	return in;
}

std::ostream& operator<<(std::ostream& out,const Sales_item& s)
{
	out<<s.isbn()<<" "<<s.units_sold<<" "
	   <<s.revenue<<" "<<s.avg_price();
	return out;
}

double Sales_item::avg_price() const
{
	if(units_sold)
		return revenue / units_sold;
	else
		return 0;
}


#include <string>
#include <iostream>

class Sales_data
{
	friend Sales_data add(const Sales_data&, const Sales_data&);
	friend std::ostream &print(std::ostream&, const Sales_data&);
	friend std::istream &read(std::istream&, Sales_data&);
public:
	// 构造函数
	Sales_data() = default;
	Sales_data(const std::string &s):bookNo(s){}
	Sales_data(const std::string &s, unsigned n, double p):
			   bookNo(s),units_sold(n),revenue(p*n){}
	Sales_data(std::istream &);

	// 对 Sales_data 对象的操作
	std::string isbn() const { return bookNo; }
	Sales_data& combine(const Sales_data&);
	double avg_price() const;
private:
public:
	std::string bookNo;
	unsigned units_sold = 0;
	double revenue = 0.0;
};

// 非成员 Sales_data 接口函数
Sales_data add(const Sales_data&, const Sales_data&);
std::ostream &print(std::ostream&, const Sales_data&);
std::istream &read(std::istream&, Sales_data&);

inline bool compareIsbn(const Sales_data &lhs,const Sales_data &rhs)
{
	return lhs.isbn() < rhs.isbn();
}

Sales_data::Sales_data(std::istream &is)
{
	// read 会将事务从 is 读取到此对象中
	read(is, *this);
}

double Sales_data::avg_price() const
{
	if(units_sold)
		return revenue / units_sold;
	else
		return 0;
}

// 将给定 Sales_data 的值添加到此对象中
Sales_data& Sales_data::combine(const Sales_data &rhs)
{
	units_sold += rhs.units_sold; //将 rhs 的成员添加到
	revenue += rhs.revenue; // “this”对象的成员
	return *this; // 返回调用函数的对象
}

Sales_data add(const Sales_data& lhs, const Sales_data &rhs)
{
	Sales_data sum = lhs;// 将数据成员从 lhs 复制到 sum
	sum.combine(rhs);//将 rhs 中的数据成员添加到 sum
	return sum;	
}

// 交易包含 ISBN、售出的副本数量和销售价格
istream& read(istream &is, Sales_data &item)
{
	double price = 0;
	is >> item.bookNo>>item.units_sold>>price;
	item.revenue = price * item.units_sold;
	return is;
}

ostream& print(ostream &os, const Sales_data &item)
{
	os << item.isbn()<<" "<<item.units_sold<<" "
	   << item.revenue <<" "<<item.avg_price();
	return os;
}

// 返回最大公约数
int gcd(int v1,int v2)
{
	while(v2)
	{
		int temp = v2;
		v2 = v1 % v2;
		v1 = temp;
	}
	return v1;
}

// val 的阶乘是 val * (val - 1) * (val - 2) 。 . . * ((val - (val - 1)) * 1)
int fact(int val)
{
	int ret = 1;
	// 在我们计算结果时保存结果的局部变量
	while(val > 1)
		ret *= val--;
	// 将 ret * val 赋值给 ret 并递减 val
	return ret;
	// 返回结果
}

// 阶乘的递归版本:
// 计算 val!,即 1 * 2 * 3 。 . . * 价值
int factorial(int val)
{
	if(val > 1)
		return factorial(val - 1) * val;
	return 1;
}

#if 0
//每个 C++程序都包含一个或多个函数 〈function),其中一个必须命名为 main。操作
//系统通过调用 main 来运行 C++程序。下面是一个非常简单的 main 函数, 它什么也不干,
//只是返回给操作系统一个值:
int main()
{
	return 0;
}


//在书店程序中,我们需要将多条记录合并成单一的汇总记录。作为一个相关的,但更
//简单的问题,我们先来看一下如何将两个数相加。通过使用 IO 库,我们可以扩展 main
//程序,使之能提示用户输入两个数,然后输出它们的和:

#include <iostream>
int main()
{
	std::cout<<"Enter two numbers:"<<std::endl;
	int v1 = 0,v2 = 0;
	std::cin>>v1>>v2;
	std::cout<<"The sum of "<<v1<<" and "<<v2
			 <<" is "<<v1 + v2<<std::endl;
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
Enter two numbers:
12 2
The sum of 12 and 2 is 14
xz@xiaqiu:~/study/cpp-primer/study/build$ 



//练习 1.3: 编写程序,在标准输出上打印 Hello,World。
#include <iostream>
using namespace std;

int main()
{
	cout<<"Hello,World"<<endl;
	return 0;
}


xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
Hello,World
xz@xiaqiu:~/study/cpp-primer/study/build$ 



//ex练习 1.4: 我们的程序使用加法运算符+来将两个数相加。编写程序使用乘法运算符*,
#include <iostream>

int main()
{
	std::cout<<"Enter two numbers: "<<std::endl;
	int v1 = 0,v2 = 0;
	std::cin>>v1>>v2;
	std::cout<<"The sum of "<<v1<<" X "<<v2
			 <<" is "<<v1 * v2<<std::endl;
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
Enter two numbers: 
12 2
The sum of 12 X 2 is 24
xz@xiaqiu:~/study/cpp-primer/study/build$ 


#include <iostream>
int main()
{
	int sum = 0,val = 0;
	// 只要val 的值小于等于10,while 循环就会持续执行
	while(val <= 10)
	{
		sum += val; // 将sum + val 赋予 sum
		++val; // 将val 加1
	}
	std::cout<<"Sum of 1 and 10 inclusive is "<<sum<<std::endl;
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
Sum of 1 and 10 inclusive is 55
xz@xiaqiu:~/study/cpp-primer/study/build$ 



#include <iostream>
int main()
{
	int sum = 0;
	for(int i = -100; i<=100;++i)
	{
		sum += i;
	}
	std::cout<<sum<<std::endl;
	return 0;
}


xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
0
xz@xiaqiu:~/study/cpp-primer/study/build$ 

//简要重述一下 for 循环的总体执行流程
//1. 创建变量 val,将其初始化为 1。
//2. 检测 val 是否小于等于 10。若检测成功,执行 for 循环体。若失败,退出循环,
//继续执行 for 循环体之后的第一条语句。
//3. 将val 的值增加 1。
//4. 重复第 2 步中的条件检测,只要条件为真就继续执行剩余步骤。



//读取数量不定的输入数据
#include <iostream>
int main()
{
	int sum = 0,value = 0;
	// 读取数据直到遇到文件尾,计算所有读入的值的和
	while(std::cin>>value)
	{
		sum += value;
	}
	std::cout<<"Sum is: "<<sum<<std::endl;
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
1 2 2 3 12 
Sum is: 20
xz@xiaqiu:~/study/cpp-primer/study/build$ 


//main 的首行定义了两个名为 sum 和 value 的 int 变量,均初始化为 0。我们使用
//value 保存用户输入的每个数,数据读取操作是在 while 的循环条件中完成的:
//当我们使用一个 istream 对象作为条件时,其效果是检测流的状态。如果流是有效
//的,即流未遇到错误,那么检测成功。当遇到文件结束符 〈end-of-file),或遇到一个无效
//输入时《例如读入的值不是一个整数),istream 对象的状态会变为无效。处于无效状态
//的 istream 对象会使条件变为假。

//当从键盘向程序输入数据时, 对于如何指出文件结束,不同操作系统有不同的约定=
//在 Windows 系统中,输入文件结束符的方法是敲 Ctrl + Z ( 按住 Ctrl 键的同时按Z键)
//然后按 Enter 或 Return 键。在 UNIX 系统中,包括 Mac OS X 系统中,文件结束符输入
//是用 Ctrl + D。


#include <iostream>

int main()
{
	 currVal 是我们正在统计的数; 我们将读入的新值存入 val
	int currVal = 0,val = 0;
	// 读取第一个数,并确保确实有数据可以处理
	if(std::cin >> currVal)
	{
		int cnt = 1; //保存我们正在处理的当前值的个数
		while(std::cin>>val) //读取剩余的数
		{
			if(val == currVal) //如果值相同
				++cnt;
			else
			{
				//和否则,打印前一个值的个数
				std::cout<<currVal <<" occurs "
						 <<cnt<<" times "<<std::endl;
				currVal = val;   // 记住新值
				cnt = 1; // 重置计数器
			}
		}// while 循环在这里结束
	}
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
1 1 1 1 12 2 2 2 2 23 2 3 3 31 2 21 2 1 2
1 occurs 4 times 
12 occurs 1 times 
2 occurs 4 times 
23 occurs 1 times 
2 occurs 1 times 
3 occurs 2 times 
31 occurs 1 times 
2 occurs 1 times 
21 occurs 1 times 
2 occurs 1 times 
1 occurs 1 times 



#include <iostream>
int main()
{
	Sales_item book;
	// 读入 TSBN 号、售出的册数以及销售价格
	std::cin>>book;
	// 写入ISBN、售出的册数、总销售额和平均价格
	std::cout<<book<<std::endl;
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
0-1212-2121221	3 12.32
0-1212-2121221 3 36.96 12.32
xz@xiaqiu:~/study/cpp-primer/study/build$ 


#include <iostream>
int main()
{
	Sales_item item1,item2;
	std::cin>>item1>>item2;
	std::cout<<item1+item2<<std::endl;
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
121 12 12.12 121 13 12
121 25 301.44 12.0576
xz@xiaqiu:~/study/cpp-primer/study/build$ 


#include <iostream>
int main()
{
	Sales_item item1,item2;
	std::cin>>item1>>item2;
	// 首先检查 iteml 和 item2 是否表示相同的书
	if(item2.isbn() == item1.isbn())
	{
		std::cout<<item2 + item1<<std::endl;
		return 0;
	}
	else
	{
		std::cerr<<"Data must refer to same ISBN"<<std::endl;
		return -1;
	}
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test
1221 12 12 1221 12 12
1221 24 288 12
xz@xiaqiu:~/study/cpp-primer/study/build$ ./test
1212 21 12 12 1221 2121
Data must refer to same ISBN
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <iostream>
int main()
{
	Sales_item total;// 保存下一条交易记录的变量
	// 读入第一条交易记录,并确保有数据可以处理
	if(std::cin>>total)
	{
		Sales_item trans;// 保存和的变量
		// 读入并处理剩余交易记录
		while(std::cin>>trans)
		{
			// 如果我们仍在处理相同的书
			if(total.isbn() == trans.isbn())
				total += trans; //更新总销售额
			else
			{
				// 打印前一本书的结果
				std::cout<<total<<std::endl;
				total = trans; // total 现在表示下一本书的销售额
			}
		}
		std::cout<<total<<std::endl;
	}
	else
	{
		//没有输入! 警告读者
		std::cerr<<"No data?!"<<std::endl;
		return -1; //表示失败
	}
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test
11 1 1 11 2 1 12 1 1 12 12 1 12 1 1 13 12 12
11 3 3 1
12 14 14 1
13 12 144 12
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <iostream>
int main()
{
	int i = 42;
	std::cout<<i<<std::endl;
	if(i)
		i =  0;
	std::cout<<i<<std::endl; 

	bool b = 42; 
	std::cout<<b<<std::endl;

	int j = b; 
	std::cout<<j<<std::endl;

	double pi = 3.14; 	
	std::cout<<pi<<std::endl;

	j = pi;
	std::cout<<j<<std::endl;

	unsigned char c = -1;	
	i = c;
	std::cout<<i<<std::endl;

	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
42
0
1
1
3.14
3
255
xz@xiaqiu:~/study/cpp-primer/study/build$ 


#include <iostream>
int main()
{
	unsigned u = 10,u2 = 42;
	std::cout<<u2 - u<<std::endl; //32
	std::cout<<u - u2<<std::endl; //4294967264

	int i = 10,i2 = 42;
	std::cout<<i2 - i<<std::endl; //32
	std::cout<<i - i2<<std::endl; //-32

	u = 42;
	i = 10;
	std::cout<<i - u<<std::endl; //4294967264
	std::cout<<u - i<<std::endl; //32

	u = 10;
	i = -42;
	std::cout<<i + i<<std::endl; //-84
	std::cout<<u + i<<std::endl; //4294967264

	i = 10;
	std::cout<<"good"<<std::endl; //good
	while(i >= 0)
	{
		std::cout<<i<<std::endl;
		--i;
	}

	for(int i = 10;i >= 0; --i)
	{
		std::cout<<i<<std::endl;
	}

	for(unsigned u = 0; u <= 10; ++u)
	{
		std::cout<<u<<std::endl;
	}

	u = 11;
	while(u > 0)
	{
		--u;
		std::cout<<u<<std::endl;
	}

	u = 10;
	i = -42;
	if(i < u)
		std::cout<<i<<std::endl;
	else
		std::cout<<u<<std::endl;

	u = 42;u2 = 10;
	std::cout<<u - u2<<std::endl;
	std::cout<<u2 - u<<std::endl;
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
32
4294967264
32
-32
4294967264
32
-84
4294967264
good
10
9
8
7
6
5
4
3
2
1
0
10
9
8
7
6
5
4
3
2
1
0
0
1
2
3
4
5
6
7
8
9
10
10
9
8
7
6
5
4
3
2
1
0
10
32
4294967264
xz@xiaqiu:~/study/cpp-primer/study/build$ 


#include <iostream>
int main()
{
	std::cout<<"Hello World!";
	std::cout<<"";

	std::cout<<"\nCC\toptions\tfile.[cC]\n";

	std::cout<<"a really,really long string literal "
			   "that spans two lines"<<std::endl;

	std::cout<<'M'<<" "<<'\115'<<" "<<'\x4d'<<std::endl;

	unsigned long long bigVal = -1ULL;
	std::cout<<bigVal<<std::endl;

	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
Hello World!
CC	options	file.[cC]
a really,really long string literal that spans two lines
M M M
18446744073709551615
xz@xiaqiu:~/study/cpp-primer/study/build$ 

//L'a'       // 宽字符型字面值,类型是 wchar_t
//u8"hil"       // utf-8 字符串字面值 (utf-8 用 8 位编码一个 Unicode 字符)
//42ULL      // 无符号整型字面值,类型是 unsigned long long
//1E-3F       // 单精度浮点型字面值,类型是 float
//3.14159L    // 扩展精度浮点型字面值,类型是 1ong double
//字符和字符串字面值
//u             Unicode 16 字符                                   char16_t
//U             Unicode 32 字符                                   char32_t
//L              宽字符                                           wchar_t
//u8              UTF-8《〈仅用于字符串字面常量)                   char


//os<<s                  将 s 写到输出流 os 当中,返回 os
//is>>s                 从 is 中读取字符串赋给 s,字符串以空白分隔,返回 is
//getline(is,s)     从 is 中读取一行赋给 s,返回 is
//s.empty ()            s 为空返回 true,和否则返回 false
//s.size()           返回 s 中字符的个数
//sr[n]               返回 s 中第 n 个字符的引用,位置n 从0 计起
//s1+s2              返回 sl 和 s2 连接后的结果
//sl=s2                 用 s2 的副本代替 sl 中原来的字符
//s1==s2                如果 sl 和 s2 中所含的字符完全一样,则它们相等,string 对象的相
//s1!=s2             等性判断对字母的大小写敏感
//<,<=,>,>=       利用字符在字典中的顺序进行比较,且对字母的大小写敏感
#include <string>
#include <iostream>
using namespace std;
int main()
{
	string s;
	cin>>s;
	cout<<s<<endl;
	string s1,s2;
	cin>>s1>>s2;  把第一个输入读到 sl 中,第二个输入读到 s2 中
	cout<<s1<<"---"<<s2<<endl;// 输出两个 string 对象
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
dsada
dsada
dsada dsasda
dsada---dsasda
xz@xiaqiu:~/study/cpp-primer/study/build$ 


//读取操作时,string 对象会自动忽略开头的空白〈即空格符、换行符、制表符等) 并从
//第一个真正的字符开始读起,直到遇见下一处空白为目。
#include <string>
using namespace std;
int main()
{
	string word;
	while(cin>>word)
		cout<<word<<endl;
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
dsads dsa d sad a d sad a d as das d sa dsa dsa
dsads
dsa
d
sad
a
d
sad
a
d
as
das
d
sa
dsa
dsa
xz@xiaqiu:~/study/cpp-primer/study/build$ 

//有时我们希望能在最终得到的字符串中保留输入时的空白符,这时应该用 getline
//函数代替原来的>>运算符。getline 函数的参数是一个输入流和一个 string 对象,函
//数从给定的输入流中读入内容,直到遇到换行符为止〈注意换行符也被读进来了),然后
//把所读的内容存入到那个 string 对象中去〈注意不存换行符)。get1line 只要一遇到换
//行符就结束读取操作并返回结果,哪怕输入的一开始就是换行符也是如此。如果输入真的
//-开始就是换行符,那么所得的结果是个空 string。

#include <string>
using namespace std;
int main()
{
	string line;
	//1 每次读入一整行,直至到达文件末尾
	while(getline(cin,line))
	{
		cout<<line<<endl;
	}
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
dsadsadsa
dsadsadsa






dsadsada
dsadsada
dsada
dsada



xz@xiaqiu:~/study/cpp-primer/study/build$ 
// 每次读入一整行,遇到空行直接跳过
#include <string>
using namespace std;
int main()
{
	string line;
	while(getline(cin,line))
	{
		if(!line.empty())
		{
			cout<<line<<"---"<<endl;
		}
	}
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
dsadsa
dsadsa---
dsada
dsada---
d
d---


dsadsa
dsadsa---
dsa
dsa---
dsa
dsa---
^C
xz@xiaqiu:~/study/cpp-primer/study/build$ 


//size 函数返回 string 对象的长度(即 string 对象中字符的个数), 可以使用size 所可
//函数只输出长度超过 80 个字符的行:
#include <iostream>
#include <string>

using namespace std;
int main()
{
	string line;
	//每次读入一整行,输出其中超过 80 个字符的行
	while(getline(cin,line))
	{
		if(line.size() > 80)
			cout<<line<<endl;
	}
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
dsadsad
sssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
xz@xiaqiu:~/study/cpp-primer/study/build$ 


#include <string>
#include <iostream>
using namespace std;
int main()
{
	string str("the expense of spirit\n");
	cout<<"The size of "<<str<<" is "<<str.size()
		<<" characters,including the newline"<<endl;
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
The size of the expense of spirit
 is 22 characters,including the newline
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <string>
#include <cctype>
#include <iostream>
using namespace std;

int main()
{
	string s("Hello world!!!");
	//punct_cnt 与 s.size 返回的类型相同
	decltype(s.size()) punct_cnt = 0;
	// 统计s中标点符号的个数
	for(auto c : s) //对于 s 中的每个字符
	{
		if(ispunct(c)) //如果字符是标点符号
			++punct_cnt;//增加标点计数器
	}
	cout<<punct_cnt<<" punctuation characters in "<<s<<endl;

	//将 s 转换为大写
	string orig = s;
	for(auto &c : s)
	{
		//对于 s 中的每个字符(注意:c 是一个引用)
		c = toupper(c);
	}
	cout<<s<<endl;

	// 将 s 中的第一个单词转换为大写
	s = orig; //将 s 恢复到原始大小写
	decltype(s.size()) index = 0;
	// 处理 s 中的字符,直到字符用完
	while(index != s.size() && !isspace(s[index]))
	{
		// s[index] 返回一个引用,因此我们可以更改底层字符
		s[index] = toupper(s[index]);
		// 增加索引以查看下一个字符
		// 在下一次迭代
		index++;
	}
	cout<<s<<endl;
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
3 punctuation characters in Hello world!!!
HELLO WORLD!!!
HELLO world!!!
xz@xiaqiu:~/study/cpp-primer/study/build$ 

//只处理一部分字符
//如果要处理 string 对象中的每一个字符,使用范围 for 语句是个好主意。然而,
//有时我们需要访问的只是其中一个字符,或者访问多个字符但遇到某个条件就要停下来。
//例如,同样是将字符改为大写形式,不过新的要求不再是对整个字符串都这样做,而仅仅
//把 string 对象中的第一个字母或第一个单词大写化。
//string 对象的下标必须大于等于0 而小于s.size()。
//使用超出此范围的下标将引发不可预知的结果,以此推断,使用下标访问
//空 string 也会引发不可预知的结果。
#include <string>
#include <iostream>

using namespace std;

int main()
{
	string str("some string"),orig = str;
	if(!str.empty()) //确保有一个字符要打印
	{ 
		cout<<str[0]<<endl; //打印字符串中的第一个字符
	}

	if(!str.empty()) //确保 str[0] 中有一个字符
	{
		// 为字符串中的第一个字符赋一个新值
		str[0] = toupper(str[0]);
	}
	cout<<str<<endl;

	str = orig; //将str恢复到原来的值
	//使用迭代器而不是下标的等效代码
	if(str.begin() != str.end())
	{
		//确保字符串不为空
		auto it = str.begin();//它表示字符串中的第一个字符
		*it = toupper(*it);//使该字符大写
	}
	cout<<str<<endl;

	str = orig; //将 str 恢复到其原始值
	//使用迭代器而不是下标的 for 循环
	for(auto it = str.begin(); it!=str.end() && !isspace(*it);++it)
	{
		*it = toupper(*it);// 大写当前字符
	}
	cout<<str<<endl;

	str = orig; //将 str 恢复到其原始值
	// 3. while 代替带下标的 for
	decltype(str.size()) index = 0;// 下标查看字符串中的字符
	while(index != str.size() && isspace(str[index]))
	{
		str[index] = toupper(str[index]);// 大写当前字符
		++index;
	}
	cout<<str<<endl;

	 4. 带有迭代器的while循环
	auto beg = str.begin();
	while(beg != str.end() && !isspace(*beg))
	{
		*beg = toupper(*beg);
		++beg;
	}
	cout<<str<<endl;

	str = orig; //将 str 恢复到其原始值
	// 循环处理每个字符的范围
	// 第一个循环将字符串中的字符打印到一行
	for(auto c : str) // 对于 str 中的每个字符
	{
		cout<<c<<endl; // 打印当前字符后跟一个换行符
	}

	// 接下来更改字符串中的每个字符
	for(auto &c : str) // 注意:c 是一个引用
		c = '*';
	// 为 str 中的底层字符分配一个新值
	cout<<str<<endl;
	str = orig; //将str恢复到原来的值

	// 使用传统 for 循环的等效代码
	// 首先打印字符串中的字符
	for(decltype(str.size()) ix = 0; ix != str.size();++ix)
	{
		cout << str[ix] << endl;  // 打印当前字符后跟一个换行符
	}

	// 接下来更改字符串中的每个字符
	for(decltype(str.size()) ix = 0; ix != str.size(); ++ix)
	{
		str[ix] = '*'; // 为 str 中的字符分配一个新值
	}

	cout<<str<<endl;

	str = orig; //将str恢复到原来的值
	// 使用传统 for 循环和迭代器的等效代码
	// 首先打印字符串中的字符
	for(auto beg = str.begin(); beg != str.end();++beg)
	{
		cout<<*beg<<endl; // 打印当前字符后跟一个换行符
	}

	//接下来更改字符串中的每个字符
	for(auto beg = str.begin(); beg != str.end(); ++beg)
	{
		*beg = '*';// 为 str 中的字符分配一个新值
	}
	cout<<str<<endl;
	return 0;
}


xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
s
Some string
Some string
SOME string
some string
SOME string
s
o
m
e
 
s
t
r
i
n
g
***********
s
o
m
e
 
s
t
r
i
n
g
***********
s
o
m
e
 
s
t
r
i
n
g
***********
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <string>
#include <iostream>
#include <cstring>
#include <cstddef>
using namespace std;

int main()
{
	string s1 = "A string example";
	string s2 = "A different string";

	if(s1 < s2)
		cout<<s1<<endl;
	else
		cout<<s2<<endl; //A different string
	const char ca1[] = "A string example";
	const char ca2[] = "A different string";

	if(strcmp(ca1,ca2) < 0) //与字符串比较 s1 < s2 效果相同
		cout<<ca1<<endl;
	else
		cout<<ca2<<endl; //A different string

	const char* cp1 = ca1, *cp2 = ca2;
	cout<<strcmp(cp1,cp2)<<endl;// 输出为正 //15
	cout<<strcmp(cp2,cp1)<<endl;//输出为负 //-15
	cout<<strcmp(cp1,cp1)<<endl;//输出为零 0

	cout<<strlen(cp1)<<endl;//打印 16; strlen 忽略空值

	const unsigned sz = 16 + 18 + 2;
	char largeStr[sz]; // 将保存结果
	// 如果我们错误地计算了 largeSt 的大小,那将是灾难性的
	strcpy(largeStr,ca1);// 将 ca1 复制到 largeStr
	strcpy(largeStr," ");// 在 largeStr 的末尾添加一个空格
	strcpy(largeStr,ca2);// 将 ca2 连接到 largeSt
	// 打印一个字符串示例一个不同的字符串
	cout<<largeStr<<endl;  //A different string

	strncpy(largeStr,ca1,sz);// 要复制的大小包括空值
	if(strlen(ca1) > sz)
		largeStr[sz-1] = '\0';
	strncpy(largeStr," ",2);// 迂腐,但好习惯
	strncpy(largeStr,ca2,sz - strlen(largeStr));
	cout<<largeStr<<endl; //A different string


	// 将 large_string 初始化为 s1、空格和 s2 的串联
	string large_string = s1 + " " + s2;
	cout<<large_string<<endl; //A string example A different string

	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
A different string
A different string
15
-15
0
16
A different string
A different string
A string example A different string
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <iostream>
#include <string>
#include <cstddef>

using namespace std;
int main()
{
	const string hexdigits = "0123456789ABCDEF";// 可能的十六进制数字
	cout<<"Enter a series of numbers between 0 and 15"
		<<" separated by spaces.  Hit ENTER when finished: "
		<<endl;
	string result;// 将保存生成的十六进制字符串

	string::size_type n;// 保存输入中的数字
	while(cin>>n)
		if(n < hexdigits.size()) // 忽略无效输入
			result += hexdigits[n];// 获取指定的十六进制数字

	cout<<"Your hex number is: "<<result<<endl;

	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
Enter a series of numbers between 0 and 15 separated by spaces.  Hit ENTER when finished: 
12
Your hex number is: C
xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
Enter a series of numbers between 0 and 15 separated by spaces.  Hit ENTER when finished: 
14
Your hex number is: E
xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
Enter a series of numbers between 0 and 15 separated by spaces.  Hit ENTER when finished: 
15
Your hex number is: F
xz@xiaqiu:~/study/cpp-primer/study/build$ 


//和任何一种类类型一样,vector 模板控制着定义和初始化向量的方法。表 3.4 列出
//了定义 vector 对象的常用方法。
//vector<T> v1    v1 是一个空 vector,它潜在的元素是 T 类型的,执行默认初始化
//Vector<T> v2(v1)          v2 中包含有 v1 所有元素的副本
//vector<T> v2 = v1         等价于 v2 (v1) ,v2 中包含有 vl 所有元素的副本
//Vector<T> v3(n,val)      v3 包含了n 个重复的元素,每个元素的值都是 val
//vector<T> v4(n)            v4 包含了n 个重复地执行了值初始化的对象
//vector<T> v5{a,b,c...} v5包含了初始值个数的元素,每个元素被赋予相应的初始值
//vector<T> v5={a,b,c...} 等价于v5fa,bvc...}
//可以默认初始化 vector 对象 参见 2.2.1 节,第 40 页),从而创建一个指定类型的
//空 vector:
//vector<string> svec;//黑认初始化,svec 不含任何元素
//看起来空 vector 好像没什么用,但是很快我们就会知道程序在运行时可以很高效地往
//vector 对象中添加元素。事实上,最常见的方式就是先定义一个空 vector,然后当运
//行时获取到元素的值后再逐一添加。

//当然也可以在定义 vector 对象时指定元素的初始值。 例如,允许把一个 vector 对
//象的元素拷贝给另外一个 vector 对象。此时,新 vector 对象的元素就是原 vector
//对象对应元素的副本。注意两个 vector 对象的类型必须相同:
//vector<int> ivec; // 初始状态为空
// 在此处给 ivec 添加一些值
//vector<int> ivec2 (ivec)        // 把 ivec 的元素拷贝给 ivec2
//vector<int> ivec3 = ivec;       // 把 ivec 的元素找贝给 ivec3
//vector<string> svec(ivec2);  // 错误: svec 的元素是 String 对象,不是 int

#include <cstddef>
#include <vector>
#include <iostream>
using namespace std;
int main()
{
	vector<unsigned> grades;
	// 以十为一组计算等级数:
	// 0--9, 10--19, . . . 90--99, 100
	unsigned scores[11] = {};// 11个桶,所有值初始化为0
	unsigned grade;
	while(cin >> grade)
	{
		if(grade<=100)
		{
			// 增加当前集群的计数器
			++scores[grade/10];
		}
		grades.push_back(grade);
	}
	cout<<"grades.size = "<<grades.size()<<endl;

	for(auto g : grades) // 对于成绩中的每个元素
	{
		cout<<g<<" ";
	}
	cout<<endl;

	for(auto i : scores)
	{
		// 对于分数中的每个计数器
		// 打印该计数器的值
		cout<<i<<" ";
	}
	cout<<endl;
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
1 12 23 45 32 21 34 67 87 54 65 67 43 54 67   
grades.size = 15
1 12 23 45 32 21 34 67 87 54 65 67 43 54 67 
1 1 2 2 2 2 4 0 1 0 0 
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <iostream>
#include <string>
#include <vector>
using namespace std;


int main()
{
	// 列表初始化,文章有3个元素
	vector<string> articles = {"a","an","the"};

	vector<string> svec; // 默认初始化; svec 没有元素
	vector<int> ivec; // ivec 持有 int 类型的对象
	vector<Sales_item> Sales_vec;  // holds Sales_items

	vector<vector<string>> file; //其元素为向量的向量
	vector<vector<int>> vecOfvec; 

	// 所有五个向量的大小都是 0
	cout<<svec.size()<<" "<<ivec.size()<<" "
		<<Sales_vec.size()<<" "
		<<file.size()<<" "<<vecOfvec.size()<<endl; //0 0 0 0 0

	vector<int> ivec2(10); // 十个元素,每个都初始化为 0
	vector<int> ivec3(10,-1);// 十个 int 元素,每个都初始化为 -1
	vector<string> svec2(10);// 十个元素,每个元素都是一个空字符串
	vector<string> svec3(10,"hi"); // 十个字符串; 每个元素都是“嗨!”
	cout<<ivec2.size()<<" "<<ivec3.size()<<" "
		<<svec2.size()<<" "<<svec3.size()<<endl; //10 10 10 10

	// 10 不是字符串,所以不能是列表初始化
	vector<string> v1(10); // 用十个值初始化的元素构造 v1
	vector<string> v2{10}; //10元素值初始化元素
	vector<string> v3(10,"hi"); // 十个值为“hi”的元素
	// 再次列表初始化不可行,所以普通构造
	vector<string> v4{10,"hi"}; // 十个值为“hi”的元素

	// 所有四个vector的大小都是 10
	cout<<v1.size()<<" "<<v2.size()<<" "<<v3.size()<<" "
		<<v4.size()<<endl; //10 10 10 10

	vector<string> vs1{"hi"};// 列表初始化:vs1 有 1 个元素
	vector<string> vs2{10}; // 10默认初始化的元素
	vector<string> vs3{10,"hi"}; // 有十个值为“hi”的元素
	cout<<vs1.size()<<" "<<vs2.size()<<" "<<vs3.size()<<endl; //1 10 10

	vector<int> v5(10,1); // 值为 1 的十个元素
	vector<int> v6{10,1}; // 两个元素的值为 10 和 1
	cout<<v5.size()<<" "<<v6.size()<<endl; //10 2

	//意图更清晰
	vector<int> alt_v3 = {10};// 一个值为 10 的元素
	vector<int> alt_v4 = {10,1};// 两个元素的值为 10 和 1
	cout<<alt_v3.size()<<" "<<alt_v4.size()<<endl; //1 2

	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
0 0 0 0 0
10 10 10 10
10 10 10 10
1 10 10
10 2
1 2
xz@xiaqiu:~/study/cpp-primer/study/build$ 


#include<string>
#include<vector>
#include<iostream>

using namespace std;

int main()
{
	// 保存我们从标准输入中读取的成绩
	vector<unsigned> grades;

	// 以十为一组计算等级数:
	// 0--9, 10--19, . ..  90--99, 100
	vector<unsigned> scores(11,0);//11 个桶,最初都是 0
	unsigned grade;
	while(cin >> grade) //读取成绩
	{
		if(grade <= 100) // 只处理有效成绩
		{
			grades.push_back(grade);
			++scores[grade/10]; // 增加当前集群的计数器
		}
	}
	cout<<"grades.size = "<<grades.size()<<endl;
	for(auto it : grades)
		cout<<it<<" ";
	cout<<endl;

	cout<<"scores.size = "<<scores.size()<<endl;
	for(auto it : scores)
	{
		cout<<it<<" ";
	}
	cout<<endl;

	// 使用迭代器而不是下标的等效程序
	vector<unsigned> alt_score(11,0); // 11 个桶,最初都是 0
	// 对于输入中的每个等级
	for(auto it = grades.begin(); it != grades.end();++it)
	{
		unsigned i = *it;
		//增加当前集群的计数器
		++(*(alt_score.begin() + i/10));
	}

	cout<<"alt_scores.size = "<<alt_score.size()<<endl;
	for(auto it = alt_score.begin();it != alt_score.end();++it)
	{
		cout<<*it<<" ";
	}
	cout<<endl;

	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
1 12 23 32 43 54 65 54 54 65 65 76 76 87 89 78 67 67  78 78 56
grades.size = 21
1 12 23 32 43 54 65 54 54 65 65 76 76 87 89 78 67 67 78 78 56 
scores.size = 11
1 1 1 1 1 4 5 5 2 0 0 
alt_scores.size = 11
1 1 1 1 1 4 5 5 2 0 0 
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <iostream>
#include <vector>
#include <string>

using namespace std;
int main()
{
	vector<string> text;// 保存输入
	string s;
	while(getline(cin,s)) // 读取整个输入文件
		text.push_back(s); // 将每一行存储为文本中的一个元素
	cout<<"text.size: "<<text.size()<<endl;

	// 将文本中的每一行打印到第一个空行
	for(auto it = text.cbegin();
		it != text.cend() && !(*it).empty(); ++it)
	{
		cout<<*it<<endl;
	}
	// 使用箭头取消引用它并调用空的等效循环
	for(auto it = text.cbegin();
		it != text.cend() && !it->empty(); ++it)
	{
		cout<<*it<<endl;
	}
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
dsad asdsa dsa ds ad sa dsa dsad a
dsadsaaaaaaaaaaaaaaaaaaaaadsadadsad
dsadaddsadsadsadas
dsadsa
dsadsadsadsad dsadsadsa
dsadsad
text.size: 6
dsad asdsa dsa ds ad sa dsa dsad a
dsadsaaaaaaaaaaaaaaaaaaaaadsadadsad
dsadaddsadsadsadas
dsadsa
dsadsadsadsad dsadsadsa
dsadsad
dsad asdsa dsa ds ad sa dsa dsad a
dsadsaaaaaaaaaaaaaaaaaaaaadsadadsad
dsadaddsadsadsadas
dsadsa
dsadsadsadsad dsadsadsa
dsadsad
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <string>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
	vector<int> v = {0,1,2,3,4,5,6,7,8,9};
	auto sz = v.size();
	decltype(sz) i = 0;
	// 将 v 的内容复制到 v 的后面
	while(i != sz)
	{
		v.push_back(*v.begin() + i);
		++i;
	}
	//prints 0...9 0...9
	for(auto it:v)
		cout<<it<<" ";
	cout<<endl;

	// 当我们到达原始的最后一个元素时停止的另一种方法
	vector<int> alt_v = {0,1,2,3,4,5,6,7,8,9};
	// 值为 0...9 的向量
	for(decltype(alt_v.size())i = 0,sz = alt_v.size();i!=sz;++i)
	{
		alt_v.push_back(alt_v[i]);
	}
	// prints 0...9 0...9
	for(auto it : alt_v)
		cout<<it<<" ";
	cout<<endl;

	vector<int> v2 = {0,1,2,3,4,5,6,7,8,9};// 值为 0 ... 9 的向量
	decltype(v2.size()) ix = 0;
	// 我们将使用 ix 来索引向量
	
	// 将值小于 5 的元素设置为 0
	while(ix != v2.size() && v2[ix] < 5)
	{
		v2[ix] = 0; // 改变v中元素的值
		++ix;// 增加索引,以便下一次迭代获取下一个元素
	}

	// 使用下标打印元素
	for(unsigned i = 0; i!=v2.size();++i)
		cout<<v2[i]<<" ";
	cout<<endl;

	// 等价但使用迭代器
	vector<int>alt_v2 = {0,1,2,3,4,5,6,7,8,9};// 值为 0...9 的向量
	// 将元素设置为 0,直到第一个 5 或更大的元素
	auto it = alt_v2.begin();
	while(it != alt_v2.end() && *it < 5)
	{
		*it = 0;// 改变 alt_v2 中元素的值
		++it; // 推进迭代器以表示下一个元素
	}
	for(auto it = alt_v2.begin();// 它表示 alt_v2 中的第一个元素
			it != alt_v2.end();// 只要它表示一个元素
			++it)// 将迭代器增加到下一个元素
		cout<<*it<<" ";// 从 alt_v2 打印由它表示的元素
	cout<<endl;
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 
0 0 0 0 0 5 6 7 8 9 
0 0 0 0 0 5 6 7 8 9 
xz@xiaqiu:~/study/cpp-primer/study/build$ 


//定义和初始化内置数组
//数组是一种复合类型参见 2.3 节,第 45 页)。数组的声明形如 a[d] ,其中 a 是数
//组的名字,q 是数组的维度。维度说明了数组中元素的个数,因此必须大于 0。数组中元
//素的个数也属于数组类型的一部分,编译的时候维度应该是已知的。也就是说,维度必须
//是一个常量表达式〈参见 2.4.4节,第 58 页 ):
#include <vector>
#include <iostream>
#include <cstddef>

using namespace std;

int main()
{
	// 大小为 3 的数组; 每个元素都是一个包含 4 个未初始化整数的数组
	int ia1[3][4]; 
	// 大小为 10 的数组; 每个元素都是一个 20 元素的数组
	// 其元素是 30 个整数的数组
	// 将所有元素初始化为 0
	int arr[10][20][30] = {0};
	// 将 arr 的第一个元素分配给最后一个元素
	// 在 ia 的最后一行
	ia1[2][3] = arr[0][0][0];

	// 将行绑定到 ia 中的第二个四元素数组
	int (&row)[4] = ia1[1];

	// 三个元素,每个元素都是一个大小为4的数组
	int ia2[3][4] = {
		{0, 1, 2, 3},// 索引为 0 的行的初始值设定项
		{4, 5, 6, 7},// 索引为 1 的行的初始值设定项
		{8, 9, 10, 11}// 索引为 2 的行的初始值设定项
	};

	// 没有可选的等效初始化
	// 每行嵌套大括号
	int ia3[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};

	// 显式地只初始化每行中的元素 0
	int ia4[3][4] = {{ 0 }, { 4 }, { 8 }};
	
	// 显式初始化第 0 行; 其余元素
	// 是否已初始化值
	int ix[3][4] = {0,3,6,9};

	//prints 9 0 0 0
	cout<<ix[0][3]<<' '<<ix[1][0]<<' '<<ix[2][0]<<endl;

	constexpr size_t rowCnt = 3,colCnt = 4;
	int ia[rowCnt][colCnt];
	// 12 个未初始化的元素

	//每行
	for(size_t i = 0; i != rowCnt; ++i)
	{
		// 对于行中的每一列
		for(size_t j = 0; j != colCnt; ++j)
		{
			//将元素的位置索引分配为其值
			ia[i][j] = i * colCnt + j;
		}
	}

	// 四种打印ia内容的方法
	// 1. 使用嵌套范围 for 循环
	for(const auto &row : ia)
	{ //对于外部数组中的每个元素
		for(auto col : row)
		{//对于内部数组中的每个元素
			cout<<col<<" ";// 打印元素的值
		}
		cout<<endl;
	}
	cout<<ia[0][0]<<' '<<ia[2][3]<<endl; // prints 0 11

	// 2. 使用指针和传统的 for 循环
	// 用指针算法计算结束指针
	for(auto p = ia; p != ia + rowCnt; ++p)
	{
		// q 指向四个整数数组的第一个元素;
		// 即 q 指向一个 int
		for(auto q = *p; q != *p+colCnt;++q)
			cout<<*q<<' ';
		cout<<endl;
	}

	// 3.使用指针和传统的for循环
	// 使用库的开始和结束函数来管理指针
	for(auto p = begin(ia); p!=end(ia);++p)
	{
		// q 指向内部数组的第一个元素
		for(auto q = begin(*p); q!=end(*p);++q)
		{
			cout<<*q<<' ';// 打印 q 指向的 int 值
		}
		cout<<endl;
	}

	// 4. 使用类型别名声明循环控制变量
	using int_array = int[4];// 新样式类型别名声明

	for(int_array *p = ia; p != ia + 3;++p)
	{
		for(int *q = *p; q != *p + 4;++q)
		{
			cout<<*q<<' ';
		}
		cout<<endl;
	}

	// 为元素分配位置索引的另一种方法
	// 在二维数组中
	// 12 个未初始化的元素
	int alt_ia[rowCnt][colCnt]; 
	size_t cnt = 0;
	for(auto &row : alt_ia) // 对于外部数组中的每个元素
	{
		for(auto &col : row) // 对于内部数组中的每个元素
		{
			col = cnt; // 给这个元素下一个值
			++cnt; // 增加 cnt
		}
	}
	// 现在打印数组的值
	for(const auto& row : alt_ia) // 对于外部数组中的每个元素
	{
		for(auto col : row) // 对于内部数组中的每个元素
		cout<<col<<" ";
	}
	cout<<endl;
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
9 0 0
0 1 2 3 
4 5 6 7 
8 9 10 11 
0 11
0 1 2 3 
4 5 6 7 
8 9 10 11 
0 1 2 3 
4 5 6 7 
8 9 10 11 
0 1 2 3 
4 5 6 7 
8 9 10 11 
0 1 2 3 4 5 6 7 8 9 10 11 
xz@xiaqiu:~/study/cpp-primer/study/build$ 


#include <iostream>
using namespace std;

int main()
{
	cout<<-30 * 3 + 21 / 5<<endl; //-86
	cout<<-30 + 3 * 21 / 5<<endl; //-18
	cout<<30 / 3 * 21 % 5<<endl; //0
	cout<<30 / 3 * 21 % 4<<endl; 
	cout<<-30 / 3 * 21 % 4<<endl;
	cout<<12 / 3 * 4 + 5 * 15 + 24 % 4 / 2<<endl;

	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
-86
-18
0
2
-2
91
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <iostream>
#include <cstddef>

using namespace std;

int ia[] = {1,2,3,3,4,5,6};

int main()
{
	constexpr size_t sz = sizeof(ia) / sizeof(*ia);
	int arr2[sz];
	cout<<"ia size: "<<sz<<endl;

	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
ia size: 7
ia size: 7
xz@xiaqiu:~/study/cpp-primer/study/build$ 


#include <iostream>
#include <string>
#include <vector>

using namespace std;

vector<unsigned> grades;

int main()
{
	unsigned i;
	while(cin>>i)
	{
		grades.push_back(i);
	}

	for(auto grade : grades) //对于成绩中的每个年级
	{
		// 将初始成绩设置为通过或失败
		string finalgrade = (grade < 60) ? "fail":"pass";

		finalgrade = (grade > 90) ? "high pass" : (grade < 60) ? "fail" : "pass";
		cout<<grade<<" " + finalgrade<<endl;
	}
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
1 23 34 56 56 67 67 87 76 76 87 90 100 92 99 
1 fail
23 fail
34 fail
56 fail
56 fail
67 pass
67 pass
87 pass
76 pass
76 pass
87 pass
90 pass
100 high pass
92 high pass
99 high pass
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <cstddef>
#include <iostream>
#include <string>
#include <cctype>

using namespace std;

string &tolower(string &s)
{
	for(auto &i : s)
	{
		i = tolower(i);
	}
	return s;
}

string &toupper(string &s)
{
	for(auto &i : s)
		i = toupper(i);
	return s;
}

int main()
{
	int i = 0;
	cout<<i<<" "<<++i<<endl;

	string s("a string"),orig = s;
	cout<<toupper(s)<<endl;
	cout<<tolower(s)<<endl;

	s = orig;
	cout<<toupper(s)<<" "<<tolower(s)<<endl;

	string first = toupper(s);
	string second = tolower(s);

	cout<<first<<" "<<second<<endl;
	cout<<second<<" "<<first<<endl;
	cout<<first<<" "<<first<<endl;
	cout<<second<<" "<<second<<endl;

	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
0 1
A STRING
a string
A STRING a string
A STRING a string
a string A STRING
A STRING A STRING
a string a string
xz@xiaqiu:~/study/cpp-primer/study/build$ 


#include <iostream>

using namespace std;

int main()
{
	short short_value = 32767;// 如果shorts是16位的最大值
	short_value += 1; //这个计算溢出
	cout<<"short_value "<<short_value<<endl;

	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
short_value -32768
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <iostream>
using namespace std;

int main()
{
	Sales_data data, *p;
	sizeof(Sales_data); // 保存类型为 Sales_data 的对象所需的大小
	sizeof data; // 数据类型的大小,即 sizeof(Sales_data)
	sizeof p;// 指针大小
	sizeof *p; // p 指向的类型的大小,即 sizeof(Sales_data)
	sizeof data.revenue; // Sales_data 的收入成员类型的大小
	sizeof Sales_data::revenue; // 获取收入大小的另一种方法

	cout<<"short: "<<sizeof(short)<<"\n"
		<<"short[3]: "<<sizeof(short[3])<<"\n"
		<<"short*: "<<sizeof(short*)<<"\n"
		<<"short&: "<<sizeof(short&)<<endl;

	cout<<endl;

	cout<<"int: "<<sizeof(int)<<"\n"
		<<"int[3]: "<<sizeof(int[3])<<"\n"
		<<"int*: "<<sizeof(int*)<<"\n"
		<<"int&: "<<sizeof(int&)<<endl;

	cout<<endl;

	cout<<"Sales_data: "<<sizeof(Sales_data)<<"\n"
		<<"Sales_data[3]: "<<sizeof(Sales_data[3])<<"\n"
		<<"Sales_data*: "<<sizeof(Sales_data*)<<"\n"
		<<"Sales_data&: "<<sizeof(Sales_data&)<<endl;

	cout<<"Sales_data::revenue: "<<sizeof Sales_data::revenue<<"\n"
		<<"data.revenue: "<<sizeof data.revenue<<endl;

	int x[10];
	int *ip = x;

	// x 中的元素数
	cout<<sizeof(x)/sizeof(*x)<<endl;

	// 将一个指针的大小除以一个 int 的大小
	cout<<sizeof(ip)/sizeof(*ip)<<endl;

	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
short: 2
short[3]: 6
short*: 8
short&: 2

int: 4
int[3]: 12
int*: 8
int&: 4

Sales_data: 48
Sales_data[3]: 144
Sales_data*: 8
Sales_data&: 48
Sales_data::revenue: 8
data.revenue: 8
10
2
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <iostream>
using namespace std;

int main()
{
	int i = 1024;
	int k = -i;
	bool b = true;
	bool b2 = -b;
	cout<<b<<" "<<b2<<" "<<endl;
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
1 1 
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <cstddef>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
	vector<int> ivec; //空向量
	int cnt = 10;
	// 添加元素 10 . . . 1 到 ivec
	while(cnt > 0)
		ivec.push_back(cnt--); // int 后缀递减
	auto iter = ivec.begin();
	// 打印 10 9 8 。 . . 1
	while(iter != ivec.end())
		cout<<*iter++<<" "; // 迭代器后缀增量
	std::cout<<std::endl;
	vector<int> vec2(10,0);// 十个元素最初都是 0
	cnt = vec2.size();
	// 从 size 分配值。 . . 1 到 vec2 中的元素
	for(vector<int>::size_type ix = 0;
		ix != vec2.size(); ++ix,--cnt)
		vec2[ix] = cnt;

	iter = vec2.begin();
	// 打印 10 9 8 。 . . 1
	while(iter != vec2.end())
		cout<<*iter++<<" ";// 迭代器后缀增量
	std::cout<<std::endl;
	return 0;
}

#include <iostream>
using namespace std;

int main()
{
	// 编译器可能会警告精度损失
	int ival = 3.541 + 3;
	// 编译器可能会警告精度损失
	cout<<ival<<endl;
	return 0;
}
#include <stdexcept>
#include <iostream>
#include "Sales_item.h"
using namespace std;

int main()
{
	Sales_item item1,item2;
	while(cin>>item1>>item2)
	{
		try
		{
			// 执行将添加两个 Sales_items 的代码
			// 如果添加失败,代码抛出runtime_error异常
			// 首先检查数据是否为同一个项目
			if(item1.isbn() != item2.isbn())
				throw runtime_error("数据必须引用相同的 ISBN");

			// 如果我们还在这里,ISBN 是一样的
			cout<<item1 + item2<<endl;
		}
		catch(runtime_error err)
		{
			// 提醒用户 ISBN 必须匹配
			// 并提示输入另一对
			cout<<err.what()<<"\n再试一次? 输入 y 或 n"<<endl;
			char c;
			cin>>c;
			if(!cin || c == 'n')
				break;// 跳出while循环
		}// 结束 catch 子句
	}// 结束while循环
	return 0;//表示成功
}

#include <iostream>
#include <string>
using namespace std;

int main()
{
	// 反复询问用户要求和的一对数字
	string rsp;// 用于条件; 不能在 do 中定义
	do
	{
		cout<<"请输入两个值:";
		int val1 = 0,val2 = 0;
		cin>>val1>>val2;
		cout<<"总数是 "<<val1<<" 和 "<<val2
			<<" = "<<val1 + val2<<"\n\n"
			<<"更多的? 输入yes 或 n: ";
		cin>>rsp;
	}while(!rsp.empty() && rsp[0] != 'n');

	cout<<endl;

	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
请输入两个值:231 32
总数是 23132 = 263

更多的? 输入yes 或 n: yes
请输入两个值:321 342
总数是 321342 = 663
更多的? 输入yes 或 n: n
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <iostream>
#include <vector>
#include <string>

using namespace std;

const vector<string> scores = {"F", "D", "C", "B", "A", "A++"};
vector<unsigned> grades;

// 这些函数演示了处理 if 测试的替代方法
// 接受一个无符号值和一个字符串的函数
// 并返回一个字符串
string goodVers(string lettergrade, unsigned grade)
{
	// 为以 8 或 9 结尾的成绩添加加号,为以 0、1 或 2 结尾的成绩添加减号
	if(grade % 10 > 7)
		lettergrade += '+';	// 以 8 或 9 结尾的成绩得到一个“+”
	else
		if(grade % 10 < 3)
			lettergrade += '-'; // 以 0、1 或 2 结尾的得到一个“-”
	return lettergrade;
}

// 为成绩添加加号或减号的函数版本不正确
string badVers(string lettergrade,unsigned grade)
{
	// 为以 8 或 9 结尾的成绩添加加号,为以 0、1 或 2 结尾的成绩添加减号
	// 错误:执行与缩进不匹配; else 与内部 if 一致
	if(grade % 10 >= 3)
		if(grade % 10 > 7)
			lettergrade += '+';// 以 8 或 9 结尾的成绩获得 +
	else
		lettergrade += '-';// grades ending in 3, 4, 5, 6 will get a minus!

	return lettergrade;
}

// 使用与 badVers 相同的逻辑路径修正版本
string rightVers(string lettergrade, unsigned grade)
{
	// 为以 8 或 9 结尾的成绩添加加号,为以 0、1 或 2 结尾的成绩添加减号
	if(grade % 10 >= 3)
	{
		if(grade % 10 > 7)
			lettergrade += '+'; // 以 8 或 9 结尾的成绩获得 +
	}
	else
		lettergrade += '-';// 以 0、1 或 2 结尾的成绩将减分
	return lettergrade;
}

int main()
{
	// 从输入中读取一组分数
	unsigned grade;
	while(cin>>grade)
		grades.push_back(grade);

	// 现在处理这些成绩
	for(auto it : grades)
	{
		// 对于我们阅读的每个年级
		cout<<it<<" ";// 打印成绩
		string lettergrade;// 持有对应的字母等级
		// 如果成绩不及格,则无需检查正负
		if(it < 60)
			lettergrade = scores[0];
		else
		{
			lettergrade = scores[(it - 50) / 10];// 获取字母等级
			if(it != 100) // 仅当还不是 A++ 时才添加加号或减号
				lettergrade += '+';// 以 8 或 9 结尾的成绩获得 +
			else if(it % 10 < 3)
				lettergrade += '-';// 以 0、1 或 2 结尾的成绩获得 -
		}
		cout<<lettergrade<<endl;
		if(it > 59 && it != 100)
		{
			cout<<"替代版本:"<<it<<" ";
			// 从基本成绩开始,没有 + 或 -
			lettergrade = scores[(it - 50)/10];
			cout<<goodVers(lettergrade,it)<<" ";
			cout<<badVers(lettergrade,it)<<" ";
			cout<<rightVers(lettergrade,it)<<" ";
			cout<<endl;
		}
	}
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
12 23 54 56 7 87 98 99 89 97 96 54 4 65 34
12 F
23 F
54 F
56 F
7 F
87 B+
替代版本:87 B B- B 
98 A+
替代版本:98 A+ A+ A+ 
99 A+
替代版本:99 A+ A+ A+ 
89 B+
替代版本:89 B+ B+ B+ 
97 A+
替代版本:97 A A- A 
96 A+
替代版本:96 A A- A 
54 F
4 F
65 D+
替代版本:65 D D- D 
34 F
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <iostream>
using namespace std;

int main()
{
	char ch;
	// 为每个元音初始化计数器
	unsigned vowelCnt = 0;
	unsigned otherCnt = 0;
	// 计算任何不是元音的东西

	while(cin >> ch)
	{
		// 如果 ch 是元音,则增加相应的计数器
		switch(ch)
		{
			case 'a': case 'e': case 'i': case 'o': case 'u':
				++vowelCnt;
				break;
			default:
				++otherCnt;
				break;
		}
	}
	//打印结果
    cout << "元音数: \t" << vowelCnt << '\n'
         << "非元音总数: \t" << otherCnt << '\n';
    return 0;
}

#include <iostream>
#include <vector>
#include <string>

using namespace std;

int main()
{
	vector<int> ivec;
	vector<int> v = {0,1,2,3,4,5,6,7,8,9};

	// 范围变量必须是一个引用,以便我们可以写入元素
	for(auto &r : v) // 对于 v 中的每个元素
		r *= 2; // 将 v 中每个元素的值加倍

	// 打印 v 中的每个元素
	for(int r : v)
		cout<<r<<" ";// 打印 v 中的元素
	cout<<endl;

	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
0 2 4 6 8 10 12 14 16 18 
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include<iostream>

using namespace std;
int main()
{
	unsigned aCnt = 0,eCnt = 0,iCnt = 0,oCnt = 0,uCnt = 0;
	char ch;
	while(cin >> ch)
	{
		//如果 ch 是元音,则增加适当的计数器
		switch(ch)
		{
			case 'a':
				++aCnt;
				break;
			case 'e':
				++eCnt;
				break;
			case 'i':
				++iCnt;
				break;
			case 'o':
				++oCnt;
				break;
			case 'u':
				++uCnt;
				break;
		}
	}
	//打印结果
    cout << "元音数 a: \t" << aCnt << '\n'
         << "元音数 e: \t" << eCnt << '\n'
         << "元音数 i: \t" << iCnt << '\n'
         << "元音数 o: \t" << oCnt << '\n'
         << "元音数 u: \t" << uCnt << endl;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
ewqewqretgrfsadxzxczvcxvcxzdsadfsfdffedfrrgtrjyjukiuihnhggfbfdvdfw
元音数 a: 	2
元音数 e: 	4
元音数 i: 	2
元音数 o: 	0
元音数 u: 	2
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <cstddef>
#include <iostream>
using namespace std;

#define  DSADSA 

// 用于说明数组相关类型声明的代码
int arr[10]; // arr 是一个包含十个整数的数组
int *p1[10]; // p1 是一个包含十个指针的数组
int (*p2)[10] = &arr; // p2 指向一个包含十个整数的数组

using arrT = int[10];// arrT 是十个整数类型数组的同义词

// 声明函数的三种方法,返回指向十个整数数组的指针
arrT* func(int i);// 使用类型别名
auto func(int i)->int(*)[10]; // 使用尾随返回类型
int (*func(int i))[10]; // 直接声明

auto func2(int i)->int(&)[10]; // func2 返回对数组的引用

// 两个数组
int odd[] = {1,3,5,7,9};
int even[] = {0,2,4,6,8};

// 返回指向这些数组之一中的 int 的指针的函数
int *elemPtr(int i)
{
	// 返回一个指向这些数组中第一个元素的指针
	return (i % 2) ? odd : even;
}

// 返回一个指向包含五个 int 元素的数组的指针
decltype(odd) *arrPtr(int i)
{
	return (i % 2) ? &odd : &even;// 返回一个指向数组的指针
}

// 返回对包含五个 int 元素的数组的引用
int (&arrRef(int i))[5]
{
	return (i % 2) ? odd : even;
}

int main()
{
	int *p = elemPtr(6);// p 指向一个 int
	int (*arrP)[5] = arrPtr(5); // aarP 指向一个包含五个整数的数组
	int (&arrR)[5] = arrRef(4); // arrR 指的是一个包含五个整数的数组

	for(size_t i = 0; i < 5; ++i)
	{
		// p 指向数组中的一个元素,我们下标
		cout<<p[i]<<" ";
	}
	std::cout<<std::endl;
	for(size_t i = 0; i < 5; ++i)
	{
		// arrP 指向一个数组,
		// 我们必须取消对指针的引用以获取数组本身
		cout<<(*arrP)[i]<<" ";
	}
	std::cout<<std::endl;
	for(size_t i = 0; i < 5; ++i)
	{
		// arrR 指的是一个数组,我们可以下标
		cout<<arrR[i]<<" ";
	}
	std::cout<<std::endl;
	return 0;
}

#include <cstddef>
#include <iostream>
using namespace std;

size_t count_calls()
{
	static size_t ctr = 0;// 值将在调用之间保持不变
	return ++ctr;
}
int main()
{
	for(size_t i = 0; i != 10; ++i)
		cout<<count_calls()<<" ";
	cout<<endl;
	return 0;
}

#include <vector>
#include <string>
#include <iostream>
#include <initializer_list>
#include <sstream>
using namespace std;

struct ErrCode
{
	ErrCode(int i) : num(i){}// 初始化 ErrCode 类型的对象
	string msg() // ErrCode 的成员函数
	{
		ostringstream s;
		s<<"ErrCode "<<num;
		return s.str();
	}
	int num;// 数据成员,注意未初始化
};

// 接受 ErrCode 和字符串列表的版本
void error_msg(initializer_list<string> il)
{
	for(auto beg = il.begin(); beg != il.end(); ++beg)
		cout<<*beg<<" ";
	cout<<endl;
}

// 接受 ErrCode 和字符串列表的版本
void error_msg(ErrCode e, initializer_list<string> il)
{
	cout<<e.msg()<<": ";
	for(const auto &elem : il)
		cout<<elem<<" ";
	cout<<endl;
}

// 说明列表初始化返回值的函数
vector<string> functionX()
{
	string expected = "description",
	actual = "some other case";
	//...
	if(expected.empty())
		return {};// 返回一个空向量
	else if(expected == actual)
		return {"functionX","okay"};// 返回列表初始化的向量
	else
		return {"functionX",expected,actual};
}

int main()
{
	string expected = "description",actual = "some other case";
	initializer_list<int> li = {0,1,2,3};

	// 预期,实际是字符串
	if(expected != actual)
		error_msg({"functionX",expected,actual});
	else
		error_msg({"functionX","okay"});

	// 预期,实际是字符串
	if(expected != actual)
		error_msg(ErrCode(42),{"functionX",expected,actual});
	else
		error_msg(ErrCode(0),{"functionX","okay"});
	// 可以传递一个空列表,调用第二个版本的 error_msg
	error_msg({});// 打印空行
	// 调用列表初始化其返回值的函数
	// 结果是一个向量<string>
	auto result = functionX();
	for(auto i : result)
		cout<<i<<" ";
	cout<<endl;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
functionX description some other case 
ErrCode 42: functionX description some other case 

functionX description some other case 
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <iostream>
int main()
{
	cout<<factorial(5)<<endl;
	cout<<fact(5)<<endl;
	cout<<factorial(0)<<endl;
	cout<<fact(0)<<endl;
	return 0;
}

#include <iostream>
#include <string>
using namespace std;

// 声明(严格来说在这个文件中不是必需的)
string::size_type sumLength(const string&, const string&);
string::size_type largerLength(const string&, const string&);

// 定义这些函数
string::size_type sumLength(const string& s1,const string &s2)
{
	return s1.size() + s2.size();
}

string::size_type largerLength(const string &s1, const string &s2)
{
	return (s1.size() > s2.size()) ? s1.size() : s2.size();
}

// 根据其字符串参数的值,
// getFcn 返回指向 sumLength 或 largeLength 的指针
// 三种方式声明getFcn
// 1. 使用 decltype 作为返回类型,
// 记得加一个*表示getFcn返回一个指针
decltype(sumLength) *getFcn(const string&);
// 使用尾随返回类型
auto getFcn(const string&) -> string::size_type(*)(const string&, const string&);
// 直接定义
string::size_type (*getFcn(const string &))(const string&, const string&);

// 定义 getFcn
decltype(sumLength)*
getFcn(const string& fetch)
{
	if(fetch == "sum")
		return sumLength;
	return largerLength;
}
int main()
{
	// "sum" 是 getFcn 的参数
	// ("hello", "world!") 是函数 getFcn 返回的参数
	cout<<getFcn("sum")("hello","world!")<<endl;
	cout<<"--------------"<<endl;
	cout<<getFcn("larget")("hello","world")<<endl;

	return 0;
}
#include <iterator>
#include <iostream>
#include <cstddef>

using namespace std;
// const int ia[] 等价于 const int* ia
// 显式传递大小并用于控制对 ia 元素的访问
void print(const int ia[], size_t size)
{
	for(size_t i = 0; i != size; ++i)
	{
		cout<<ia[i]<<" ";
	}
	cout<<endl;
}

int main()
{
	int j[] = {0,1,2,3,4,5,6,7,8,9};
	print(j,end(j) - begin(j));
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
0 1 2 3 4 5 6 7 8 9 
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <string>
#include <iostream>
using namespace std;

inline const string &
shorterString(const string& s1, const string &s2)
{
	return s1.size() <= s2.size() ? s1 : s2;
}

int main()
{
	string s1("successes"),s2("failure");
	cout<<shorterString(s1,s2)<<endl;

	//调用shorterString返回的字符串的size成员
	cout<<shorterString(s1,s2).size()<<endl;

	// 调用内联版本生成的等效代码
	// 较短的字符串
}

#include <cstdlib>
int main()
{
	bool some_failure = false;
	if(some_failure)
		return EXIT_FAILURE; 
	else
		return EXIT_SUCCESS; //在 cstdlib 中定义
}


#include <iostream>
#include <bitset>
using namespace std;

int main()
{
  short i = 65537; 
  int j = i + 1;  
  cout<<bitset<32>(65537)<<endl;
  cout<<i<<endl;
  cout<<bitset<32>(65538)<<endl;
  cout<<j<<endl;

  bitset<sizeof(short)*8>shortSet;
  shortSet.set();
  cout<<shortSet<<endl;
  cout<<(int)(shortSet.to_ulong())<<endl;
  cout<<(short)(shortSet.to_ulong())<<endl;
  return 0;
}






xz@xiaqiu:~/study/cpp-primer/study/1$ ./1
00000000000000010000000000000001
1
00000000000000010000000000000010
2
1111111111111111
65535
-1
xz@xiaqiu:~/study/cpp-primer/study/1$ 






#include <stdio.h>

class A
{
public:
	void test(){printf("test A\nthis = %d\n",this);}
};

int main()
{
	A *pA = NULL;
	pA->test();
	return 0;
}





//静态绑定
//this == 0



xz@xiaqiu:~/study/cpp-primer/study/1$ ./2
test A
this = 0
xz@xiaqiu:~/study/cpp-primer/study/1$ 





#include <iostream>
#include <typeinfo>
#include <cxxabi.h>
using namespace std;
string getClearName(const char* name)
{
  int status = -1;
  char* clearName = abi::__cxa_demangle(name,NULL,NULL,&status);
  const char* const demangledName = (status == 0)?clearName : name;
  string ret_val(demangledName);
  free(clearName);
  return ret_val;
}

int main()
{
    int a[2][2][3] = {{{1,2,3},{4,5,6}},{{7,8,9},{10,11,12}}};
    int *ptr = (int*)(&a+1);
    printf("%d %d\n", *(int*)(a + 1), *(ptr - 1));
    cout<<getClearName(typeid(ptr).name())<<endl;
    cout<<getClearName(typeid(a).name())<<endl;
    cout<<getClearName(typeid(&a).name())<<endl;
    cout<<"-------------------------------"<<endl;
    cout<<getClearName(typeid(a+1).name())<<endl;
    cout<<getClearName(typeid(&a+1).name())<<endl;
    return 0;
}





xz@xiaqiu:~/study/cpp-primer/study/1$ ./3
7 12
int*
int [2][2][3]
int (*) [2][2][3]
-------------------------------
int (*) [2][3]
int (*) [2][2][3]
xz@xiaqiu:~/study/cpp-primer/study/1$ 





#include <iostream>
#include <typeinfo>
#include <cxxabi.h>

using namespace std;
string getClearName(const char* name)
{
  int status = -1;
  char* clearName = abi::__cxa_demangle(name,NULL,NULL,&status);
  const char* const demangledName = (status == 0)?clearName : name;
  string ret_val(demangledName);
  free(clearName);
  return ret_val;
}

int main()
{
  static char* s[] = {"black","white","pink","violet"};
  char **ptr[] = {s+3,s+2,s+1,s}, ***p;
  p = ptr;++p;
  printf("%s\n",*(s));
  printf("%s\n",*(s+1)); 
  printf("%s\n",*(s+2)); 
  printf("%s\n",*(s+3));
  printf("%s\n",(**p)+1); 

  cout<<"------------------------"<<endl;
  cout<<getClearName(typeid(s).name())<<endl; 
  cout<<getClearName(typeid(s+1).name())<<endl; 
  cout<<getClearName(typeid(p).name())<<endl; 
  cout<<getClearName(typeid(ptr).name())<<endl; 
  cout<<getClearName(typeid(**p).name())<<endl; 
  cout<<getClearName(typeid((**p)+1).name())<<endl;
  return 0;
}





xz@xiaqiu:~/study/cpp-primer/study/1$ ./4
black
white
pink
violet
ink
------------------------
char* [4]
char**
char***
char** [4]
char*
char*
xz@xiaqiu:~/study/cpp-primer/study/1$ 





static char* s[] = {"black","white","pink","violet"};
--------------------------------------------
|s[0]|--------->"black"
|s[1]|--------->"white"
|s[2]|--------->"pink"
|s[3]|--------->"violet"
--------------------------------------------
s 	= s[0]
s+1 = s[1]
s+2 = s[2]
s+3 = s[3]

char **ptr[] = {s+3,s+2,s+1,s};

|ptr[0]|------->|s[3]|--------->"violet"
|ptr[1]|------->|s[2]|--------->"pink"
|ptr[2]|------->|s[1]|--------->"white"
|ptr[3]|------->|s[0]|--------->"black"

***p
p = ptr; 

p------->|ptr[0]|------->|s[3]|--------->"violet"
		 |ptr[1]|------->|s[2]|--------->"pink"
		 |ptr[2]|------->|s[1]|--------->"white"
		 |ptr[3]|------->|s[0]|--------->"black"
++p;
		 |ptr[0]|------->|s[3]|--------->"violet"
p------->|ptr[1]|------->|s[2]|--------->"pink"
		 |ptr[2]|------->|s[1]|--------->"white"
		 |ptr[3]|------->|s[0]|--------->"black"

(**p)+1
		 |ptr[0]|------->|s[3]|--------->"violet"
		 |ptr[1]|------->|s[2]|--------->"pink"<----------(**p)
		 |ptr[2]|------->|s[1]|--------->"white"
		 |ptr[3]|------->|s[0]|--------->"black"

(**p)+1------------------->"ink"






#include <iostream>
using namespace std;
class animal
{
protected:
	int age;
public:
	virtual void print_age(void) = 0;
	virtual void print_age1(void) = 0;

};

class dog:public animal
{
public:
	dog(){this->age = 2;}
	~dog(){}
	virtual void print_age(void)
	{
		cout<<"wang.my age = "<<this->age<<endl;
	}
	virtual void print_age1(void)
	{
		cout<<"wang.my age1 = "<<this->age<<endl;
	}

};

class cat : public animal
{
public:
	cat(){this->age = 1;}
	~cat(){}
	virtual void print_age(void){cout<<"Miao,my age= "<<this->age<<endl;}
	virtual void print_age1(void){cout<<"Miao,my age1= "<<this->age<<endl;}

};

int main()
{
	cat kitty,kitty1,kitty2;
	dog jd,jd1,jd2;
	animal *pa;
	int* p = (int*)(&kitty);
	int* p1 = (int*)(&kitty1);
	int* p2 = (int*)(&kitty2);
	int* q = (int*)(&jd);
	int* q1 = (int*)(&jd1);
	int* q2 = (int*)(&jd2);
	cout<<hex;
	cout<<q[0]<<endl;
	cout<<q1[0]<<endl;
	cout<<q2[0]<<endl;
	cout<<"-----------------"<<std::endl;
	cout<<p2[0]<<endl;
	cout<<p1[0]<<endl;
	cout<<p[0]<<endl;
	p[0] = q[0];
	pa = &kitty;
	pa->print_age();
	pa->print_age1();

	system("pause");
	return 0;
}





xz@xiaqiu:~/study/cpp-primer/study/1$ ./5 
2c44dce8
2c44dce8
2c44dce8
-----------------
2c44dcc8
2c44dcc8
2c44dcc8
wang.my age = 1
wang.my age1 = 1
sh: 1: pause: not found
xz@xiaqiu:~/study/cpp-primer/study/1$ 





#include <iostream>

using namespace std;
int i = 0;
int fun(int n)
{
	static int a = 2;
	a++;
	return (a * n);
}
int main()
{
	int k = 5;
	{
		int i = 2;
		k += fun(i); //2 x 3 + 5 = 11
		cout<<k<<endl;
	}
	k += fun(i);
	cout<<k<<endl;
	return (0);
}





xz@xiaqiu:~/study/cpp-primer/study/1$ ./6
11
11
xz@xiaqiu:~/study/cpp-primer/study/1$ 





#include <iostream>
using namespace std;
class B
{
public:
	B(){cout<<"default constructor"<<endl;}
	~B(){cout<<"destructed"<<endl;}
	B(int i):data(i)
	{cout<<"constructed by parameter "<<data<<endl;}
private:
	int data;
};
B Play(B b){ return b; }
int main()
{
	B temp = Play(5);
	return 0;
}





xz@xiaqiu:~/study/cpp-primer/study/1$ ./7
constructed by parameter 5
destructed
destructed
xz@xiaqiu:~/study/cpp-primer/study/1$ 





#include <stdio.h>
#include <string.h>

class CBuffer
{
	char *m_pBuffer;
	int m_size;
public:
	CBuffer(){ m_pBuffer = NULL;}
	~CBuffer(){ Free(); }
	void Allocte(int size) { 
		m_size = size; 
		m_pBuffer = new char[size];
	}
private:
	void Free()
	{
		if(m_pBuffer != NULL)
		{
			delete[] m_pBuffer;
			m_pBuffer = NULL;
		}
	}
public:
	void SaveString(const char* pText)
	{
		Allocte(sizeof(pText));
		strcpy(m_pBuffer,pText);
	}
	char *GetBuffer() const
	{
		return m_pBuffer;
	}
};

int main()
{
	CBuffer buffer1;
	buffer1.SaveString("Microsoft");
	printf("%s\n", buffer1.GetBuffer());
}





xz@xiaqiu:~/study/cpp-primer/study/1$ ./8
Microsoft
xz@xiaqiu:~/study/cpp-primer/study/1$ 



#include <cstddef>
#include <string>
#include <iostream>

using namespace std;

inline string make_plural(size_t ctr, const string& word,
							   const string& ending)
{
	return (ctr > 1) ? word + ending : word;
}

int main()
{
	size_t cnt = 1;
	cout<<make_plural(cnt,"success","es") << endl;
	cnt = 2;	
	cout<<make_plural(cnt,"failure","s")<<endl;

	return 0;
}

#include <iostream>
#include <string>

char &get_val(string &str, string::size_type ix)
{
	return str[ix];
}

int main()
{
	string s("a value");
	cout<<s<<endl;

	get_val(s,0) = 'A';
	cout<<s<<endl;

	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
a value
A value
xz@xiaqiu:~/study/cpp-primer/study/build$


#include <iostream>
#include <string>
#include <vector>
#include <cstddef>

// 返回 c 在 s 中第一次出现的索引
// 引用参数出现计算 c 出现的频率
string::size_type find_char(const string& s,char c,string::size_type &occurs)
{
	auto ret = s.size(); // 第一次出现的位置,
	occurs = 0; //如果有的话设置出现次数参数	

	for(decltype(ret) i = 0; i != s.size(); ++i)
	{
		if(s[i] == c)
		{
			if(ret == s.size())
				ret = i; // 记住第一次出现 c 
			++occurs; //增加出现次数
			
		}
	}
	return ret;// 计数在发生时隐式返回
}
// 返回一个引用第一次出现的值的迭代器
// 引用参数出现包含第二个返回值
vector<int>::const_iterator	find_char(
	vector<int>::const_iterator beg,// 第一个元素
	vector<int>::const_iterator end, // 最后一个元素
	int value,// 我们想要的值
	vector<int>::size_type &occurs // 出现的次数
	)
{
	auto res_iter = end;// res_iter 将保存第一次出现,如果有的话
	occurs = 0; // 设置出现次数参数

	for(;beg != end;++beg)
	{
		if(*beg == value)
		{
			// 记住第一次出现的值
			if(res_iter == end)
				res_iter = beg;
			++occurs;// 增加出现次数
		}
	}
	return res_iter; // 在发生时隐式返回的计数
}

int main()
{
	string s;
	getline(cin,s);
	size_t ctr = 0;
	auto index = find_char(s,'o',ctr);
	cout<<index<<" "<<ctr<<endl;

	vector<int> ivec;
	int i;
	// 在发生时隐式返回的计数
	while(cin >> i)
		ivec.push_back(i);

	// 对于整数列表中的每个值
	for(auto i : {42,33,92})
	{
		auto it = find_char(ivec.begin(),ivec.end(),i,ctr);
		if(it == ivec.end())
			cout<<i<<" is not in the input data"<<endl;
		else
			cout<<i<<" was at position "
				<<it - ivec.begin()<<endl;
	}
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
pooiiiidsao o oo o o oo 
1 10
32 32 32 33 3 33  33 333 333 42 42 42 42  9 9 9 92 92 92
42 was at position 9
33 was at position 3
92 was at position 16
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <iostream>
// get 返回对给定数组中元素的引用
int &get(int *arry, int index){ return arry[index]; }

int main()
{
	int ia[10]; // 十个未初始化整数的数组
	for(int i = 0; i != 10; ++i)
	{
		get(ia,i) = i;// 调用 get 为元素赋值
	}

	for(auto i : ia) // 打印元素
		cout<<i<<" ";
	cout<<endl;
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
0 1 2 3 4 5 6 7 8 9 
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <iostream>
#include <vector>

using namespace std;
// 引用 int 的函数
// 并将给定的对象设置为零
// i 只是传递给 reset 的对象的另一个名称
void reset(int &i)
{
	i = 0;// 改变 i 所指对象的值
}

// 带指针的函数
// 并将指向的值设置为零
void reset(int *ip)
{
	*ip = 0; // 改变ip指向的对象的值
	ip = 0;// 改变ip的本地副本; 参数不变
}

int main()
{
	int j = 42;
	reset(j); // j 通过引用传递; j 中的值发生了变化
	cout<<"j = "<<j<<endl; // prints j = 0

	j = 42;//恢复j的原始值
	reset(&j); // 改变 j 但不改变 j 的地址
	cout<<"j = "<<j<<endl;  // prints j = 0

	j = 42;//恢复j的原始值
	int *p = &j;
	reset(p); // 改变 p 指向的对象而不是 p 中的地址
	cout<<"j = "<<*p<<endl; // prints j = 0

	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
j = 0
j = 0
j = 0
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <iostream>
#include <iterator>

using namespace std;

// 打印一个以空字符结尾的字符数组
void print(const char *cp)
{
	if(cp) // 如果cp不是空指针
		while(*cp) // 只要它指向的字符不是空字符
			cout<<*cp++;// 打印字符并使指针前进
}

// 打印给定范围内的整数
void print(const int *beg,const int *end)
{
	// 打印从 beg 开始到但不包括 end 的每个元素
	while(beg != end)
		cout<<*beg++<<" "; // 打印当前元素
						   // 并推进指针 
}

int main()
{
	print("hi world!");// 调用第一个版本的打印
	cout<<endl;
	// j 被转换为指向 j 中第一个元素的指针
	// 第二个参数是指向 j 结尾之后的指针
	int j[2] = {0,1};
	print(begin(j),end(j)); // 库开始和结束函数
	cout<<endl;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
hi world!
0 1 
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <iostream>
#include <vector>

using namespace std;

// 返回整数向量中最小元素的函数
int min_element(vector<int>::iterator,
				vector<int>::iterator);
// 指向函数的指针,初始化为指向 min_element

int (*pf)(vector<int>::iterator,vector<int>::iterator) = min_element;

int main()
{
	vector<int> ivec{1,3,4,5,-1,32,-32};
	// 给 ivec 一些值
	cout<<"直接调用:"
		<<min_element(ivec.begin(),ivec.end())<<endl;

	cout<<"间接调用:"
		<<pf(ivec.begin(),ivec.end())<<endl;

	cout<<"等效的间接调用:"
		<<(*pf)(ivec.begin(),ivec.end())<<endl;

	return 0;
}

// 返回整数向量中的最小元素
int min_element(vector<int>::iterator beg,
				vector<int>::iterator end)
{
	int minVal = 0;
	while(beg != end)
	{
		if(minVal > *beg)
			minVal = *beg;
		++beg;
	}	
	return minVal;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
直接调用:-32
间接调用:-32
等效的间接调用:-32
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <cstddef>
#include <cassert>
#include <string>
#include <iostream>
using namespace std;

void print(const int ia[], size_t size)
{
#ifndef NDEBUG
// __func__ 是一个由编译器定义的局部静态变量,它保存着这个函数的名字
cerr<<__func__<<" : 数组大小是 "<<size<<endl;
#endif
}

int main()
{
	string word = "foo";
	const string::size_type threshold = 5;
	if(word.size() < threshold)
		cerr<<"错误: "<<__FILE__
			<<" : 在函数中 "<<__func__
			<<" 在行 "<<__LINE__<<endl
			<<" at "<<__TIME__<<endl
			<<"字读为 \""<<word
			<<"\": 长度太短"<<endl;
	word = "超过五个字符的长度";
	assert(word.size() > threshold);
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
错误: /home/xz/study/cpp-primer/study/main1.cpp : 在函数中 main 在行 3264
 at 21:24:24
字读为 "foo": 长度太短
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <string>
class Account
{
public:
	Account() = default;
	Account(const std::string &s,double amt):
		owner(s),amount(amt){}
	void calculate() { amount += amount * interestRate;}
	double balance() { return amount; }
public:
	static double rate() { return interestRate; }
	static void rate(double);
private:
	std::string owner;
	double amount = 0.0;
	static double interestRate;
	static double initRate() { return .0225; }
	static const std::string accountType;
	static constexpr int period = 30;// period 是一个常量表达式
	double daily_tbl[period];
};

// 定义静态数据和函数成员
const string Account::accountType("Saving Account");
double Account::interestRate = initRate();

void Account::rate(double newRate)
{
	interestRate = newRate;
}


#include <iostream>
using namespace std;

int main()
{
	Sales_data data1,data2;
	if(read(cin,data1) && read(cin,data2))
	{
		if(data1.isbn() == data2.isbn())// 读取交易
		{
			data1.combine(data2);// 添加交易
			print(cout,data1);// 打印结果
			cout<<endl;// 后跟一个换行符
		}
	}
	else
		cerr<<"Input failed!"<<endl;
	return 0;
}

#include <iostream>
using namespace std;

int main()
{
	Sales_data total; // 保存运行总和的变量
	if(read(cin, total)) // 读取第一笔交易
	{
		Sales_data trans;// 保存下一个交易数据的变量
		// 交易包含 ISBN、售出的副本数量和销售价格
		while(read(cin,trans)) // 读取剩余的交易
		{
			if(total.isbn() == trans.isbn()) // 检查isbn
			{
				total.combine(trans);// 更新运行总数
			}
			else
			{
				print(cout,total)<<endl;// 打印结果
				total = trans;// 处理下一本书
			}
		}
		print(cout,total)<<endl;// 打印最后一笔交易
	}
	else	// 没有输入
	{
		cerr << "No data?!" << endl;// 通知用户
	}
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
1111 12 12
1111 2 12
1111 2 32
1112 3 12
1111 16 232 14.5
1112 23 12
1112 13 12        
1112 39 468 12
xz@xiaqiu:~/study/cpp-primer/study/build$ 

class Debug
{
public:
	constexpr Debug(bool b = true):hw(b),io(b),other(b){}
	constexpr Debug(bool h,bool i,bool o):hw(h), io(i), other(o) { }
	constexpr bool any() const { return hw || io || other;}
	constexpr bool hardware(){ return hw || io;}
	constexpr bool app(){ return other; }

	void set_io(bool b){ io = b;}
	void set_hw(bool b){ hw = b;}
	void set_other(bool b){ hw = b; }
private:
	bool hw;// IO 错误以外的硬件错误
	bool io; // IO错误
	bool other; // 其他错误
};

class HW_Subsystem{
public:
	HW_Subsystem():debug(false){} // 默认不调试
	bool field_debug() { return debug.any(); }
	bool default_debug() const { return enable.any() && debug.any(); }
	void set_debug(bool b){ debug.set_hw(b);}//开启硬件调试
private:
	Debug debug;
	constexpr static Debug enable{true,false,false};
};

class IO_Subsystem{
public:
	IO_Subsystem():debug(false){}// 默认不调试
	bool field_debug() { return debug.any();}
	bool default_debug() { return enable.any() && debug.any();}
	void set_debug(bool b){ debug.set_io(b); }// 开启IO调试
private:
	Debug debug;
	constexpr static Debug enable{true,false,true};
};

#include <iostream>
using namespace std;

int main()
{
	constexpr Debug io_sub(false,true,false);//调试IO
	if(io_sub.any()) // 等价于 if(true)
		cerr<<"打印适当的错误信息"<<endl;
	constexpr Debug prod(false); // 生产过程中没有调试
	if(prod.any()) // 等价于 if(false)
		cerr<<"打印错误信息"<<endl;

	IO_Subsystem ioErrs;// 默认情况下,不打印任何调试信息
	// 这里没有调试
	if(ioErrs.default_debug()) // if (false || debug.any())
		cerr<<"打印消息 3"<<endl;
	ioErrs.set_debug(true);// 开启调试
	if(ioErrs.default_debug())  // if (false || debug.any())
		cerr<<"打印消息 4"<<endl;
	ioErrs.set_debug(false);// 好的,调试部分完成

	HW_Subsystem hw;
	hw.set_debug(true);
	if(ioErrs.default_debug() || hw.default_debug()) // if (false || debug.any())
			cerr<<"打印消息 5"<<endl;
}
xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
打印适当的错误信息
打印消息 4
打印消息 5
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <string>
#include <iostream>

class Screen
{
public:
	typedef std::string::size_type pos;
	Screen() = default; // 需要,因为 Screen 有另一个构造函数
	//cursor被它的类内初始化器初始化为 0
	Screen(pos ht,pos wd, char c): height(ht),width(wd),contents(ht * wd,c){}
	friend class Window_mgr;
	Screen(pos ht = 0,pos wd = 0):
		cursor(0),height(ht),width(wd),contents(ht * wd, ' '){}
	char get() const // 获取光标处的字符
	{
		return contents[cursor]; // 隐式内联
	}
	inline char get(pos ht, pos wd) const; // 显式内联
	Screen &clear(char = bkground);
private:
	static const char bkground = ' ';
public:
	Screen &move(pos r, pos c); // 可以稍后内联
	Screen &set(char);
	Screen &set(pos,pos,char);
	// 显示重载对象是否为常量
	Screen &display(std::ostream &os)
	{
		do_display(os);
		return *this;
	}
	const Screen &display(std::ostream &os) const
	{
		do_display(os);
		return *this;
	}
private:
	// 完成显示屏幕工作的函数
	void do_display(std::ostream &os) const { os << contents; }
	pos cursor = 0;
	pos height = 0,width = 0;
	std::string contents;
};

Screen &Screen::clear(char c)
{
	contents = std::string(height * width,c);
	return *this;
}

inline // 我们可以在定义中指定内联
Screen &Screen::move(pos r, pos c)
{
	pos row = r * width; // 计算行位置
	cursor = row + c; // 将光标移动到该行内的列
	return *this; // 将此对象作为左值返回
}

char Screen::get(pos r, pos c) const // 在类中声明为内联
{
	pos row = r * width;// 计算行位置
	return contents[row + c]; // 返回给定列的字符
}

inline Screen &Screen::set(char c)
{
	contents[cursor] = c;// 在当前光标位置设置新值
	return *this;// 将此对象作为左值返回
}

inline Screen &Screen::set(pos r, pos col, char ch)
{
	contents[r*width + col] = ch;// 将指定位置设置为给定值
	return *this; // 将此对象作为左值返回
}

#include <iostream>
#include <string>
using namespace std;
int main()
{
	Screen myScreen(5,3);
	// 将光标移动到给定位置,并设置该字符
	myScreen.move(4,0).set('#');

	Screen nextScreen(5,5,'X');
	nextScreen.move(4,0).set('#').display(cout);
	cout<<"\n";
	nextScreen.display(cout);
	cout<<endl;

	const Screen blank(5,3);
	myScreen.set('#').display(cout);// 调用非 const 版本
	cout<<endl;
	blank.display(cout);// 调用 const 版本
	cout<<endl;

	myScreen.clear('Z').display(cout); cout<<endl;
	myScreen.move(4,0);
	myScreen.set('#');
	myScreen.display(cout);cout<<endl;
	myScreen.clear('Z').display(cout); cout<<endl;

	// 如果移动返回屏幕而不是屏幕&
	Screen temp = myScreen.move(4,0);// 返回值将被复制
	temp.set('#');// myScreen 中的内容将保持不变
	myScreen.display(cout);
	cout<<endl;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
XXXXXXXXXXXXXXXXXXXX#XXXX
XXXXXXXXXXXXXXXXXXXX#XXXX
            #  
               
ZZZZZZZZZZZZZZZ
ZZZZZZZZZZZZ#ZZ
ZZZZZZZZZZZZZZZ
ZZZZZZZZZZZZZZZ
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <iostream>
using namespace std;
int main()
{
	// 写入 hi 和换行符,然后刷新缓冲区
	cout<<"hi!"<<endl;

	// 写入 hi,然后刷新缓冲区; 不添加数据
	cout<<"hi!"<<flush;

	// 写入 hi 和一个 null,然后刷新缓冲区
	cout<<"hi!"<<ends;

	cout<<unitbuf;// 所有写入将立即刷新

	// 立即刷新任何输出,无缓冲
	cout<<"first"<<"second"<<endl;
	cout<<nounitbuf;// 恢复正常缓冲

	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
hi!
hi!hi!firstsecond
xz@xiaqiu:~/study/cpp-primer/study/build$ 
#include <iostream>
#include <sstream>
#include <string>
using namespace std;

void read()
{
	// 打开fail和bad位
	cin.setstate(cin.badbit | cin.eofbit | cin.failbit);
}

void off()
{
	// 关闭 failbit 和 badbit 但所有其他位不变
	cin.clear(cin.rdstate() & ~cin.failbit & ~cin.badbit);
}

int main()
{
	cout<<"before read"<<endl<<endl;
	if(cin.good()) cout<<"cin's good"<<endl;
	if(cin.bad()) cout<<"cin's bad"<<endl;
	if(cin.fail()) cout<<"cin's fail"<<endl;
	if(cin.eof()) cout<<"cin's eof"<<endl;

	read();
	cout<<"after read"<<endl<<endl;
	if(cin.good()) cout<<"cin's good"<<endl;
	if(cin.bad()) cout<<"cin's bad"<<endl;
	if(cin.fail()) cout<<"cin's fail"<<endl;
	if(cin.eof()) cout<<"cin's eof"<<endl;

	off();
	cout<<"after off"<<endl<<endl;
	if (cin.good()) cout << "cin's good" << endl;
	if (cin.bad()) cout << "cin's bad" << endl;
	if (cin.fail()) cout << "cin's fail" << endl;
	if (cin.eof()) cout << "cin's eof" << endl;
	return 0;	
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
before read

cin's good
after read

cin's bad
cin's fail
cin's eof
after off

cin's eof
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <iostream>
#include <fstream>
#include <string>
#include <stdexcept>

using namespace std;

void process(ifstream &is)
{
	string s;
	while(is >> s)
		cout<<s<<endl;
}
int main(int argc,char* argv[])
{
	// 对于传递给程序的每个文件
	for(auto p = argv + 1; p != argv + argc;++p)
	{
		ifstream input(*p); // 创建输入并打开文件
		if(input) // 如果文件没问题,“处理”这个文件
		{
			process(input);
		}
		else
			cerr<<"couldn't open: "<<string(*p);
	}
	// 输入超出范围并在每次迭代时销毁
	auto p = argv + 1,end = argv + argc;

	ifstream input;
	while(p!=end) // 对于传递给程序的每个文件
	{
		input.open(*p);// 打开文件,自动清除流
		if(input)
		{
			process(input);// 如果文件没问题,读取并“处理”输入
		}
		else
			cerr<<"couldn't open: "+string(*p);
		input.close();// 完成后关闭文件
		++p;// 递增指针以获取下一个文件
	}
}



xz@xiaqiu:~/study/cpp-primer/study/build$ ./test test1.txt test2.txt 
test1.txt
test1.txt
test1.txt
test1.txt
test2.txt
test2.txt
test2.txt
test1.txt
test1.txt
test1.txt
test1.txt
test2.txt
test2.txt
test2.txt
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <iostream>
#include <sstream>
#include <vector>
#include <string>

using namespace std;
// 成员默认是公开的
struct PersonInfo
{
	string name;
	vector<string> phones;
};

// 我们将在第 17 章中看到如何重新格式化电话号码
// 现在只返回给定的字符串
string format(const string &s){ return s;}

bool valid(const string &s)
{
	// 我们将看到如何验证电话号码
	// 在第 17 章中,现在只返回 true
	return true;
}

vector<PersonInfo> getData(istream &is)
{
	//将分别保存输入中的一行和单词
	string line,word;

	// 将保存输入中的所有记录
	vector<PersonInfo> people;

	// 一次读取输入一行,直到文件结束(或其他错误)
	while(getline(is,line))
	{
		PersonInfo info;// 保存这条记录数据的对象
		istringstream record(line); // 将记录绑定到我们刚刚读取的行
		record >> info.name;//读取名字
		while(record >> word)//读取电话号码
			info.phones.push_back(word); // 并存储它们
		people.push_back(info); // 将此记录附加到人
	}
	return people;
}

ostream& process(ostream &os,vector<PersonInfo>people)
{
	for(const auto &entry : people) // 对于 people 中的每个条目
	{
		ostringstream formatted,badNums; // 在每个循环上创建的对象
		for(const auto &nums : entry.phones) // 对于每个number
		{
			if(!valid(nums))
			{
				badNums<<" "<<nums;// badNums 中的字符串
			}
			else
				// ``写入'' 到格式化的字符串
				formatted<<" "<<format(nums);
		}
		if(badNums.str().empty()) // 没有badNums
		{
			os<<entry.name<<" "// 打印名称
			  <<formatted.str()<<endl;// 和重新格式化的数字
		}
		else
		{
			// 否则,打印名称和错误数字
			cerr<<"input error: "<<entry.name
				<<" invalid number(s) "<<badNums.str()<<endl;
		}
	}
	return os;
}

int main()
{
	process(cout,getData(cin));

	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
xiao 12345678
chen 123344567
123344 344556
wang 12233244



zhao 23345454
xiao  12345678
chen  123344567
123344  344556
wang  12233244
 
 
 
zhao  23345454
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <vector>
#include <iostream>
using namespace std;

int main()
{
	vector<int> ivec;
	// 大小应该为零; 容量是实现定义的
	cout<<"ivec: size: "<<ivec.size()
		<<" capacity: "<<ivec.capacity()<<endl;

	// 给 ivec 24 个元素
	for(vector<int>::size_type ix = 0; ix != 24;++ix)
		ivec.push_back(ix);

	// 大小应该是 24; 容量将 >= 24 并且是实现定义的
	cout<<"ivec: size: "<<ivec.size()
		<<" capacity: "<<ivec.capacity()<<endl;
	ivec.reserve(50);// 将容量设置为至少 50; 可能更多
	// 大小应该是 24; 容量将 >= 50 并且是实现定义的
	cout<<"ivec: size: "<<ivec.size()
		<<" capacity: "<<ivec.capacity()<<endl;

	// 添加元素以用完多余的容量
	while(ivec.size() != ivec.capacity())
	{
		ivec.push_back(0);
	}

	// 容量应该保持不变,大小和容量现在相等
	cout<<"ivec: size: "<<ivec.size()
		<<" capacity: "<<ivec.capacity()<<endl;
	ivec.push_back(42);// 再添加一个元素

	// 大小应该是 51; 容量将 >= 51 并且是实现定义的
	cout<<"ivec: size: "<<ivec.size()
		<<" capacity: "<<ivec.capacity()<<endl;

	ivec.shrink_to_fit();// 请求返回内存

	// 大小应该保持不变; 容量是实现定义的
    cout << "ivec: size: " << ivec.size()
         << " capacity: "  << ivec.capacity() << endl;

    return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
ivec: size: 0 capacity: 0
ivec: size: 24 capacity: 32
ivec: size: 24 capacity: 50
ivec: size: 50 capacity: 50
ivec: size: 51 capacity: 100
ivec: size: 51 capacity: 51
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <list>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

int main()
{
	list<string> slist;
	string s;
	while(cin >> s)
		slist.push_back(s);// 将内容读入slist
	/* 我们将在第 10 章解释 find
	* find 在其前两个表示的序列中查找
	* 迭代器参数为其第三个参数的值
	* 将迭代器返回到具有该值的第一个元素
	* 如果该元素存在于输入序列中
	* 否则返回结束迭代器
	*/
	auto iter = std::find(slist.begin(),slist.end(),"Quasimodo");
	if(iter != slist.end())
		slist.erase(iter);

	auto orig = slist; // 在销毁内容之前保留一份副本
	slist.clear();// 删除容器内的所有元素
	cout<<"after clear,size is: "<<slist.size()<<endl;

	slist = orig; //恢复数据
	slist.erase(slist.begin(),slist.end()); // equivalent
	cout<<"after erase begin to end, size is: "<<slist.size()<<endl;

	slist = orig; //恢复数据
	auto elem1 = slist.begin(),elem2 = slist.end();
	// 删除两个迭代器之间的元素范围
	// 返回一个迭代器到最后一个被移除元素之后的元素
	elem1 = slist.erase(elem1,elem2);// 在调用 elem1 == elem2 之后
	cout<<"after erase elem1 to elem2 size is: "<<slist.size()<<endl;

	if(elem1 != elem2)
		cout<<"something wrong"<<endl;
	else
		cout<<"okay, they're equal "<<endl;
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
 aa aa aa cc cc ccc dd dd dd dd ss ss ss xx xx xx xx  ccc cc cc cc ss sd dsa dsa dsa d xz xz xz cd fd wed sa dsa dsa dsd dsa sd fd dsa dsf rfgr grf gr g r gre gre ger g
after clear,size is: 0
after erase begin to end, size is: 0
after erase elem1 to elem2 size is: 0
okay, they're equal 
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <algorithm>
#include <string>
#include <forward_list>
#include <vector>
#include <iostream>
#include <list>

using namespace std;

int main()
{
	// 在调用 elem1 == elem2 之后
	list<int> lst = {0,1,2,3,4,5,6,7,8,9};

	// 打印 lst 中的初始值
	cout<<"initial list: ";
	for(auto it : lst)
		cout<<it<<" ";
	cout<<endl;

	// 删除列表中的奇数元素
	auto it = lst.begin();
	while(it != lst.end())
		if(*it % 2)// 如果元素是奇数
			it = lst.erase(it); // 删除这个元素
		else
			++it;

	// 打印lst的当前内容
	cout<<"从列表中删除奇数元素后:";
	for(auto it : lst)
		cout<<it<<" ";
	cout<<endl;

	// 重复相同的动作,但在 forward_list 上
	forward_list<int> flst = {0,1,2,3,4,5,6,7,8,9};

	// 在平面上打印初始值
	cout<<"initial list:";
	for(auto it : flst)
		cout<<it<<" ";
	cout<<endl;
	// 在平面上打印初始值
	auto prev = flst.before_begin();// 元素“离开始”的平面
	auto curr = flst.begin();// 表示 flat 中的第一个元素
	while(curr != flst.end()) // 虽然还有元素
	{
		if(*curr % 2) // 如果元素是奇数
			curr = flst.erase_after(prev); // 删除它并移动 curr
		else
		{
			prev = curr;// 移动迭代器以表示下一个
			++curr;// 元素和下一个元素之前的一个
		}
	}
	// 打印lst的当前内容
	cout<<"从 flst 擦除元素后:";
	for(auto it : flst)
		cout<<it<<" ";
	cout<<endl;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
initial list: 0 1 2 3 4 5 6 7 8 9 
从列表中删除奇数元素后:0 2 4 6 8 
initial list:0 1 2 3 4 5 6 7 8 9 
从 flst 擦除元素后:0 2 4 6 8 
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <iostream>
#include <string>
using namespace std;

int main()
{
	string name("AnnaBelle");
	auto pos1 = name.find("Anna"); // pos1 == 0
	cout<<pos1<<" ";
	string lowercase("annabelle");
	pos1 = lowercase.find("Anna"); // pos1 == npos
	cout<<" "<<pos1<<" string::npos="<<string::npos<<endl;
	return 0;
}

#include <string>
#include <iostream>

using namespace std;

int main()
{
	string numbers("0123456789"),name("r2d2");
	// 返回 1,即 name 中第一个数字的索引
	auto pos = name.find_first_of(numbers);
	if(pos != string::npos)
	{
		cout<<"found number at index: " <<pos
			<<" element is "<<name[pos]<<endl;
	}
	else
		cout<<"no number in: "<<name<<endl;

	pos = 0;
	// 每次迭代查找名称中的下一个数字
	while((pos = name.find_first_of(numbers,pos)) != 
		string::npos)
	{
		cout<<"found number at index: "<<pos
			<<" element is "<<name[pos]<<endl;

		++pos;// 移动到下一个字符
	}
	string river("Mississippi");

	auto first_pos = river.find("is");// returns 1
	auto last_pos = river.rfind("is");// returns 4
	cout<<"find returned: "<<first_pos
		<<" rfind returned: "<<last_pos<<endl;

	string dept("03714p3");
	// 返回 5,这是字符 'p' 的索引
	pos = dept.find_first_not_of(numbers);
	cout<<"first_not returned: "<<pos<<endl;

	// uint32_t u1 = 0x1p16f;
	// uint32_t u2 = 0x1p32f;
	// cout<<u1<<endl;
	// cout<<u2<<endl;
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
found number at index: 1 element is 2
found number at index: 1 element is 2
found number at index: 3 element is 2
find returned: 1 rfind returned: 4
first_not returned: 5
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <vector>
#include <iostream>
using namespace std;

void printVec(const vector<int> &vi)
{
	// 打印向量的元素
	auto iter = vi.begin();
	while(iter != vi.end())
		cout<<*iter++<<" ";
	cout<<endl;
}

int main()
{
	// 删除偶值元素的愚蠢循环
	// 并插入一个奇数元素的副本
	vector<int> vi = {0,1,2,3,4,5,6,7,8,9};
	printVec(vi);

	// 我们调用begin,而不是cbegin,因为我们正在改变vi
	auto iter = vi.begin();
	while(iter != vi.end())
	{
		if(*iter % 2)// 如果元素是奇数
		{
			iter = vi.insert(iter,*iter); // 复制它
			iter += 2;// 跳过这个元素和新元素
		}
		else
			iter = vi.erase(iter); // 删除偶数元素
		// 不要推进迭代器;
		// iter 表示我们擦除后的元素
	}
	printVec(vi);
	return 0;
}
xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
0 1 2 3 4 5 6 7 8 9 
1 1 3 3 5 5 7 7 9 9 
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <cstddef>
#include <deque>
#include <stack>
#include <iostream>
using namespace std;

bool process(int);

int main()
{
	stack<int> intStack; // 空栈
	// 填满栈
	for(size_t ix = 0; ix != 10; ++ix)
		intStack.push(ix);
	// intStack 持有 0 。 . . 9 包含
	// 当 intStack 中还有值时
	while(!intStack.empty())
	{
		int value = intStack.top();
		// 使用值的代码
		cout<<value<<" ";
		intStack.pop();// 弹出顶部元素,并重复
	}
	cout<<endl;
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
9 8 7 6 5 4 3 2 1 0 
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <string>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
	string s = "some string",s2	= "some other string";
	// 在 s 开头插入 s2 中所有字符的等效方法
	// 在 s.begin() 之前插入迭代器范围
	s.insert(s.begin(),s2.begin(),s2.end());
	cout<<"insert iterators version: "<<s<<endl;

	s = "some string";
	s.insert(0,s2);// 在 s 中的位置 0 之前插入 s2 的副本
	cout<<"insert string at given position: "<<s<<endl;

	s = "some string";
	// 在 s[0] 之前从 s2[0] 开始从 s2 插入 s2.size() 字符
	s.insert(0,s2,0,s2.size());
	cout<<"insert positional version: "<<s<<endl;

	s = "";//s 现在是空的
	vector<char> c_vec(1,'a');
	// 将 c_vec 中的字符插入到 s
	s.insert(s.begin(),c_vec.begin(),c_vec.end());
	s.insert(s.size(),5,'!');// 在 s 末尾添加五个感叹号
	cout<<s<<endl;

	s.erase(s.size() - 5,5);// 删除 s 的最后五个字符
	cout<<s<<endl;

	s = "";// s 现在是空的
	const char *cp = "Stately, plump Buck";
	s.assign(cp,7);// s == "Stately"
	cout<<s<<endl;
	s.insert(s.size(), cp + 7);// s == "Stately, plump Buck"
	cout<<s<<endl;

	s = "C++ primer";// 重置 s 和 s2
	s2 = s;// to "C++ Primer"
	s.insert(s.size(),"4th Ed ");// s == "C++ Primer 4th Ed."
	s2.append(" 4th Ed.");// 等效:附加“第 4 版”。 到 s2;
	cout<<s<<" "<<s2<<endl;

	// 用“5th”替换“4th”的两种方式
	//1.插入和擦除
	s.erase(11,3);// s == "C++ Primer Ed."
	s.insert(11,"5th");// s == "C++ Primer 5th Ed."

	// 2. 使用替换
	// 从位置 11 开始擦除三个字符
	// 然后插入“5th”
	s2.replace(11,3,"5th");// equivalent: s == s2
	cout<<s<<" "<<s2<<endl;

	// 用“5th”替换“Fifth”的两种方法
	// 1. 如果我们知道要替换的字符串在哪里,则使用替换
	s.replace(11,3,"Fifth");// s == "C++ Primer Fifth Ed."

	// 2. 首先调用 find 来获取要替换的位置
	auto pos = s2.find("5th");
	if(pos!=string::npos)
		s2.replace(pos,3,"Fifth");
	else
		cout<<"something's wrong. s2 is: "<<s2<<endl;
	cout<<s<<" "<<s2<<endl;

	return 0; 
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
insert iterators version: some other stringsome string
insert string at given position: some other stringsome string
insert positional version: some other stringsome string
a!!!!!
a
Stately
Stately, plump Buck
C++ primer4th Ed  C++ primer 4th Ed.
C++ primer45thEd  C++ primer 5th Ed.
C++ primer4FifthEd  C++ primer Fifth Ed.
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <string>
#include <iostream>
#include <stdexcept>

using namespace std;
int main()
{
	try
	{
		string s("hello world");
		cout<<s.substr(0,5)<<endl; // prints hello
		cout<<s.substr(6)<<endl; // prints world
		cout<<s.substr(6,11)<<endl; // prints world
		cout<<s.substr(12)<<endl; // throws out_of_range 
	}
	catch(out_of_range)
	{
		cout<<"caught out_of_range"<<endl;
	}
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
hello
world
world
caught out_of_range
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <vector>
#include <iterator>
#include <iostream>
#include <algorithm>
using namespace std;

int main()
{
	vector<int> vi;
	int i;
	while(cin>>i)
		vi.push_back(i);
	// 将 lambda 传递给 for_each 以打印 vi 中的每个元素
	for_each(vi.begin(),vi.end(),[](int i){ cout<<i<<" ";});
	cout<<endl;

	vector<int> orig = vi; // 在vi中保存原始数据

	//用它们的绝对值替换负值
	std::transform(vi.begin(),vi.end(),vi.begin(),[](int i){return i < 0?-i:i;});
	// 现在在 vi 中打印元素
	for_each(vi.begin(),vi.end(),[](int i){cout<<i<<" ";});
	cout<<endl;

	vi = orig;// 重新开始
	// 使用具有指定返回类型的 lambda 来转换 vi
	transform(vi.begin(),vi.end(),vi.begin(),[](int i)->int{
		if(i<0) return -i;else return i;
	});
	// 现在在 vi 中打印元素
	for_each(vi.begin(),vi.end(),[](int i){cout<<i<<" ";});
	cout<<endl;

	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
-1 -12 -23 233232 3 232  32  32 13 21 -21 -434
-1 -12 -23 233232 3 232 32 32 13 21 -21 -434 
1 12 23 233232 3 232 32 32 13 21 21 434 
1 12 23 233232 3 232 32 32 13 21 21 434 
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <vector>
#include <string>
#include <algorithm>
#include <numeric>
#include <iterator>
#include <iostream>

using namespace std;

int main()
{
	vector<int> vec(10); // 默认初始化为 0
	fill(vec.begin(),vec.end(),1);// 将每个元素重置为 1

	// 对 vec 中的元素求和,从值 0 开始求和
	int sum = accumulate(vec.begin(),vec.end(),0);
	cout<<sum<<endl;

	// 将容器的一个子序列设置为 10
	fill(vec.begin(),vec.begin() + vec.size()/2,10);
	cout<<accumulate(vec.begin(), vec.end(),0)<<endl;

	// 将相同的子序列重置为 0
	fill_n(vec.begin(),vec.size()/2,0);
	cout<<accumulate(vec.begin(),vec.end(), 0)<<endl;

	// 在 vec 的末尾创建 10 个元素,每个元素的值为 42
	fill_n(back_inserter(vec),10,42);
	cout<<accumulate(vec.begin(),vec.end(),0)<<endl;

	// 连接字符串向量中的元素并存储在总和中
	vector<string> v;
	string s;
	while(cin>>s)
		v.push_back(s);
	string concat = accumulate(v.cbegin(),v.cend(),string(" "));
	cout<<concat<<endl;

	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
10
55
5
425
hello           world
   xiao
 helloworldxiao
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#include <numeric>
#include <iterator>
#include <iostream>
using namespace std;

int main()
{
	istream_iterator<int> in(cin),eof;
	cout<<accumulate(in,eof,0)<<endl;
	return 0;
}

xz@xiaqiu:~/study/cpp-primer/study/build$ ./test 
1 2 23  4 5
35
xz@xiaqiu:~/study/cpp-primer/study/build$ 

#endif

举报

相关推荐

0 条评论