第2题字母统计【2016狮山镇小甲六年级】

题目描述

晨晨对小写字母情有独钟,特别喜欢小写字母,而且她很喜欢统计一个单词里面有多少个小写字母, 所以现在她想请你帮忙编写一条程序,专门统计一个单词里面小写字母的个数。

输入

一个单词(长度不大于 20) 。

输出

一个整数,代表单词里面小写字母的个数。 

样例输入 Copy

Day

样例输出 Copy

2

程序

#include<iostream>

#include<fstream>

#include<algorithm>

using namespace std;

string er;

int h;

int main()

{

    cin>>er;

    for(int i=0;i<er.size();i++)

    {  

        if(er[i]>='a'&&er[i]<='z')h++;

    }      

    cout<<h;

    return 0;

}

小知识:return

返回类型和return语句
 return 语句的作用是终止一个函数的执行,结束当前代码块中return后的语句,即return后的语句不再执行,从当前位置退出函数。return语句有两种形式:

return;
return expresion;
1
2
无返回值函数
 没有返回值的return语句只能用在返回类型是void的函数中。返回void的函数不要求非得有return语句,因为这类函数的最后一句后面会隐式执行return。

// example
void swap(int &v1, int &v2){
    // 如果两个值是相等的,则不需要交换,直接退出
    if(v1 == v2){
        return ;
    }
    // 如果执行到了这里,说明还需要继续完成某些功能
    int tmp = v2;
    v2 = v1;
    v1 = tmp;
    // 这里无须显示的return语句
}
1
2
3
4
5
6
7
8
9
10
11
12
​ 强行另void函数返回其他类型的表达式将会产生编译错误!!

有返回值函数
 return语句的第二种形式提供了函数的结果。只要函数的返回类型不是void,则该函数内的每条return语句必须返回一个值。return语句返回值类型必须与函数的返回类型相同,或者能够隐式地转换成函数的返回类型。

 尽管编译器无法确保结果的正确性,但是可以保证每个return语句的结果类型正确。例如:

// 因为含有不正确的返回值 ,所以这段代码无法编译通过
bool str_subrange(const string &str1, const string &str2){
    // 大小相同,此时用普通的相等性判断结果作为返回值
    if(str1.size() == str2.size()){
        return str1 == str;        // 正确:==运算符返回的是布尔值
    }
    auto size = (str1.size() < str2.size()) ? str1.size() < str2.size();
    
    // 检查两个string对象的对应字符是否相等,以较短的字符串长度为限
    for(decltype(size) i = 0;i != size; ++i){
        if(str1[i] != str2[i])
        return ;    // 错误:没有返回值,编译器将会报告这一错误
    }
    // 错误:控制流可能尚未返回任何值就结束了函数的执行
    // 编译器可能检查不出来这一错误!
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 注意!含有return语句的循环后面应该也要有一条return语句,如果没有那么程序就是错误的!很多编译器都无法发现此类错误!

值是如何被返回的
 返回一个值的方式和初始化一个变量或形参的方式完全一样:返回值是初始化调用点的一个临时量,该临时量就是函数调用的结果

string make_plural(size_t ctr, const string &word, const string &ending){
    return (ctr > 1) ? word + ending : word;
}
1
2
3
 该函数的返回类型是string,意味着和返回值将被拷贝到调用点。因此,该函数将返回word的副本或者一个未命名的临时string对象,该对象的内容是word和ending的和。

const string &shorterString(const string &s1, const string &s2){
    return s1.size() <= s2.size() ? s1: s2;
}
1
2
3
​ 其中形参和返回类型都是const string的引用,不管是调用函数还是返回结果都不会真正拷贝string对象!

不要返回局部对象的引用或指针
 函数完成后,它所占用的存储空间也会随之被释放掉。因此,函数终止意味着局部变量的引用将指向不再有效的内存区域:

// 严重错误:这个函数试图返回局部对象的引用
const string &manip(){
    string ret;
    if(!ret.empty())
        return ret;            // 错误,返回局部对象的引用!
    else
        return "empty";        // 错误,"empty”是一个局部变量!
}
1
2
3
4
5
6
7
8
 在第二条return语句中,字符串字面值转换成一个局部临时string对象,对于manip来说,该对象和ret一样都是局部的。

引用返回左值
 函数的返回类型决定函数调用是否是左值。调用一个返回引用的函数得到左值,其他返回类型得到右值。可以像使用其他左值那样来使用返回引用的函数调用,特别是,能为返回类型是非常量引用的函数的结果赋值:

char &get_val(string &str, string::size_type ix){
    return str(ix);    // get_val假定索引值是有效的
}

int main(){
    string s("a value");    // 输出a value
    cout << s << endl;        // 将s[0]的值改为A
    get_value(s, 0) = 'A';    // 输出A value
    cout << s << endl;    
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
 把函数调用放在赋值语句的左侧可能看起来会有点奇怪,但其实没什么特别的!返回值是引用,因此调用是个左值,和其他左值一样他也能出现在复制运算符的左侧!

列表初始化返回值
 C++11新标准规定,函数可以返回花括号包围的值的列表。类似于其他返回结果,此处的列表也用来对表示函数返回的临时量进行初始化。如果列表为空,临时量执行值初始化;否则,返回的值有函数的返回类型决定。

vector<string> process(){
    // ...
    // expected  actual是string对象
    if(expected.empty()){
        return {};
    }
    else if(expected == actual)
        return {"functionX", "okay"};
    else 
        return {"functionX", expected, actual};
}
1
2
3
4
5
6
7
8
9
10
11
 如果函数返回的是内置类型,则花括号包围的列表最多包含一个值!而且该值所占空间不应该大于目标类型的空间!如果函数返回类型是类类型,由类本身定义初始值如何使用。

主函数main的返回值
 如果函数的返回类型不是void,那么必须返回一个值。但是这条规定有个例外:我们允许main函数没有return语句直接结束。如果控制到达了main函数的结尾处而且没有return语句,编译器将隐式地插入一条返回0的return语句。

 main函数的返回值可以看作是状态指示器。返回0表示执行成功,返回其他值表示执行失败,其中非0值的具体含义根据机器来定!

返回数组指针
 因为数组不能拷贝,所以函数不能返回数组。不过,函数可以返回数组的指针或引用!要想定义一个返回数组的指针或者引用的函数比较繁琐,但可以使用类型别名来简化这一任务!

typedef int arrT[10];    // arrT是一个类型别名,表示的类型含有10个整数的数组
using arrT = int [10];    // arrT的等价声明
arrT* func(int i);        // func返回一个指向含有10个整数的数组的指针
1
2
3
 arrT是含有10个整数的数组别名。因为无法返回数组,所以将返回类型定义成数组的指针。因此,func函数接收一个int实参,返回一个指向包含10个整数数组的指针。

声明一个返回数组指针的函数
​ 首先要区分以下的不同:

int arr[10];            //arr是一个含有10个整数的数组
int *p1[10];            //p1是一个含有10个指针的数组    数组中的值是指针
int (*p2)[10] = &arr;    //p2是一个指针,它指向含有10个整数的数组
1
2
3
返回数组指针的函数形式如下所示:

Type (*function(parameter_list))[dimension];
// example
int (*func(int i))[10];
1
2
3
可以按照以下顺序来逐层理解该声明的定义:

func(int i) 调用func函数时需要int类型实参
(*func(int i)) 对函数调用的结果进行解引用操作
(*func(int i))[10] 解引用func的调用将得到一个大小是10的数组
int (*func(int i))[10]; 表示数组中的元素时int类型
#include<iostream>
using namespace std;

int (*func(int k))[10] {
    int (*p)[10];
    for(int i=0;i<k;i++){
        (*p)[i] = i;
    }
    return p;
}
int main() {
    int (*a)[10];
    a = func(10);
    for(int i=0; i<10; i++) {
        cout << (*a)[i] << " ";
    }
    return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
使用尾置返回类型
 C++11新标准有一种能简化上述声明的方法,就是使用尾置返回类型。然和函数的定义都能使用位置返回,但是这种形式对于返回类型比较复杂的函数最有效,比如返回类型是数组或者数组的引用。为了表示函数真正的返回类型跟在形参列表之后,应该要在本应该出现返回类型的地方放置一个auto。

// func接受一个int类型的实参,返回一个指针,该指针指向含有10个整数的数据
auto func(int i) -> int(*)[10];
1
2
 把函数的返回类型放在形参列表之后,可以清楚地看到func函数返回是一个指针,并且该指针指向了含有10个整数的数组。

使用decltype
​  假设一直到函数返回的指针指向哪个数组,就可以使用decltype关键字声明返回类型。例如,下面的函数返回一个指针,该指针根据参数i的不同指向两个已知数组的某一个:

int odd[] = {1,3,5,7,9};
int even[] = {2,4,6,8,10};
// 返回一个指针,该指针指向含有5个整数的数组
decltype(odd) *arrPtr(itn i){
    return (i%2) ? &odd : &even;
 }
1
2
3
4
5
6
arrptr使用关键字decltype表示它的返回类型是个指针,并且该指针所指向的对象与odd类型一致。

 需要注意的是,decltype并不负责把数组类型转换成对应的指针,所以decltype的结果是个数组,想要表示arrptr返回指针,还必须在函数声明时加一个*符号。
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值