C++ primer之第六章(函数2)

 知识点:
        1.尽量使用常引用,而把函数不会改变的形参定义成引用是一种比较常见的错误, 我们不能把const对象, 字符值,或者需要类型转换的对象传递给普通的引用形参。
         2.数组的两个性质:1不允许拷贝数组;2使用数组时会将其转换成指针。
        3 .数组是以指针的形式传递给函数的,所以一开始函数并不知道数组的确切尺寸,调用者应该为此提供一些额外的信息。一般有三种方法: a 一般常见于C风格字符串,函数处理到最后一个空字符串时停止。但是有时对于int这样所有的取值都是合法值的数据就不太有效。 b 第二种传递指向数组首元素的尾元素的指针 如: void print( const int *beg, const int *end)。当不需要对数组元素执行写操作的时候,数组形参应该是指向const的指针,只有当函数确实要改变元素值的时候,才把形参定义成指向非常量的指针。 c 第三种管理数组实参的方法是在传送数组首地址后,在另外传一个形参专门表示数组大小的形参。
        4.请记住,在C ++中没有数组类型的值,所以数组类型不能是函数参数或返回类型。数组的大小对函数的调用没关系。
        5.但是C++语言允许将变量定义成数组的引用,所以形参也可以是数组的引用。此时引用形参绑定到对应的实参上,也就是绑定到数组 上。
         6.C++11新标准引入了两个名为begin和end的函数,这两个函数与容器中的两个同名成员功能类似,但不是成员函数,是标准库函数。(主要用于返回数组的首尾指针)。
        7.当我们需要给main函数传参时,需要注意到int main(int argc,char*  argv []) 第二个形参是C风格数组,存放字符命令的地址,数量等于字符串的数量(argc)。当实参传给main函数之后,argv的第一个元素指向程序的名字或者一个空字符串,接下来的元素依次传递命令行提供的实参, 记住最后一个指针指针之后的元素为0(eg p197)。
        8.当使用argv中的实参时,一定要记得可选的实参从argv[1]开始; argv[0]保存程序的名字, 而非用户输入。
         9.为了能出列不同数量实参的函数,C++11标准提供了两种主要的方法,1实参类型相同可以传递initializer_list的标注库类型(模板类型)个人觉得和传参数组引用很相似;2类型不同可以编写可变参数模板。还有一种只用于与C函数交互的接口程序省略符形参。
        10.return 语句;主要是 终止当前函数的执行,将控制权返还到调用该函数的地方。void 函数可以使用两种return 1是当提前终止函数,加"return;"语句即可; 另一种是return expression; expression必须是另一个返回void的函数。
        11.函数的返回类型决定函数的调用是否是左值。

疑问:
        1. 今天才编写6.17时,没弄懂记录在这里
环境:VS2010 //刚开始 使用迭代器访问一直出错,调试是错误的指针,换成用下标访问依然有错。
string word( "hello Everybody" );
fun6_17(word);

void fun6_17(const string &word1) //因为传进来的是常量,所以这里必须加const
{
      /*
     for(auto it=word1.begin(); it!=word1.end(); ++it)
     {
           if(isupper(*it))
           {
                cout<<"含有大写字母!"<<word1[i]<<endl;
                break;
           }
     }
     */
      int len = word1.size();
      for ( int i=0; i<len; ++i)
     {
            if (isupper(word1[i]))
           {
                cout<< "含有大写字母!" <<word1[i]<<endl;
                 break ;
           }
     }
}
  好奇怪;去吃中午饭前,有调试了下这段程序;莫名奇妙的好了;连原因不知道在哪里
/*6.25及6.26
这个是参考别人的,感觉在IED下不是很好理解,在Linux有命令参数下编程,会好理解些
int main(int argc, char *argv[])
{
     cout<<"输入参数:";
     string str;
     cin>>str;
     for(int i = 0; i<argc; ++i)
     {
           str += argv[i];
           str += " ";
     }
     cout<<str<<endl;
     return 0;
}
*/

    习题:
        6.16 答:当实参是const对象,字符值等时,会发生错误。改为 bool is_empty(const string &s)
         618 答:(a)   bool compare ( const matrix &m1, const matrix &m2);
            (b) vector< int >::iterator change_val ( int , vector< int >::iterator);
        6.19 答:(a) 不合法; (b) 合法  (c) 合法 (d) 合法 但有警告;
        6.20 答:当传入是字符面值常量, 或者是用const修饰的字符,或者调用者就需要关心传入的 Student 对象有可能会被修改形参一般是常量引用。看编译器执行标准吧, 如果必须用const而形参没加肯定会报错,如果不太需要const,编译不会报错。
        6.24 答:这段程序是想接受一个含有10个const int 类型的数, 但是C++编译器会将带有[]类型的统一解释成指针,所以数组大小是不相关的,如const int ia[5]与const int ia[255] 没有 区别。 (关于本节知识点4,5)
void print(const int ia[10])
{
for (size_t i = 0; i != 10; ++i)
cout << ia[i] << endl;
}
应该这样做:
void print10(const int (&ia)[10]) { /*...*/ }
        6.28 答:原型:void error_msg(ErrCode e,   initializer_list<string> il) 因为il是个<string> 类型的数组,所以范围for语句elem 是string& 类型。范围for循环中auto推导出来的是值,而非迭代器。
        6.29 答:看是否追求效率。

程序题:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
//判断string中是否含有大写字母
void fun6_17( const string &word1) //因为传进来的是常量,所以这里必须加const
{
      //int len = word1.size();
      for ( auto it=word1.begin(); it!=word1.end(); ++it)
     {
            if (isupper(*it))
           {
                cout<< "含有大写字母!" <<*it<<endl;
                 break ;
           }
     }
     
}
//将单词改为小写
void fun6_17(string & s)
{
      for ( auto it=s.begin(); it!=s.end(); ++it)
     {
            if (isupper(*it))
                *it = *it+32;
     }
     cout<<s;
}
//返回较大的数
int fun6_21( int in, int *jn)
{
      return (in>*jn) ? in:*jn;
}
void fun6_22( int * &pp, int * &qq)  //采用引用方便,指针麻烦易出错
{
      int *tmp;
     tmp = pp;
     pp = qq;
     qq = tmp;
}
//采用第一种方式访问数组内容(访问到空字符串,自动停止)
void fun6_23print( char (&ch1)[6]) //注意这里的括号
{
     cout<< "采用第一种方式:" <<ch1<<endl;
}
//采用第二种方式,传送数组的首尾指针
void fun6_23print( const char *p, const char *q) //因为不牵扯修改数组内容,建议const修饰
{
     cout<< "采用第二种方式" <<endl;
      while (p != q)
     {
           cout<<*p++;
     }
}
//采用第三种方式,传递数组首地址以及数组元素个数
void fun6_23print( char *p, int num)
{
     cout<< "采用第三种方式" <<endl;
      //用for是为了加深数组名与地址的转换, 编译器对char *p的解释与char p[] 相同。
      for ( int i = 0; i<num; ++i)
     {
           cout<<p[i];
           ++p;
     }
      /*
     while(num)
     {
           cout<<*p++;
           --num;
     }
     cout<<endl;
     */
}
//采用initializer_list计算传过来的所有参数的值,vs2010不支持新特性,win7
/*
int fun6_27_sum(const std::initializer_list<int>& il)
{
    int sum = 0;
    for (auto i : il) sum += i;
    return sum;
}
*/
//关于编译器对rentrun 报错的反应结果:
//“fun6_30str_subrange”: 函数不接受 0 个参数,fun6_30str_subrange”: 函数必须返回值
bool fun6_30str_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 ( int i = 0; i<size; ++i)
     {
            if (str1[i] != str2[i])
                 return ;
     }    
}
int main()
{
/*
     string word("hello Everybody");
     //fun6_17(word);
     //cout<<"请输入单词:"<<endl;
     //string word;
     //cin>>word;
     //fun6_17(word);
     int i = 10,j = 20;
     cout<<fun6_21(i,&j);
     int *p = &i;
     int *q = &j;
     cout<<*p<<'\t'<<*q<<endl;
     fun6_22(p,q);
     cout<<*p<<'\t'<<*q;
     int i = 0,j[2] = {0,1};
     char ch[6] = "hallo";
     //fun6_23print(ch);
     //fun6_23print(begin(ch),end(ch));//c++ 标准库函数,返回数组首尾指针
     //fun6_23print(ch, 6);
*/    
      //fun6_27_sum({1,2,3,4,5,6,7});
     fun6_30str_subrange( "abc" , "hallo" );
      return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值