C++_programming_basis_1(函数,类,指针,const)

#include<iostream>
#include<string>
#include<vector>
#include<cctype>
#include<initializer_list>
#include<istream>
#include<fstream>


//run时候的问题我觉得是因为把这个import到了3文件

using std::istream;
using std::ostream;
using std::string;
using std::cin;
using std::cout;
using std::endl;
using std::getline;
using std::size;
using std::empty;
using std::vector;
using std::begin;
using std::end;
using std::initializer_list;
typedef string::size_type sz;
using F = int(int*, int);//F是函数类型
using PF = int(*)(int*, int);//PF是指针类型
string screen(sz ht = 24, sz wid = 80, char backgrnd = ' ');
string screen1(sz sd=12 , sz ed=78, char=' ');
bool lengthcompare(const string &, const string &);//用来函数指针

//声明放在调用后面的函数
int fact(int cc);
void reset(int *p);
void re(int &i);
void print(const int *beg, const int *end);
void printtt(const int ia[10]);
const string &shortS(const string &s1, const string &s2);
string &shortSt(string &s1, string &s2);
char &get_val(string &str, string::size_type ix);
int main() {
	cout << "enter two numbers,please" << endl;
	int v1, v2;
	cin >> v1 >> v2;
	cout << "the sum of " << v1 << "and " << v2 << "is  " << v1 + v2 << endl;//输入输出

	string s;
	while (getline(cin,s))//getline函数
		if(s.size()>3)
		cout << s << endl;
		
	string ass = "sad ";
	string fd = ass + ", ";
	string ed = ", ";
	string gd = ed + ", ";//不允许字符串字面值直接相加
	string v("sdsafa asdfasw ew");
	for (auto c : v)
		cout << c << endl;//按字符输出
	string ds = "hello world!!!@";
	decltype(ds.size()) punct_cnt = 0;
	for (auto c : ds)
		if (ispunct(c))
			++punct_cnt;
	cout << punct_cnt << "\n" << ds << endl;
	
	string rd("dsfa ef!!");
	for (auto &c : rd)
		c = toupper(c);
	cout << rd << endl;//重新试的时候忘了include string了  没问题
	//这个例子实在说明使用引用可以改变我们的实参值
	
	const string sixteen ("0123456789ABCDEF");
	cout << "enter a series of numbers" << endl;
	string result;
	string::size_type n;
	while (cin >> n)
	
		if (n < sixteen.size())
			result += sixteen[n];
		cout << result << endl;
	string es("sde efrf");
	for (auto &c : es)
		if(!es.empty())
			c = 'x';
		cout << es << endl;


	vector <string>art = { "ss" , "ds","df"};//列表初始化
	vector<string>aw(art);//直接传递拷贝初始化
	vector<int>qwer(12, -2);//创建指定数量元素  以上为三种直接初始化的例子 元素较少,元素全相同,一个是另一个的副本
	vector<int>eddc(12, 3);
	vector<string>ws(12, "dew");
	vector<string>ed(12);//int和string支持默认初始化 有些未必支持
	vector<int>wws{ 10,1 };//列表初始化
	vector<int>wse(10, 1);//10个1
	vector<int>was(10);//10个初始值为0
	vector<int>wqw{ 10 };//1个初始值为0
	vector<string>qwe{ 10,"ws" };
	
	int ww;
	vector<int>tr;
	while (cin>>ww)
	{
		tr.push_back(ww);
	}//添加元素类似Python的append后入

	vector<string>wx{ "wdew","ws","wsc" };
	for (auto i : wx)
		cout << i << " ";//千万注意,这是vector,不能直接cout,以下边cout可以的
	
	vector<unsigned>score(11, 0);
	unsigned grade;
	while (cin >> grade)
	{
		if (grade <= 100)
			++score[grade / 10];
	}

	vector<int>we;
	we.push_back(10);

	int sad = fact(4);
	cout << sad << endl;
	
	int i = 42;
	reset(&i);
	cout << i << endl;//引用还是改变了实参值

	int j = 42;
	re(j);
	cout << j << endl;//传引用 改变实参值

	int j[2] = {0,1};
	print(begin(j), end(j));//使用的标准库函数

	int j[10] = { 0,1,2,3,4,8,21,12,23,};//你把初始值设定多了会报错 但少了不会报错
	printtt(j);	//????	

	string aa = shortS("dsfs", "dsdaewde");
	cout << aa << endl;

	//shortSt("as", "wedecee") = "zzzzzzzzzz";这一行错在他本身就是个常量,不是个可以接纳赋值的变量

	string suv("a value");
	cout << suv << endl;
	get_val(suv, 0) = 'A';//你看它函数定义  它的返回值类型是引用 所以可以改变 
	cout << suv << endl;
	
	screen(66);//形参不能跳过设定,必须一一设定,或者从前往后
	
	//函数指针的应用
	bool(*pf)(const string&, const string &);//你看,先在下面定义函数,然后在前面声明一下下,接着在这里定义一个函数指针(尚未初始化)
	pf = lengthcompare;//这是赋值哦很简单
	bool b1 = pf("hello ", "sadew");//这里是函数指针的调用
	bool b2 = (*pf)("sd", "ewdfew");//一样样的跟上头
	bool b3 = lengthcompare("wde", "wedf");//等价

	Sales_data total;

	//返回一个this类型的函数
	Screen::pos ht = 24, wd = 80;
	Screen scr(ht, wd, ' ');//定义初始化一个Screen类
	Screen *p = &scr;//类对象的使用
	char c = scr.get();
	c = p->get();


	string rf = screen1(23, 34);//这是调用有部分默认形参的函数

	double r;
	r = account::rate();//这是访问account类的static成员rate

	account ac1;
	account *ac2 = &ac1;
	r = ac1.rate();//虽然static成员不属于任何一个account类的对象 但可以通过对象访问(引用 指针等)
	r = ac2->rate();

	auto old_state = cin.rdstate();//
	cin.clear();
	cin.setstate(old_state);

	
system("pause");return 0;

}
int fact(int cc) {
	int co = 1;
	while (cc>1)
	{
		co *= cc--;
	}
	return co;//调用函数普通  2.如果有两个形参 也得把两个都写出类型如int a,int b

}
void reset(int *p) {
	*p = 0;//只改变了&i实参的i值
	p = 0;//指针形参,传值参数,不会改变实参值
}
void re(int &i)//传引用参数,可以改变实参的值
{
	i = 0;
}


void print(const int *beg, const int *end) {
	while (beg!=end)
	{
		cout << *beg++ << endl;//这种方法规定实参的首末指针(使用标准库规范begin,end)
	}
}

void printt(const int ia[], size_t size) {//直接规定了指针和实参的长度size
	for (size_t i = 0; i != size; ++i) {
		cout << ia[i] << endl;
	}
}
void printtt(const int ia[10]) {//无措但是该函数遇到调用时数组并非10个时也工作因此可能导致输出多个0
	for (size_t i = 0; i != 10; ++i) {
		cout << ia[i] << endl;
		
	}
}
void error_msg(initializer_list<string> i1) {//initializer_list的应用 可以接受不同数量的形参
	for (auto beg = i1.begin(); beg != i1.end(); ++beg) {
		cout << *beg << " ";
		cout << endl;
	}
}

void swap(int &a, int &b) {//函数中return执行条件中途退出的功能类似于break
	if (a == b)
		return;
	else
	{
		int temp = a;
		a = b;
		b = temp;
	}
}
const string &shortS(const string &s1, const string &s2) {//形参尽量避免拷贝,尽量使用引用,第二,return语句
	return s1.size() <= s2.size() ? s1 : s2;
}

string &shortSt(string &s1, string &s2) {//尝试
	return s1.size() <= s2.size() ? s1 : s2;
}

char &get_val(string &str, string::size_type ix) {//返回值是引用类型 所以可以改变  也就是相当于赋值
	return  str[ix];
}

int mul(int val) {//递归函数
	if (val > 1)
		return mul(val - 1)*val;
	return 1;
}
void print(int &a, string &b) {//同名函数形参不一样即可 重载
	cout << a << "  " << b << endl;
}
typedef string::size_type sz;
string screen(sz , sz , char ) {//默认形参
	return 0;
}
inline string screen1(sz, sz, char) {//部分默认形参形式  内联函数

}
constexpr int cd = 23;
constexpr int new_pr() { return 42; }
constexpr int foo = new_pr();//可以用于常量表达式的函数 才叫做常量表达式函数constexpr

void f(int) {

}
void f(int, int) {

}
void f(double t, double tz) {//函数匹配问题

}

//函数指针可以做形参 也可以做函数返回值
bool lengthcompare(const string &, const string &) { return 0; }//用来函数指针
void usebigger(const string &s1, const string &s2, bool pf(const string &, const string &)) {}//这是函数(指针)作为形参的第一次pf会被转为指针

void usebiggerr(const string &s1, const string &s2, bool *pf(const string &, const string &)) {}//等价

//函数的返回值为 指向函数的指针
PF f1(int){}//该函数返回指向函数的指针  在前面先声明using哦——函数指针作为另一函数的返回值
F *f2(int){}//显式地指定返回类型是指向函数的指针


//类
struct Sales_data//一个类的实验
{//这是进阶版的四个函数
public://这两个叫做访问说明符 public允许在整个程序访问
	Sales_data() = default;//三个定义的构造函数  default是使之指向默认构造
	Sales_data(const string &s):bookNo(s){}//:表示对数据成员赋初值,成为初始值列表 所以函数体为空
	Sales_data(const string &s,unsigned n,double p)://所有定义在类内部的函数自动是inlinebookNo(s),units_sold(n),revenue(p*n){}
	Sales_data(istream &);//这个是声明的构造函数  定义在类外部
	
	//下面(这是初阶版的)
	string isdn()const { return bookNo; }//直接定义函数
	Sales_data& combine(const Sales_data&);
	double avg_price()const;//单纯声明

private://而private只允许被类的成员函数调用访问(封装在内部啦)danshi这样的话辅助函数add和print也没法访问了 然后看有缘friend
	string bookNo;//成员定义放在前后没有任何关系(编译原理)
	unsigned units_sold = 0;
	double revenue = 0.0;

	friend Sales_data add(const Sales_data&, const Sales_data&);//有缘friend用来允许辅助函数add等对private的成员数据进行访问
	friend istream &read(istream&, Sales_data&);//friend不能代替函数调用的声明 只是对访问数据的声明耳 
	friend ostream &print(ostream&, const Sales_data&);//friend只可以出现在类定义内部,但次序随意
	
};
Sales_data add(const Sales_data&, const Sales_data&);//???XDD这些三个都是类的辅助函数不属于类本身 在外
ostream &print(ostream &, const Sales_data&);//辅助函数de 声明XD
istream &read(istream&, Sales_data&);


double Sales_data::avg_price()const {//在类的外部定义成员函数 注意1.声明类的名字2.如果是常量成员函数就const3.类内成员编译可直接识别
	if (units_sold)return revenue / units_sold;
	else
		return 0;
}

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.isdn() << " " << item.units_sold << " " <<
		item.revenue << " " << item.avg_price();
	return os;
}
Sales_data add(const Sales_data &lhs, const Sales_data &rhs) {
	Sales_data sum = lhs;
	sum.combine(rhs);
	return sum;
}

Sales_data::Sales_data(istream &is) { read(is, *this); }//这是构造函数在类外部 函数体非空(执行一定的功能)

class Screen {
public:
	friend class window_mgr;//声明友元类
	//也可以直接去把需要调用别人数据的成员函数声明为有缘 但是对重载的函数需要一一声明
	//友元函数甚至可以直接定义在调用的这个的类内部,但是 友元声明终究不是函数声明,它只代表访问权限 要用该函数还是要声明 ok??
	typedef string::size_type pos;
	Screen() = default;//默认
	Screen(pos ht,pos wd,char c):height(ht),width(wd),contents(ht*wd,c){}//定义在类内的成员函数自动inline  这行是非默认初始化
	char get()const { return contents[cursor]; }
	inline char get(pos ht, pos wd)const;//这个是在类外定义的成员函数但在类内直接显式的声明称inline哒
	Screen &move(pos r, pos c);

	//小进阶
	Screen &set(char);//注意了 我们定义的这个函数就是个引用型& 如果不是将无法*this来改变Screen的值
	Screen &set(pos, pos, char);//定义在外面

	Screen &display(ostream &os) { do_display(os); return *this; }//这两个display函数涉及重载 所以在某个对象上调用之
	const Screen &display(ostream &os)const { do_display(os); return *this; }//时该对象是否const决定了调用which
private:
	pos cursor = 0;
	pos height = 0, width = 0;
	string contents;

	void do_display(ostream &os) const { os << contents; }//负责打印screen 的工作内容
};//class后有;记得要

inline //类外的成员函数想要inline必须手动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 {//已经在类内声明为inline辣
	pos row = r * width;
	return contents[row + c];
}

class screen {//定义一个const的成员函数和一个即将被调用的mutable数据,他是可变的
public:
	void some_member() const ;
private:
	mutable size_t access_ctr;
};
void screen::some_member()const {
	++access_ctr;
}

class window_mgr {//类数据成员的初始化{}或者=
public:
	using ScreenIndex = vector<Screen>::size_type;
	void clear(ScreenIndex);
private:
	vector<Screen>screens{ Screen(24,80,' ') };
	
};
void window_mgr::clear(ScreenIndex i) {//作为有缘类的成员函数来调用朋友的数据height,width
	Screen &s = screens[i];
	s.contents = string(s.height*s.width, ' ');

}

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;
}
class student;//类可以先声明不定义
Sales_data aa;
struct Sales_data as;//同上等价
//student ads;

class link_screen {
	Screen window;
	link_screen *next;
	link_screen &asd;//在这个类中,类还没被定义完 这时可以包含自身类型的引用或指针,而不能直接用它定义类
};

class X {
	int i;
	int j;
private:
	X(int val):j(val),i(j){}
};//因为成员初始化顺序需要和类定义中的出现顺序一致 所以应该先i后j 但编译没警告

class account {
public:
	void calculate() { amount += amount * interestRate; }//成员函数可以直接访问static成员
	static double rate() { return interestRate; }//静态成员不得const也不得调用this
	static void rate(double);//使用作用域运算符可访问  她的定义在外
private:
	string owner;
	double amount;
	static double interestRate;//
	static double initRate();

};

void account::rate(double newrate) {//在类外定义static成员函数
	interestRate = newrate;//ta在类里是个static,但不能重复说static
}
double account::interestRate = initRate();//必须在类的外部定义和初始化每个static成员,只许定义once



发布了44 篇原创文章 · 获赞 9 · 访问量 3387

猜你喜欢

转载自blog.csdn.net/puying1/article/details/83691329