输入
输入不确定个数的一组数
以空格为间隔输入纯数字
#include<iostream>
#include<vector>
#include<sstream>
using namespace std;
int main()
{
string s;
vector<int> v;
getline(cin,s);
istringstream is(s);
int inter;
while(is>>inter){
v.push_back(inter);
}
for(int i=0;i<v.size();i++)
cout<<v[i]<<" ";
cout<<endl;
return 0;
}
以‘,’为间隔输入数字
#include<iostream>
#include<vector>
#include<sstream>
using namespace std;
int main()
{
string s;
vector<int> v;
getline(cin, s);
istringstream is(s);
int inter;
char ch;
while (is >> inter)
{
v.push_back(inter);
is >> ch;
}
for(int i=0;i<v.size();i++)
cout<<v[i]<<" ";
cout<<endl;
return 0;
}
输入n行 长度不定的数字
#include<iostream>
#include<vector>
#include<sstream>
using namespace std;
int main()
{
int n;
string s;
vector<int> v;
cin>>n;
cin.ignore();//删掉滞留在输入流中的'\n'
for(int i=0;i<n;i++){
getline(cin,s);
istringstream is(s);
int inter;
while(is>>inter){
v.push_back(inter);
}
}
for(int i=0;i<v.size();i++)
cout<<v[i]<<" ";
cout<<endl;
return 0;
}
memset
memset为初始化函数,但是它是以字节为单位进行初始化的。
操作为memset(要初始化的内存块,值,要初始化的字节大小)
因为是以字节为单位初始化,因此不能随意赋值,不是填入什么数就初始化为什么数。
对于char类型,由于char类型占1个字节,memset函数刚好以字节为单位,故可直接赋值
int main(){
char a[4];
memset(a,'1',4);
for(int i=0; i<4; i++){
cout<<a[i]<<" ";
}
return 0;
}
而对于int类型,int类型占4个字节,除了0和-1能直接赋值,其他的都不行
int main(){
int a[4];
memset(a,1,sizeof(a));
for(int i=0; i<4; i++){
cout<<a[i]<<" ";
}
return 0;
}
而如果要让4个int值变为1,可以这样操作:
memset(a,1,16); //int所占内存为4字节的情况
memset(a,1,sizeof(a));
这里的sizeof()则可以对全部内容进行初始化,故最好使用sizeof(),或者用for和while循环进行初始化。
memcpy
以字节为单位进行复制操作,在复制数组上挺好用的。最好用sizeof。
int a[5]={0,1,2,3,4},b[5];
memcpy(b,a,sizeof(a));
这时b数组的值就和a数组一样啦
swap
首先要提一下引用传递和指针传递的不同
指针传递
void myswap(int *a,int *b){//传入的是a和b的地址值
int tmp=*a; //除了声明或初始化指针时,*代表指针的意思,其他时候*在指针变量名左边代表指针指向的内容。这里tmp=a地址指向的内容,即a的值
*a=*b; //指针a指向的地址空间内容变成指针b指向的地址空间内容,即a=b
*b=tmp; //同理b指向的地方=tmp/a,完成交换
}
void main(){
int a=1,b=2;
myswap(&a,&b); //传入地址值
printf("%d %d",a,b); // 输出为2 1
return 0;
}
引用传递
void myswap(int &a,int &b){ //传入的为引用,调用该函数的时候,会生成引用a=a,引用b=b,所以函数里操作引用的时候,就是修改了原值。
int tmp=a;
a=b;
b=tmp;
}
void main(){
int a=1,b=2;
myswap(a,b);
printf("%d %d",a,b); // 2 1
return 0;
}
在这里指针传递和引用传递都可以交换两个变量的值。
但是其实有所区别,指针变量可以理解为指向变量的地址空间,而地址空间中储存着地址值,利用指针变量将变量改变实际上是指针指向的空间的地址值改变,即地址值指向要变成的那个值的地址。
而引用则是无法改变地址的,引用指向一个地址空间,该地址空间无法改变,只可以改变地址空间中的值。
C++中自带的swap函数属于引用传递
void main(){
int a=1,b=2;
swap(a,b);
printf("%d %d",a,b); // 2 1
return 0;
}
sort
Sort函数有三个参数:
(1)第一个是要排序的数组的起始地址。
(2)第二个是结束的地址的下一个地址
(3)第三个参数是排序的方法,可以是从大到小也可是从小到大,还可以不写第三个参数,此时默认的排序方法是从小到大排序。
例一:sort函数没有第三个参数,实现的是从小到大
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int a[10]={9,6,3,8,5,2,7,4,1,0};
for(int i=0;i<10;i++)
cout<<a[i]<<endl;
sort(a,a+10);
for(int i=0;i<10;i++)
cout<<a[i]<<endl;
return 0;
}
例二:用bool进行判断实现从大到小排序
#include<iostream>
#include<algorithm>
using namespace std;
bool compare(int a,int b)
{
return a>b;
}
int main()
{
int a[10]={9,6,3,8,5,2,7,4,1,0};
for(int i=0;i<10;i++)
cout<<a[i]<<endl;
sort(a,a+10,compare);//在这里就不需要对compare函数传入参数了,//这是规则
for(int i=0;i<10;i++)
cout<<a[i]<<endl;
return 0;
}
例三:可以直接用C++标准库中的函数
less<数据类型>()//从小到大排序
greater<数据类型>()//从大到小排序
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int a[10]={9,6,3,8,5,2,7,4,1,0};
for(int i=0;i<10;i++)
cout<<a[i]<<endl;
sort(a,a+10,less<int>());
for(int i=0;i<10;i++)
cout<<a[i]<<endl;
return 0;
}
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int a[10]={9,6,3,8,5,2,7,4,1,0};
for(int i=0;i<10;i++)
cout<<a[i]<<endl;
sort(a,a+10,greater<int>());
for(int i=0;i<10;i++)
cout<<a[i]<<endl;
return 0;
}
例四:利用sort函数还可以实现对字符的排序
即对字符ASCII码的排序
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
char a[11]="asdfghjklk";
for(int i=0;i<10;i++)
cout<<a[i]<<endl;
sort(a,a+10,greater<char>());
for(int i=0;i<10;i++)
cout<<a[i]<<endl;
return 0;
}
cin和getline
C++中使用cin和cout比较方便,但是输入输出效率比scanf和printf低,故有些算法题如果对时间复杂度要求高,可以将cin和cout改成scanf和printf。
使用cin可以输入数字或字符,字符串,但是接受字符串时遇到“空格”“TAB”“回车”就会结束,因此需要cin.getline()或者getline
cin.getline()为istream流
#include <iostream>
using namespace std;
main ()
{
char m[20];
cin.getline(m,5);
cout<<m<<endl;
}
输入:jkljkljkl
输出:jklj
接收5个字符到m中,其中最后一个为’\0’,所以只看到4个字符输出;
1、cin.getline()实际上有三个参数,cin.getline(接收字符串的变量,接收字符个数,结束字符)
2、当第三个参数省略时,系统默认为’\0’
3、如果将例子中cin.getline()改为cin.getline(m,5,‘a’);当输入jlkjkljkl时输出jklj,输入jkaljkljkl时,输出jk
getline()为string流
用法:接收一个字符串,可以接收空格并输出,需包含“#include”
#include<iostream>
#include<string>
using namespace std;
main ()
{
string str;
getline(cin,str);
cout<<str<<endl;
}
输入:jkljkljkl
输出:jkljkljkl
输入:jkl jfksldfj jklsjfl
输出:jkl jfksldfj jklsjfl
注意:getline()不读取换行符,默认遇到换行符或EOF结束,(也可以在括号中第三个位置设置结束标志)所以如果在使用getline()之前有用scanf输入或者用scanf(),则需要用getchar()吃掉换行符才能继续输入。
注意:如果前面有cin输入,后面有getline,可以用**cin.ignore()**清除掉缓冲区的符号,否则后面的getline会读取缓冲区的回车键。
for循环一些看法
最普通的for循环如下
for ( int i = 0; i < 10; i++){
//cout<<i<<endl;
}
for循环的执行逻辑如下
- 初始化变量,int i = 0
- 判断i < 10
- 执行循环体内的代码
- 变量自增,i++或者++i
那么,不难看出,不管使用++i还是i++,对最终的计算结果其实是没有区别的。
bool变量
bool变量有两个值,true和false,而C++把所有非0的数解释为true,0解释为false,所以直接赋值⼀个数字给 bool 变量也是可以的~它会⾃动根据 int 值是不是零来决定给 bool 变量赋值 true 还是 false
bool flag = true;
bool flag2 = -2; // flag2为true
bool flag3 = 0; // flag3为false
const
const是C++特有的用const这个限定符定义常量,这样做有个好处就是可以定义常量的类型,⽐如 int 类型的常量 a 这样定义:
const int a = 99999999;
C++结构体和C的一些区别
定义好结构体 stu 之后,使⽤这个结构体类型的时候,C语⾔需要写关键字 struct ,⽽C++⾥⾯可以省略不写:
struct stu {
int grade;
float score;
};
struct stu arr1[10]; // C语⾔⾥⾯需要写成struct stu
stu arr2[10];// C++⾥⾯不⽤写struct,直接写stu就好了~
C++的引用&和传值的区别
&在C语言中是取址运算符,而在C++中是引用,即引用变量。
void func(int &a) { // 传⼊的是n的引⽤,相当于直接对n进⾏了操作,只不过在func函数中换了个名
字叫a
a = 99;
}
int main() {
int n = 0;
func(n); // n由0变成了99
}
void func(int a) {// 传⼊的是0这个值,并不会改变main函数中n的值
a = 99;
}
int main() {
int n = 0;
func(n);// 并不会改变n的值,n还是0
}
strlen
strlen()函数用于求字符串的长度。且只能求到“\0”字符串前面的字符串(不包括“\0”),(C语言规定,字符串必须以’\0’字符作为最后一个字符,表示字符串的结束字符)。
定义字符串数组后,一定要初始化。
为什么呢,看一下例子:
#include<bits/stdc++.h>
using namespace std;
int main()
{
char test[50];
for(int i=0;i<26;i++)
{
test[i]='A'+i;
cout<<test[i]<<" ";
}
cout<<strlen(test)<<endl;
}
这里没有初始化char数组,输出的strlen值为27,并不是我们想要的26。
#include<bits/stdc++.h>
using namespace std;
int main()
{
char test[50]={0};
for(int i=0;i<26;i++)
{
test[i]='A'+i;
cout<<test[i]<<" ";
}
cout<<strlen(test)<<endl;
return 0;
}
初始化了之后,就能得到正确的结果啦
最后一个点就是,strlen函数得到的是一个无符号的整型,即不小于0的整数。
min和max
用法:min(a,b), max(a,b)
注意:直接调用min和max函数只能比较两个数!!!若比较两个以上会报错,可以用max(max(a,b),c)这样的方法或者自己定义函数(自己定义函数要注意,C++是从上往下执行的,所以main函数如果要调用自己定义的max或min函数应该将max或min函数的代码块写在main的上面,下面才可以调用)
lower_bound( )和upper_bound( )
lower_bound( )和upper_bound( )都是运用二分查找的方法进行查找,作用的对象都是已经排好序的数组。
在从小到大的排序数组中:
- lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。
- upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。
在从大到小的排序数组中:
- lower_bound( begin,end,num,greater() ):从数组的begin位置到end-1位置二分查找第一个小于或等于num的数字,找到返回该数字的地址,不存在则返回end。
- upper_bound( begin,end,num,greater() ):从数组的begin位置到end-1位置二分查找第一个小于num的数字,找到返回该数字的地址,不存在则返回end。
通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
accumulate
accumulate用来做累加或者累乘操作。
有三个参数:
- _First:指定范围内第一个迭代的值或者结合操作选项使用。
- InputIterator _Last:指定范围内最后一个迭代值或者结合操作项使用。
- _Val:要计算的初始值。
- _Binary_op:运用于指定范围内所有元素和前面计算得到结果的参数。
需要注意的是:第三个参数是什么类型,即初始值是什么类型,返回的结果就是什么类型。
这样直接看有点抽象,直接用例子来理解。
求和
#include<bits/stdc++.h>
using namespace std;
int main()
{
vector<int>v;
vector<int>::iterator iter;
int i;
for(i=0;i<21;i++)
{
v.push_back(i);
}
for(iter=v.begin();iter!=v.end();iter++)
{
cout<<*iter<<" ";
}
int total;
total=accumulate(v.begin(),v.end(),0);
cout<<endl<<total<<endl;
}
求前n项和
#include<bits/stdc++.h>
using namespace std;
int main()
{
vector<int>v1,v2(20);
vector<int>::iterator iter1,iter2;
int i;
for(i=0;i<21;i++)
{
v1.push_back(i);
}
int j=0,partotal;
for(iter1=v1.begin()+1;iter1!=v1.end();iter1++)
{
partotal=accumulate(v1.begin(),iter1,0);
v2[j++]=partotal;
}
for(iter2=v2.begin();iter2!=v2.end();iter2++)
{
cout<<*iter2<<" ";
}
//for(int k=0;k<j;k++)
//{
// cout<<v2[k]<<" ";
//}
return 0;
}
求积
#include<bits/stdc++.h>
using namespace std;
int main()
{
vector<int>v1;
vector<int>::iterator iter1;
int i;
for(i=1;i<11;i++)
{
v1.push_back(i);
}
int ptotal;
ptotal=accumulate(v1.begin(),v1.end(),1,multiplies<int>());
cout<<ptotal<<endl;
return 0;
}
求前n项的积
在这里插入代码片
max_element和min_element
max_element和min_element用来求vector或数组的最大值最小值,返回的是迭代器或指针,可以用*来获取值。
数组
#include<bits/stdc++.h>
using namespace std;
int main()
{
int a[]={3,6,8,2};
int len=sizeof(a)/sizeof(int);
//求出数组a的长度
cout<<*max_element(a,a+len)<<endl;
cout<<max_element(a,a+len)<<endl;
cout<<*min_element(a,a+len)<<endl;
cout<<min_element(a,a+len)<<endl;
return 0;
}
vector容器
#include<bits/stdc++.h>
using namespace std;
int main()
{
vector<int>v;
v.push_back(7);v.push_back(4);
v.push_back(2);v.push_back(9);
cout<<*max_element(v.begin(),v.end())<<endl;
cout<<*min_element(v.begin(),v.end())<<endl;
return 0;
}
注意:vector数组时,不能输出指针地址,只能输出指针的值。
string和int相互转换
string转换为int
这个是把string转化为char p再转化为int
string str;
const char*p=str.c_str();
int i=atoi(p);
这个直接把string转化为int,更方便
string str;
int i=stoi(str);
int转换为string
int n;
string s=to_string(n);
stoi,stoll,stof,stod
stoi将string转化为int
stoll将string转化为long long
stof将string转化为float
stod将string转化为double
用法见上个标题
char和string
- char是字符型变量,string是字符串型变量,字符串是由各个字符组成的,char默认最后一位是“\0”,而string没有这个默认。
- 字符用单引号‘ ’,字符串用双引号“ ”。
- 如果只写字符数组,代表的其实是该字符数组的首地址。
- 用占位符时,“&d”为int类型,“&s”为字符串类型,“&c”为字符类型.
?:三目运算符
真的超级方便超级好用的运算符!!!
用法:表达式1?表达式2:表达式3
如果表达式1为真,则执行表达式2,否则执行表达式3
但是在具体操作时应注意运算的优先级,<<的优先级是大于?的,所以在使用时记得加括号加括号!!
cout<<((grade < 60) ? "fail" : "pass");//输出pass或者fail
cout<<(grade < 60 ) ? "fail" : "pass" ;//输出0或者1
cout<<grade < 60 ? "fail" : "pass" ; //错误的,这个代码试图比较cout和60
上面代码中第二条语句等价于:
cout<<(grade < 60 ) ? "fail" : "pass" ;//输出0或者1
//等价于:
cout<< (grade < 60 ) ;//输出0或者1 (0表示真,1表示假)
cout ? "fail" : "pass" ; //根据cout的值是真还是假产生对应的字面值
上面代码中第三条语句等价于:
cout<<grade < 60 ? "fail" : "pass" ; //错误的,这个代码试图比较cout和60
//等价于:
cout<< grade ; // 小于运算符的优先级低于移位运算符,所以先输出grade
cout << 60 ? "fail" : "pass" ;//比较cout和60错误的
ASCII相加减
用来处理字符串中的数字超级方便
string s="123456";
int i=s[4]+'0';
int j=s[5]-'2';
这里的加减实际上是ASCII码的相加减,i就等于5(理解为5+0),j等于4(理解为6-2),这样就超级方便啦,不用像本篇上面所做笔记将string转化为char再利用atoi转化为int。不过只限于单个位的好像…
字符串一些函数
isalpha
真就返回1,否则返回0
toupper和tolower
顾名思义,就是转化为大写和小写,用在单个字符这个维度
do while
可以用来表示至少执行一次,先执行再判断
do
循环语句;
while(表达式);
//while后面有分号