C++语法基础(1)

目录

  • 变量,输入输出语句
    • 变量的定义
    • 输入输出语句
  • 判断语句
    • 基本if-else语句
    • 常用比较运算符
    • else if 语句
    • 条件表达式
    • 时间间隔计算总结
  • 循环语句
    • for循环
    • while 循环
    • do while 循环
    • continue 和 break
    • 嵌套循环
    • 打印菱形:曼哈顿距离
  • 数组
    • 数组的初始化
    • 访问数组
    • 旋转数组
    • 多维数组定义与访问
    • memset初始化 memcpy复制
  • 字符串
    • 字符与整数的联系:ASCII码
    • 字符数组
      • 字符数组的定义:
      • 字符数组的输入输出
      • 获取整行字符
      • 字符数组的常用操作
      • 遍历字符数组:
    • string
      • string 的定义
      • string 的读入和输出
      • string 的常用操作
      • 遍历处理string对象

变量,输入输出语句

一个C++程序的大致结构如下
C++语法基础(1)_第1张图片

变量的定义

变量类型:
bool: true/false 大小为1Byte
char:单引号引起的字符,大小为1Byte
int:范围-231~231-1的整数,大小为4Byte
float精度6-7位有效数字的整数,大小为4Byte
double精度14-15位有效数字的浮点数,大小位8Byte

long long:范围-263~263-1的整数,大小为8Byte
long double精度18-19位有效数字的浮点数,大小为16Byte

变量定义:

int a,b = 2, c = 2;
float d = 1.5, e = 1, f = 1.2345e2;
bool g = true, h = false;
char i = 'a',j = 'j';

long long l = 12345678987654321LL;   
long double m = 123.45;

输入输出语句

cincout输入输出语句:

cin >> a >> b;  //输入语句
cout << a+b <<' ' << a*b << endl;  //输出语句

scanf,printf输入输出语句

#include 
#include 
using namespace std;

int main()
{
	int a,b;
	scanf("%d%d",&a,&b);  //输入语句
	printf("a*b=%d\na*b=%d",a+b,a*b);   //输出语句
	printf("a*b=%.2f")
	return 0;
}

cinscanf的区别:
cin可以跳过空格,scanf会读入空格,cin执行效率低,scanf执行效率高

类型转换:
运算过程中,精度低的会转化为精度高的

tips:
1.做算法用浮点数时,建议用double,精度高
2.保留有效几位小数,用printf
3.整数,浮点数混在一起乘除,注意整数之间的除法会不会变成整除

using namespace std的作用:

常用头文件:iostream cstring algorithm

printf格式化输出:

#include 

using namespace std;

int main()
{
	int a = 1;
	int b = 12;
	int c = 123;
	printf("%5d\n",a);   //字长为5,右对齐,补齐加空格 
	printf("%-5d\n",b);  //字长为5,左对齐,补齐加空格 
	printf("%05d\n",c);   //字长为5,补齐加0字符 
	return 0;
}

判断语句

基本if-else语句

#include 

using namespace std;

int main()
{
	int score;
	cin >> score;
	if(score>60)		cout << "及格" << endl;
	else				cout << "不及格" << endl;
	return 0;
}

if else 条件下只有一条语句,可以不加括号,否则要加

常用比较运算符

(1) 大于 >
(2) 小于 <
(3) 大于等于 >=
(4) 小于等于 <=
(5) 等于 ==
(6) 不等于 !=

else if 语句

#include 

using namespace std;

int main()
{
	int grade;
	cin >> grade;
	if(grade>=85)		cout<<'A'<<endl;
	else if(grade>=75)	cout<<'B'<<endl;
	else if(grade>=60)	cout<<'C'<<endl;
	else				cout<<'D'<<endl;
	return 0;
}

条件表达式

与: &&
或 :||
非: !

转移字符:
\n 换行 \' 单引号字符 \"双引号字符 %%字符串中显示%

时间间隔计算总结

AcWing668 游戏时间2
给出两个时间点,计算出间隔的时间数
思路:
将两个时间换算成距离0点0分的分钟数在计算,若结束时间大于开始时间,则间隔的分钟数=结束时间对应的分钟数-开始时间对应的分钟数
若结束时间小于开始时间,说明经过了一天,则间隔的分钟数=结束时间对应的分钟数+1440(一天的分钟数)-开始时间对应的分钟数

题解代码:

#include 
#include 

using namespace std;
int main()
{
	int a,b,c,d;
	cin >> a >> b >> c >> d;
	
	int x = a*60+b;   //开始时间对应的分钟数
	int y = c*60+d;   //结束时间对应的分钟数
	
	if(y>x)			 printf("O JOGO DUROU %d HORA(S) E %d MINUTO(S)",(y-x)/60,(y-x)%60);
	else			 printf("O JOGO DUROU %d HORA(S) E %d MINUTO(S)",(y+1440-x)/60,(y+1440-x)%60);
	return 0;
}

循环语句

for循环

把控制循环次数的变量从循环体中剥离,基本结构如下:
for (init-statement : condition: expression)
{
statement
}
init-statement可以是声明语句、表达式、空语句,一般用来初始化循环变量;
condition 是条件表达式,和while中的条件表达式作用一样;可以为空,空语句表示true
expression 一般负责修改循环变量,可以为空

#include 
#include 

using namespace std;
int main()
{
	for(int i=1;i<=10;i++)
	{
		cout << i << endl;    //输出1-10
	}
	return 0;
}

while 循环

循环版的if语句。If语句是判断一次,如果条件成立,则执行后面的语句;while是每次判断,如果成立,则执行循环体中的语句,否则停止。

#include 
#include 

using namespace std;
int main()
{
	int i = 1;
	while(i<=10)
	{
		cout << i << endl;  //输出1-10
		i++;
	}
	return 0;
}

do while 循环

do while语句与while语句非常相似。唯一的区别是,do while语句限制性循环体后检查条件。不管条件的值如何,我们都要至少执行一次循环。

#include 
#include 

using namespace std;
int main()
{
	int i = 0;
	do
	{
		i++;
	}while(i<0);
	
	cout << i << endl;  
	
	int j = 0;
	while(j<0)
	{
		j++;
	}
	cout << j << endl;  //两个都不满足条件,但是do while先执行了一次
						//所以i=1,j=0 
	return 0;
}

continue 和 break

break:可以提前从循环中退出,不再执行循环体内的语句
continue:跳到下次循环的开头,不执行循环体内该次循环这条语句后的语句

嵌套循环

打印n阶方阵

#include 
#include 

using namespace std;
int main()
{
	int n;
	cin >> n;
	
	for(int i=0,k=1;i<n;i++)
	{
		for(int j=0;j<n;j++,k++)
		{
			cout << k << " " ;
		}
		cout << endl;
	}
	return 0;
}

打印菱形:曼哈顿距离

曼哈顿距离:把两个点坐标的 x 坐标相减取绝对值,y 坐标相减取绝对值,再加和
c = ∣ x 1 − x 2 ∣ + ∣ y 1 − y 2 ∣ c=|x1-x2|+|y1-y2| c=x1x2+y1y2
思路:观察n阶菱形中点的坐标,发现每个点到中心点的曼哈顿距离都小于 ⌊ n 2 ⌋ \lfloor\frac{n}{2}\rfloor 2n

#include 
#include 
#include 

using namespace std;
int main()
{
	int n;
	cin >> n;
	
	int cx = n/2,cy = n/2;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			if((abs(i-cx)+abs(j-cy))<=n/2)		cout << "*";
			else								cout << " ";	
		}
		cout << endl;
	}
	return 0;
}

数组

数组的初始化

	int a[3] = [0,1,2];  //定义一个长度为3的数组
	int b[3] = {0,1,1};	 //定义一个长度为3的数组
	
	int c[5] = {0,1,2};  //等价与{0,1,2,0,0}空缺的元素默认用0补全
	char d[] = {'a','b','c'}; 

函数内部定义的数组都是随机赋值的,且数组存储与栈内存中,大小有限制,约为1M
而函数外部定义的数组都初始化为0,且存储在堆内存中,大小可以很大(受内存限制),因此定义较大的数组一般放在函数外面

访问数组

#include 

using namespace std;
int main()
{
	int n,m;
	cin >> n >> m;
	
	int a[n];
	for(int i=0;i<n;i++)		cin>>a[i];
	for(int i=0;i<n;i++)		cout << a[i] << " ";
	return 0;
}

旋转数组

Leecode 189 旋转数组
暴力解法:
旋转一次前,记录下数组的最后一个元素为temp,之后把所有的元素都往后移一个单位,再在空出的第一个位置填上temp

代码如下:

#include 
using namespace std;
int main()
{
	int n,m;
	cin >> n >> m;
	
	int a[n];
	for(int i=0;i<n;i++)		cin>>a[i];
	
	for(int i=0;i<m;i++)
	{
		int temp=a[n-1];
		for(int j=n-1;j>0;j--)		a[j]=a[j-1];
		a[0] = temp;
	}
	for(int i=0;i<n;i++)		cout << a[i] << " ";
	return 0;
}

优化解法:
以数组【1,2,3,4,5】,旋转2次为例

操作 数组
初始状态 【1,2,3,4,5】
目标状态 1,23,4,5
①将整个数组翻转 5,4,3,2,1
②将对应的前半部分数组翻转 4,5,3,2,1】
③将后半部分数组翻转 【4,5,1,2,3

代码如下:

#include 
#include 

using namespace std;
int main()
{
	int n,k;
	cin >> n >> k;
	
	int a[n];
	for(int i=0;i<n;i++)		cin>>a[i];
	
	reverse(a,a+n);
	reverse(a,a+k);
	reverse(a+k,a+n);
	
	for(int i=0;i<n;i++)		cout << a[i] << " ";
	return 0;
}

多维数组定义与访问

#include 

using namespace std;
int main()
{
	int a[3][4]={{0,1,2,3},		//定义一个三行四列的数组 
				{4,5,6,7},
				{8,9,10,11}};
				
	for(int i=0;i<3;i++)
	{
		for(int j=0;j<4;j++)
		{
			cout << a[i][j] << " ";
		}
		cout << endl;
	}
	return 0;
}

memset初始化 memcpy复制

需要先调用cstring头文件
memset: memset是以字节为单位,初始化内存块。
初始化数组时,格式如下
memset(数组名, 0, sizeof 数组名); // 初始化为全零数组
memcpy:内存拷贝函数,从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中,格式如下:
memcpy(拷贝目的数组, 拷贝原数组, sizeof 原数组);

#include 
#include 

using namespace std;
int main()
{
	int a[10],b[10];
	for(int i=0;i<10;i++)  a[i]=i;     //a=[0,1,2,3,4,5,6,7,8,9] 
	
	memcpy(b,a,sizeof a);   //复制a数组到b数组 
	memset(a,0,sizeof a);   //初始化a数组 
	
	for(int i=0;i<10;i++)		cout << b[i] << " ";
	cout << endl;
	for(int i=0;i<10;i++)		cout << a[i] << " ";
	return 0;
}

练习题:
Acwing 754 平方矩阵II
Acwing 756 蛇形矩阵

字符串

字符与整数的联系:ASCII码

每个常用字符都对应一个-128~127的数字,二者之间可以相互转化

#include 

using namespace std;

int main()
{
	for(int i=1;i<128;i++)  	printf("%d: %c\n",i,(char)i); 
	
    return 0;
}

常用ASCII值:’A’-‘Z’ 是65~90,’a’-‘z’是97-122,’0’-‘9’是48-57。
字符可以参与运算,运算时会将其当做整数:

字符数组

字符数组的定义:

#include 

using namespace std;

int main()
{
	char a1[] = {'c','+','+'};       //列表初始化,没有结尾\0空字符 
	char a2[] = {'c','+','+','\0'};  //列表初始化,有结尾\0空字符 
	char a3[] = "c++";               //自动添加\0空字符 
	
	cout << sizeof a3 << endl;      //a3长度为4,后面自动补上\0 
	
    return 0;
}

字符数组的输入输出

cin输入 cout输出

	char a[100],b[100];
	cin >> a;                //cin读入 
	scanf("%s",b);           //scanf读入,注意:不要加取地址符 
	cin >> a+1;      //从下标1开始存

输出:cout printf,puts:

#include 

using namespace std;

int main()
{
	char a1[] = "ABCDEFG";             //定义字符串 
	
	cout << a1 << endl;      //cout 输出
	printf("%s\n",a1); 		//printf("%s")输出
	puts(a1);
	cout << a1+1 << endl;   
	printf("%s\n",a1+1);    //a1+1表示从B开始输出
	
    return 0;
}

cin scanf 都是遇到空格,回车就停止了

获取整行字符

fgets():可读入到字符数组中,fgets(字符数组名,读取长度,stdin)

注意:fgets()会把回车读进来

	char a[100],b[100];
	fgets(a,100,stdin);

getline():读到string里,getline(cin,读入的string变量名)

	string s;
	getline(cin,s);

字符数组的常用操作

strlen() strcmp() strcpy()

#include 
#include  

using namespace std;

int main()
{
	char a[100],b[100]; 
	cin >> a;
	
	strcpy(b, a);        					//将字符串b复制给从a开始的字符数组。
	
	cout << strlen (a) << endl;   			//strlen (a)  返回a的字符串长度
	cout << strcmp(a,"abc") << endl;		//strcmp(s1,s2)   string compare 比较两个字符串的大小,
											//a < b 返回-1,a == b 返回0,a > b返回1。这里的比较方式是字典序!
	cout << b << endl;  					//复制的b 
	
    return 0;
}

遍历字符数组:

#include 
#include  
#include 
using namespace std;

int main()
{
	char a[100]; 
	cin >> a;
	
	for(int i=0,len = strlen(a);i<len;i++)		cout << a[i] << endl;
	
    return 0;
}

string

string 的定义

#include 

using namespace std;

int main()
{
	string s1;    			//默认初始化为一个空字符串 
	string s2 = "ABCD";     //s2设为值为ABCD的字符串 
	string s3 = s2;			//将s2复制给s3 
	string s4(10,'c');      //s4为10个c 
    return 0;
}

string 的读入和输出

string能用cin读入,不能用scanf读入
string可以用cout,printf输出

string 的常用操作

#include 
#include 

using namespace std;

int main()
{
	string s1 = "abc",s2 = "abcd";
	
	cout << s1.empty() << endl;   //返回string是否为空
	cout << s1.size() << endl;	 //返回string的长度
	
	cout << s1>s2 << endl;      //string 的比较  支持 > < >= <= == !=等所有比较操作,按字典序进行比较。
	
	string s3 = s1+s2;
	cout << s3 << endl;			//两个string对象相加 
								//s3的值为abcabcd 
	return 0; 
}

注意:
字面值和string对象相加:
做加法运算时,字面值和字符都会被转化成string对象,因此直接相加就是将这些字面值串联起来:

	string s1 = “hello”, s2 = “world”;		// 在s1和s2中都没有标点符号
	string s3 = s1 + “, “ + s2 + ‘\n’;

当把string对象和字符字面值及字符串字面值混在一条语句中使用时,必须确保每个加法运算符的两侧的运算对象至少有一个是string:

string s4 = s1 + ", ";	// 正确:把一个string对象和有一个字面值相加
string s5 = "hello" +", "; // 错误:两个运算对象都不是string
string s6 = s1 + ", " + "world";  // 正确,每个加法运算都有一个运算符是string
string s7 = "hello"+ ", " + s2;  // 错误:不能把字面值直接相加,运算是从左到右进行的

substr()取出字串的函数:
s.substr(p, len)
返回一个string,包含s中从p开始的len个字符的拷贝(pos的默认值是0,n的默认值是s.size() - len,即不加参数会默认拷贝整个s)
另外,若len的值超过了string的大小,则substr函数会抛出一个out_of_range异常;若pos+n的值超过了string的大小,则substr会调整n的值,只拷贝到string的末尾

遍历处理string对象

可以将string对象当成字符数组来处理

#include 
#include 
using namespace std;

int main()
{
	string s1 = "Hello World";
	for(int i =0;i<s1.size();i++)		cout << s1[i] << endl; //for遍历string 
	

	for(char c: s1)		cout << c << endl;        //for(遍历的赋值变量:string 对象名) 
												 //等价于for(int i =0;i
	for(char &c:s1)		c='0';   				//加上&,可以对源string进行修改操作 
	cout << s1 << endl; 
	
	return 0;
}

stringstream
把字符串初始化为一个类似于cin的方式,从中读出需要的信息

#include 
#include 

using namespace std;
int main()
{
    string s;
    getline(cin,s);
    
    int a,b;
    double c;
    string str;
    stringstream ssin(s);       //把str转化为stringstream类型 

	ssin >> a >> b >> str >> c ;		

	cout << a << endl << b << endl << str << endl << c << endl;
    
    return 0;
}

练习题:
Acwing 770 单词替换
Acwing 771 字符串中最长的连续出现的字符
Acwing 777 字符串的乘方
Acwing 778 字符串最大跨距
Acwing 779 最长公共字符串后缀

你可能感兴趣的:(算法学习,算法,c++)