本人初学C++,代码有问题的地方希望能够指出!
#include<iostream>
#include<algorithm>
using namespace std;
/*练习6.6:
形参:函数调用时会用一个实参初始化,函数结束时,形参被销毁
局部变量:程序运行到它时,被创建,该程序块结束时被销毁
局部静态变量:程序运行到它时,被创建,所有程序结束时被销毁
*/
//书中例子
int vary(int val) {
int localnum = val;
static int globalnum = 0;
localnum += globalnum++;
return localnum;
}
void test66(){
for (int i = 0; i < 5; i++) {
cout << "第"<<i<<"次输出为"<<vary(5)<< endl;
}
}
//练习6.7
size_t zerofun() {
static size_t num = -1;
num++;
return num;
}
void test67() {
for(int i=0;i<10;i++)
cout << zerofun() << endl;
}
int main() {
//test66();
test67();
return 0;
}
#include<iostream>
#include<algorithm>
#include"Chapter6.h"
using namespace std;
/*练习6.6:
形参:函数调用时会用一个实参初始化,函数结束时,形参被销毁
局部变量:程序运行到它时,被创建,该程序块结束时被销毁
局部静态变量:程序运行到它时,被创建,所有程序结束时被销毁
*/
int vary(int val) {
int localnum = val;
static int globalnum = 0;
localnum += globalnum++;
return localnum;
}
void test66() {
for (int i = 0; i < 5; i++) {
cout << "第" << i << "次输出为" << vary(5) << endl;
}
}
//练习6.7
size_t zerofun() {
static size_t num = -1;
num++;
return num;
}
void test67() {
for (int i = 0; i < 10; i++)
cout << zerofun() << endl;
}
int main() {
//test66();
test67();
return 0;
}
#include<iostream>
#include"Chapter6.h"
using namespace std;
void swapnum(int *i,int *j) {
int temp = *j;
*j = *i;
*i = temp;
}
void test610()
{
int i = 10, j=50;
cout << "交换前i的值为" << i << endl;
cout << "交换前j的值为" << j << endl;
swapnum(&i,&j);
cout << "交换后i的值为" << i << endl;
cout << "交换后j的值为" << j << endl;
}
int main()
{
int n = 0, i = 42;
int* p = &n, * q = &i; //p的类型是指针,初始化为地址
cout << *p << endl;//对指针类型进行解引用,得到指针对应地址存储的值
cout << p << endl;//指针存储的为地址
*p = 42;//对指针对应地址进行赋值操作
p = q;//将q指针指向的地址赋给p,此时p为i的地址
cout << *p << endl;
//p = 0;
//cout << *p << endl;//把指针p指向的地址赋为了0,出错
cout << "n的值为" << n << endl;
cout << "i的值为" << i << endl;
cout << "p的值为" << p << endl;
cout << "q的值为" << q << endl;
//练习6.10------------------------------------------------
test610();
return 0;
}
#include<iostream>
#include<algorithm>
using namespace std;
#include"Chapter6.h"
#include<string>
//书中例子
int find_char(const string& s, char c, int & occurs)
{
auto ret = s.size();//ret 为输入字符串的长度
occurs = 0;
for (decltype(ret) i = 0; i != s.size(); ++i)
{
if (s[i] == c) {
if (ret == s.size())
ret = i;
++occurs;
}
}
return ret;
}
void test() {
string s = "heloollo";
int ctr;
auto index = find_char(s, 'o', ctr);
cout << index << endl;
cout << ctr << endl;
}
//练习6.11-------------------------------------------------
void reset(int& val) {
val++;
}
void test611() {
int val = 0;
for (int i = 0; i < 10; i++) {
reset(val);
cout << val << endl;
}
}
//练习6.12-------------------------
void swap(int& i, int& j) {
int temp = i;
i = j;
j = temp;
}
void test612() {
int a = 10;
int b = 50;
cout << "交换前a的值为" << a << endl;
cout << "交换前b的值为" << b << endl;
swap(a, b);
cout << "交换后a的值为" << a << endl;
cout << "交换后b的值为" << b << endl;
}
/*练习6.13
void f(T):声明函数的形参为T类型
void f(&T):声明函数的形参为T类型的引用,直接对初始化形参的实参进行更改
*/
/*
练习6.14
形参是引用:对数组进行排序时
形参不是引用:写一个两数运算的函数时
*/
/*
练习6.15
s是常量引用:因为不希望对输入的字符串进行修改,
并且s有可能过长,所以用引用,避免再次copy
如果s为普通引用,会造成内存浪费
occurs是普通引用:希望对occurs进行修改
如果常量引用,将无法修改
c:是需要查找的字符串,较短
*/
int main()
{
//test();
//test611();
test612();//使用引用交换两个数更方便,因为避免了在函数体内对输入的数解引用
return 0;
}
#include<iostream>
#include<algorithm>
using namespace std;
#include"Chapter6.h"
#include<string>
#include<vector>
//6.2.3书中例子
void test01() {
const int ci = 42; //ci不能被修改
int i = ci; //用一个常量给i赋值,i可以修改
cout << i << endl;
i = 5;
cout << i << endl;
int* const p = &i;//指针常量p初始化,必须为引用类型的i,p不能直接赋值,但i可以修改
cout <<*p<< endl;
i = 10;
cout << *p << endl;
*p = 0;//可以通过解引用指针常量对i进行修改
cout << i << endl;
}
void test02() {
int i = 42;
const int* cp = &i;//常量指针,不能通过对该指针解引用来修改i的值
cout << *cp << endl;
const int& r = i;//常量引用,不能通过修改r来修改i的值
cout << r << endl;
const int& r2 = 42;
cout << r2 << endl;
const int* p = cp; //常量指针cp中存储的是地址
cout << p << endl;
}
/*当一个函数的形参类型为引用时,
不能用字面值、或者需要转换的类型的实参对其进行初始化
如果函数不需要对形参进行修改时,尽量使用常量引用,实参可以为字面值等
*/
/*
练习6.16:
形参的类型最好设置为常数引用:const &
可以保证输入的对象不会被改变,
而且可以接受字面值或别的可以强制转化为string类型的类型值
*/
//练习6.17
bool largeABC(const string & val){
auto len = val.size();
for (int i = 0; i < len; i++) {
while (isupper(val[i])) {
return true;
}
}
return false;
}
void test03() {
string he = "hello";
if (largeABC(he)) {
cout << "字符串中有大写字母" << endl;
}
else
{
cout << "字符串中没有大写字母" << endl;
}
}
void decode(string& val) {
auto len = val.size();
for (int i = 0; i < len; i++) {
val[i]=tolower(val[i]);
}
}
void test04() {
string he = "HELLO";
cout << "修改前为" << he << endl;
decode(he);
cout << "修改后为" << he << endl;
}
/*
练习6.18
(a) bool compare(const matrix A,const matrix B){}
功能:比较两个输入,返回一个布尔值
(b) vector<int> change_val(const int &A,vector<int> & B)
把容器B中的值改变为A
*/
/*
练习6.19
(a)不合法,输入参数过多
(b)合法,char类型的形参无需常量引用,实参也可以为字面值
(c)合法 输入为int类型,将被强制转换为double
(d)合法 但是输入的double类型会丢失数据
*/
int count( char)
{
return 5;
}
double calc(double val) {
return val;
}
int sum(vector<int>::iterator, vector<int>::iterator, int val) {
return val;
}
void test05() {
double b=calc(66);
//char a = 'a';
//int b = count( 'a');
cout << b << endl;
vector<int> vec(10);
int cc=sum(vec.begin(), vec.end(), 3.8);
cout << cc << endl;
}
/*
练习6.20
当不需要对形参修改时,为常量引用
可能会发生修改的情况,或无法进行类型修改,或者输入字面值报错
*/
int main()
{
//test01();
//test02();
//test03();
//test04();
test05();
return 0;
}
#include<iostream>
#include<algorithm>
using namespace std;
#include"Chapter6.h"
#include<string>
#include<vector>
/*
6.2.4数中例子
void print(const int *);
void print(const int []);
void print(const int [10]);三种表达的意义相同,因为数组只能以指针形式传递
管理数组形参的三种方法:
1、使用标记指定数组长度,如在数组最后加空格
2、使用标准库规范,传入起始和结束的指针,begin(),end()
3、直接传入表示数组大小的形参.
数组引用形参:void print(int(&arr)[10])
指明了形参只能是10个元素的数组,其他大小的数组将报错
*/
//练习6.21---------------------------------------------
int comparenum(const int val1,const int* val2) {
int val =*val2;
if (val1 > val) {
return val1;
}
else {
return val;
}
}
void test01() {
int i = 60;
int q = 50;
int n = comparenum(i, &q);
cout << n << endl;
}
//练习6.22------------------------------------------
void swappoint( int* val1, int* val2) {
int temp = *val2;
*val2 = *val1;
*val1 = temp;
}
void test02() {
int a = 10;
int b = 20;
int* m = &a;
int* n = &b;
cout << "交换前a的值为" << a << endl;
cout << "交换前b的值为" << b<< endl;
swappoint(m, n);
cout << "交换后a的值为" << a << endl;
cout << "交换后b的值为" << b << endl;
}
//练习6.23----------------------------------------
void print(const int val1, int (&arr)[2]) {
cout << "int类型的值为" << val1 << endl;
for (auto elem : arr)
cout <<"数组的值有"<< elem << endl;
}
void test03() {
int a = 20;
int j[2] = { 1,2 };
print(a, j);
}
//练习6.24----------------------------------------
void print2(const int ia[3])
{
for (size_t i = 0; i != 3; ++i)
cout << ia[i] << endl;
}
void test04() {
int j[3] = { 1,2,3 };
print2(j);
}
int main(){
//test01();
//test02();
//test03();
test04();
return 0;
}
#include<iostream>
#include<algorithm>
#include"Chapter6.h"
#include<string>
#include<vector>
using namespace std;
/*
练习6.25
打开调试,点击调试属性,左侧选择调试选项,在命令参数中输入想输出的参数
*/
int main(int argc, char const** argv)
{
cout << argv[1] << endl;
cout << argv[2] << endl;
cout << string(argv[1]) + string(argv[2]) << endl;
system("pause");
return 0;
}
#include<iostream>
#include<algorithm>
#include"Chapter6.h"
#include<string>
#include<vector>
using namespace std;
//书中例子
void error_msg(initializer_list<string> il)
{
for (auto beg = il.begin(); beg != il.end(); ++beg)
cout << *beg << "";
cout << endl;
}
void test01()
{
string expected = "hello";
string actual = "world";
if (expected != actual)
error_msg({ "functionX",expected,actual });
else
error_msg({ "functionX", "okay" });
}
//练习6.27-------------------------------------
int numsum(initializer_list<int> ls)
{
int temp = 0;
for (auto beg = ls.begin(); beg != ls.end(); ++beg)
temp += *beg;
return temp;
}
void test02()
{
initializer_list<int> arr = {1,2,3,4,5,6,7,8,9};
int abc = numsum(arr);
cout << "数组的和为:"<<abc << endl;
}
/*
练习6.28
eleml类型为initializer_list<string>
*/
/*
练习6.29
应该,如果不调用引用类型,在调用时会copy一份该数据
*/
int main()
{
//test01();
test02();
}
#include<iostream>
#include<algorithm>
#include"Chapter6.h"
#include<string>
#include<vector>
using namespace std;
//书中例子
bool str_subrange(const string& str1, const string& str2)
{
if (str1.size() == str2.size())
return str1 == str2;
auto size = (str1.size() < str2.size())
? str1.size() : str2.size();
for (decltype(size) i = 0; i != size; i++)
{
if (str1[i] != str2[i])
return true ;
}
}
void test01()
{
string str1 = "hello";
string str2 = "world";
bool aa = str_subrange(str1, str2);
cout << aa << endl;
}
/*
在定义函数时,如果返回值的类型为const &;则不会真正的copy对象
返回引用类型的对象时,该对象不能是局部变量,因为函数结束时,局部变量会被销毁
*/
/*
当返回对象为引用时,但不是常量,则我们可以为函数返回的结果进行赋值
*/
//练习6.30 编译失败
/*
练习6.31
当返回的值为函数内局部变量时,返回的引用无效
当对一个常量的引用类型作为返回时,不可以对该返回值进行赋值操作
*/
/*
练习6.32
合法
作用是给一个容量为10的数组赋值0~9
*/
int & get(int * arry, int index)
{
return arry[index];
}
void test02()
{
int ia[10];
for (int i = 0; i != 10; i++)
get(ia, i) = i;
for (int j = 0; j != 10; j++)
{
cout << ia[j] << "";
cout << endl;
}
}
/*
练习6.33
*/
void printvector(vector<int> &arr,int val)
{
while (val< arr.size())
{
cout << arr[val] << endl;
return printvector(arr, val+1);
}
return ;
}
void test03()
{
vector<int> arr = { 1,2,3,4,5 };
printvector(arr,0);
}
/*
练习6.34
如果输入的是一个负数,函数将一直运行下去,知道栈满
*/
/*
如果是val--的话
当进行下次迭代的时候,val仍未上一次的值,并没有-1,将会使函数陷入无限循环
可能是因为val--的内在程序存在中间局部变量,
导致作为下次迭代的形参时,并不能返回-1后的值
*/
int main()
{
// test01();
//test02();
test03();
return 0;
}
#include<iostream>
#include<algorithm>
#include"Chapter6.h"
#include<string>
#include<vector>
#include<typeinfo>
using namespace std;
typedef string arrT[10];
using arrT = string[10];
//函数不能返回数组,若想返回数组,只能返回指向一个数组的指针
// Type (*function(parameter_list))[dim]
// int (*func(int i))[10]
//auto func(int i)->int(*)[10] 尾置返回类型
// odd 类型是一个五个元素的数组
//decltype(odd) *func(int i) decltype返回类型
//练习6.36
string(*func(int i))[10]
{
static string aa[10] = {"1", "1", "1" ,"1", "1", "1","1", "1","1", "1"};
return &aa;
}
void test01()
{
int i = 0;
//string bb[10];
auto bb = func(i);
cout <<"原始类型"<< endl;
for (int j=0; j<10;j++)
{
cout << (*bb)[j] << endl;
}
}
//练习6.37
arrT * funcc(int i)
{
static string aa[10] = { "1", "1", "1" ,"1", "1", "1","1", "1","1", "1" };
return &aa;
}
void test02()
{
int i = 0;
//string bb[10];
auto bb = funcc(i);
cout << "类型别名" << endl;
for (int j = 0; j < 10; j++)
{
cout << (*bb)[j] << endl;
}
}
auto funccc(int i)->string(*)[10]
{
static string aa[10] = { "1", "1", "1" ,"1", "1", "1","1", "1","1", "1" };
return &aa;
}
void test03()
{
int i = 0;
//string bb[10];
auto bb = funccc(i);
cout << "尾置返回类型"<< endl;
for (int j = 0; j < 10; j++)
{
cout << (*bb)[j] << endl;
}
}
string aa[10] = { "1", "1", "1" ,"1", "1", "1","1", "1","1", "1" };
decltype(aa)* funcccc(int i)
{
static string aa[10] = { "1", "1", "1" ,"1", "1", "1","1", "1","1", "1" };
return &aa;
}
void test04()
{
int i = 0;
//string bb[10];
auto bb = funcccc(i);
cout << "decltype关键字类型" << endl;
for (int j = 0; j < 10; j++)
{
cout << (*bb)[j] << endl;
}
}
//练习6.38
int odd[] = { 1,3,5,7,9 };
int even[] = { 0,2,4,6,8 };
decltype(odd)& arrptr(int i)
{
return(i % 2) ? odd : even;
}
void test05()
{
int i = 5;
auto ac = arrptr(i);
cout << "修改arrptr函数" << endl;
for (int j = 0; j < 5; j++)
{
cout << ac[j] << endl;
}
}
int main()
{
//test01();
//test02();
//test03();
//test04();
test05();
return 0;
}
#include<iostream>
#include<algorithm>
#include"Chapter6.h"
#include<string>
#include<vector>
#include<typeinfo>
using namespace std;
/*
函数重载:
非常量与常量、指针与指针常量不能区分函数重载
引用与常量引用、常量指针与指针类型可以区分
const_cast和重载
先用const_cast将非常量实参转换为const的引用,调用const输出类型的函数,
得到const类型的引用,由于这个引用实际上是绑定在一个初始的非常量上的,
所以将其转换为普通的非常量引用是安全的
*/
/*
练习6.39
(a):非常量与常量并不能区分出函数重载
(b):无法重载仅按返回值类型区分的函数
(c):合法,可以定义函数重载,形参类型不同
*/
int * get(int* val)
{
int * aa=val;
return aa;
}
double * get(double *val)
{
double* bb = val;
return bb;
}
void test01()
{
double q = 12.3;
double * qq = &q;
double * c = get(qq);
cout << *c << endl;
}
int main()
{
test01();
}
#include<iostream>
#include<algorithm>
#include"Chapter6.h"
#include<string>
#include<vector>
#include<typeinfo>
using namespace std;
/*
练习6.40
(a):正确 b被赋值默认实参后,c也被赋值了
(b):错误,第一个被赋值默认实参,后续所有都应该赋值
*/
/*
练习6.41
(a):非法,ht没有被赋值默认实参,调用时必须给实参
(b):合法
(c):合法,但是第二个输入的实参为char类型,将被强制转换为int类型
与初衷不符
*/
int ff(int a, int b = 0, int c = 0)
{
return 0;
};
void test01()
{
auto q= ff(10);
cout << q << endl;
}
//练习6.24
string make_plural(size_t ctr, const string &word="s", const string &ending=" ")
{
return (ctr > 1) ? word + ending : word;
}
void test02()
{
size_t ctr =2;
string aa = make_plural(ctr, "success", "ed");
string bb = make_plural(ctr, "failure", "ed");
cout << "success复数形式为"<<aa << endl;
cout << "failure复数形式为" << bb << endl;
}
int main()
{
//test01();
test02();
return 0;
}
#include<iostream>
#include<algorithm>
#include"Chapter6.h"
#include<string>
#include<vector>
#include<typeinfo>
using namespace std;
//内联函数可避免开销
inline const string& shorterstring(const string& s1, const string& s2)
{
return s1.size() <= s2.size() ? s1 : s2;
}
void test01()
{
string s1 = "abc";
string s2 = "ab";
cout << shorterstring(s1, s2) << endl;
}
/*
constexpr:
当给函数输入实参时,函数就是一个常量表达式,可以将函数看作一个字面值
当给constexpr类型的函数输入的实参为常量表达式或字面值时
该函数返回常量表达式,若输入为其他类型的实参,则返回非常量表达式
*/
/*
练习6.43
(a):放入头文件中,因为内联函数可以在程序中多次定义
(b):可以放在头文件中,也可以放在源文件中,普通声明在使用时要有函数定义
*/
/*
练习6.44如上
*/
/*
练习6.46
不能,因为输入不是字面值,若直接输出形参,需要两个返回
*/
constexpr string shorterstringqq( string s1, string s2)
{
if (s1.size() <= s2.size())
{
return s1;
}
else
{
return s2;
}
}
void test02()
{
string s1 = "abc";
string s2 = "ab";
constexpr const string foo = shorterstring1("abc", "ab");
cout << foo << endl;
}
int main()
{
//test01();
test02();
return 0;
}
#include<iostream>
#include<algorithm>
#include"Chapter6.h"
#include<string>
#include<vector>
#include<typeinfo>
using namespace std;
#define NDEBUG
#include<cassert>
//宏定义了NDEBUG,对应的表达式将不会被执行
void printvector(vector<int>& arr, int val)
{
#ifndef NDEBUG
cout << arr.size() << endl;
#endif // !NDEBUG
while (val < arr.size())
{
cout << arr[val] << endl;
return printvector(arr, val + 1);
}
return;
}
void test01()
{
vector<int> arr = { 1,2,3,4,5 };
printvector(arr, 0);
}
/*
练习6.48
合理,当命令行输入string类型字符时,进入while循环,对该字符进行操作
若什么都不输入,assert程序将使函数退出,否则将陷入死循环
*/
void test02()
{
string s;
while (cin >> s && s != "sought")
{
}
assert(cin);
}
int main()
{
//test01();
test02();
return 0;
}
#include<iostream>
#include<algorithm>
#include"Chapter6.h"
#include<string>
#include<vector>
#include<typeinfo>
using namespace std;
/*
练习6.52
(a):char类型提升为int类型,属于第3类 通过类型提升实现的匹配
(b):double类型转化为int类型,属于第4类,通过算术类型转换
*/
/*
练习6.53
(a):当传入的对象为const类型时,会调用第二个
当传入对象为非常量类型时,会精确匹配第一个
(b):同上
(c):
*/
//int calc(int &);
//int calc(const int &)
int calc(char*);
//int calc(const char*);
int calc(char* const);
#include<iostream>
#include<algorithm>
#include"Chapter6.h"
#include<string>
#include<vector>
#include<typeinfo>
using namespace std;
/*
候选函数:
在选择调用函数时,与想要调用的函数名字相同,且声明在调用点可见
可行函数:
形参数量与本次调用提供的实参数量相等,且每个实参的类型与对应的形参类型相同
或者能被强制转换
*/
/*
练习6.50
(a):可行函数有 f(int, int)f(double,double)
不合法,因为调用具有二义性
(b):可行函数有f(int)f(double,double=3.14)
合法,第一个是精准匹配
(c):可行函数有f(int, int)f(double,double)
合法,第一个是精准匹配
(d):可行函数有f(int, int)f(double,double)
合法,第二个是精准匹配
*/
/*
练习6.51
*/
void f()
{
cout << "f()" << endl;
}
void f(int val)
{
cout << "f(int val)" << endl;
}
void f(int, int)
{
cout << "f(int, int)" << endl;
}
void f(double, double = 3.14)
{
cout << "f(double, double = 3.14)" << endl;
}
void test01()
{
//f(2.56, 42);
f(42);
f(42, 0);
f(2.56, 3.14);
}
int main()
{
test01();
return 0;
}
#include<iostream>
#include<algorithm>
#include"Chapter6.h"
#include<string>
#include<vector>
#include<typeinfo>
using namespace std;
//函数指针,将函数名处改为(*p)即可
//函数指针不存在类型转换,但可以给函数指针赋一个nullptr或者值为0的整形常量表达式
//练习6.54
/* int func(int, int);
void test01()
{
int (*p)(int, int);
p = func;
vector<decltype(p)> a;
}
*/
//练习6.55
int func1(int val1, int val2)
{
return val1 + val2;
}
int func2(int val1, int val2)
{
return val1 - val2;
}
int func3(int val1, int val2)
{
return val1 * val2;
}
int func4(int val1, int val2)
{
return val1/val2;
}
void test02()
{
int (*p)(int, int);
p = func1;
vector<decltype(p)> a = {*func1,*func2, *func3, *func4};
vector<decltype(p)>::iterator it = a.begin();
for (int i = 0; i < 4; i++)
{
int b = (*it[i])(1, 2);
cout << b << endl;
}
}
int main()
{
test02();
return 0;
}