给定一个 k 位整数 N=dk−110k−1+⋯+d1101+d0 (0≤di≤9, i=0,⋯,k−1, dk−1>0),请编写程序统计每种不同的个位数字出现的次数。例如:给定 N=100311,则有 2 个 0,3 个 1,和 1 个 3。
输入格式:
每个输入包含 1 个测试用例,即一个不超过 1000 位的正整数 N。
输出格式:
对 N 中每一种不同的个位数字,以 D:M
的格式在一行中输出该位数字 D
及其在 N 中出现的次数 M
。要求按 D
的升序输出。
输入样例:
100311
输出样例:
0:2
1:3
3:1
实现代码:
#include<iostream>
#include<map>
using namespace std;
int main()
{
string s;
cin>>s;
map<char,int>mp;
for(auto x:s) mp[x]++;
for(auto x:mp) printf("%c:%d\n",x.first,x.second);
return 0;
}
知识点:
auto:
程时常常需要把表达式的值赋给变量,这就要求声明变量时清楚的知道表达式的类型。然而有些情况是声明的变量的类型我们并不知道,比如在模板编程时。为了解决这个问题,C++11引入了auto类型说明符,用它来让编译器替我们去分析表达式所属的类型。
auto的推导规则
- 规则1:声明为auto(不是auto&)的变量,
忽视掉初始化表达式的顶层const
。即对有const的普通类型(int 、double等)忽视const,对常量指针(顶层const)变为普通指针,对指向常量(底层const)的常量指针(顶层cosnt)变为指向常量的指针(底层const)。 - 规则2:声明为auto&的变量,
保持初始化表达式的顶层const或volatile 属性
。 - 规则3:若希望auto推导的是顶层const,加上const,即const auto。
auto例子
int i = 0, &ri = i;
auto a = i; //a为int型变量
auto a1 = ri; //a1为int型变量
auto p = &i;// &i 是一个普通int指针,p是一个整型指针int *
auto p1 = &ri; //同上
const int ci = 2, &rci = ci , ci2 = 9;
auto b = ci;//b为int型变量,因为规则1,b`并不是一个const int型的常量`
auto b1 = rci;//同上
b = 4;b1 = 5;//b和b1的值可以改变
auto cp = &ci;//cp是一个指向常量的指针const int* ,因为&ci对常量对象取地址是底层const,无顶层const属性
cp = &ci2;//cp的指向可以改变
下面看忽视顶层const指针的例子:
int z = 9,z1 = 10;
int* const pz1 = &z;//pz1为int* const(顶层const)
const int* pz2 = &z;//pz2为const int* (底层const)
const int* const pz3= &z;//pz3为const int* const(同时包含底层和顶层const)
auto apz1 = pz1;//apz1为int*
auto apz2 = pz2;//apz2为const int*
auto apz3 = pz3;//apz3为cosnt int*
对于pz1和pz3,它们都有顶层const属性,所以apz1和apz3都会忽略顶层const属性。
这里注意:对常量对象取地址总是看作为一种底层的const,即不是对指针(也就是指向)的常量,而是对指针指向内存中的值是常量
。所以上面的&ci是const int*型。
C++中for auto的用法:
1.for(auto iter:vec)不改变迭代对象的值,for(auto &iter:vec)可以改变迭代对象的值。
两者都可以获取到迭代容器中的值,但是使用auto iter时不会对容器对象造成改变,
而使用auto &iter,对于iter的任何修改将直接修改容器内对应的值。
2.简单的例子
#include <iostream>
#include <vector>
using namespace std;
void printVec(vector<int>& vec) {
for (int i = 0; i < vec.size(); i++)
cout << vec[i] << endl;
}
int main() {
vector<int>vec = {4,3,2,1,0 };
cout<<"***************第一种*************"<<endl;
//这个时候每个取出来的iter只是原来vec元素的副本,不会改变vec中任何元素
for (auto iter : vec) {
iter = iter + 100;
}
printVec(vec);
cout<<"***************第二种*************"<<endl;
//这个时候取出来的是 &iter,代表原来vec中元素的引用,如果对iter进行任何改变都会作用在vec上
for (auto& iter : vec) {
iter = iter + 100;
}
printVec(vec);
}
输出的结果如下:
***************第一种*************
4
3
2
1
0
***************第二种*************
104
103
102
101
100
map:
一、map简介
map是STL(中文标准模板库)的一个关联容器。
- 可以将任何基本类型映射到任何基本类型。如int array[100]事实上就是定义了一个int型到int型的映射。
- map提供一对一的数据处理,key-value键值对,其类型可以自己定义,第一个称为关键字,第二个为关键字的值
- map内部是自动排序的
二、map的用法
- 必须引入包
#include<map>
2.map的定义
map<type1name,type2name> maps;//第一个是键的类型,第二个是值的类型
map<string,int> maps;
3.map容器内元素的访问
- 通过下标进行访问
如:maps['c']=5;
- 通过迭代器进行访问
map可以使用it->first来访问键,使用it->second访问值
简单的例子:
#include<map>
#include<iostream>
using namespace std;
int main()
{
map<char, int>maps;
maps['d'] = 10;
maps['e'] = 20;
maps['a'] = 30;
maps['b'] = 40;
maps['c'] = 50;
maps['r'] = 60;
for (map<char, int>::iterator it = maps.begin(); it != maps.end(); it++)
{
cout << it->first << " " << it->second << endl;
}
return 0;
}
输出的结果如下:
a 30
b 40
c 50
d 10
e 20
r 60